Pivotal Labs

Main menu

Skip to primary content
Skip to secondary content
  • About
  • Case Studies
  • Team
    • Executives
    • Locations
      • San Francisco (HQ)
      • Boston
      • Boulder
      • Denver
      • London
      • Los Angeles
      • New York
  • Community
    • Blogs
    • Tech Talks
    • Events
  • Careers
    • Lifestyle
    • Principles & Practices
    • Benefits
    • FAQ
    • Apply
  • Tools
  • Contact
    • Press Room
    • Press Releases
    • In The News
    • Press Kit
  • All
  • Labs
  • Standup
  • Tracker
Pivotal Labs

Shared Behaviors in Screw.Unit or how to DRY up your javascript specs

Pivotal Labs
Thursday, August 27, 2009

The project that I’m working on is using Screw.Unit for Javascript testing. We recently ran into a case where we found ourselves copying and pasting some code. We wanted to DRY up our specs and found a neat way to do it that I figured I’d share with everyone. Here’s a really simple example to demonstrate how we did it.

Given a cat model that keeps track of the number of lives the cat has left:

function Cat() {
    var lives = 9;
    this.die = function(num) {
        lives = lives - 1
    };
    this.lives = function(){
        return lives;
    };
    this.isDead = function() {
        return lives <= 0
    };
}

Lets make up a spec that checks that isDead works for some values of lives:

Screw.Unit(function() {
    describe('Cat', function() {
        var cat;
        describe('isDead', function(){
            var shouldNotBeDeadBehavior = function(num){
                describe("when the cat has " + num + " lives left", function(){
                    it("it should not be dead", function(){
                        cat = new Cat({lives: num});
                        expect(cat.isDead()).to(be_false);
                    });
                });
            }

            for (i=3;i>0;i--){
                shouldNotBeDeadBehavior.call(Screw.Specification, i);
            }

            describe("when the cat has 0 lives left", function(){
                it("it should be dead", function(){
                    cat = new Cat({lives: 0});
                    expect(cat.isDead()).to(be_true);
                });
            });
        });

    });
});

The neat part in here is the line:

shouldNotBeDeadBehavior.call(Screw.Specification, i);

If you’re not familiar with it, the call function in javascript allows you to define what “this” is for that function call. By calling our shared behavior with Screw.Specification, we’re saying that we want to execute this function within the context of the Screw.Unit Specifications. This lets us execute our specs as though they were written in various places. The test results from this spec look like this
screw unit screenshot

This is one way to DRY up some of your Screw.Unit specs. If you find yourself copying and pasting code, consider refactoring the spec out into a shared behavior instead.

Have other good ways to clean up Srew.Unit specs? Share them in the commments!

  • 0 Shares
  • Share on Facebook
  • Share on Twitter
David Stevenson

Standup 08/24/2009: How do you redefine css classes in javascript?

David Stevenson
Monday, August 24, 2009

Ask for Help

“How do I redefine a CSS class in javascript”

You can create a new <style> element and append it to the head. This should probably be avoided if you can help it.

If you simply want to toggle between 2 states, consider putting both sets of rules in the CSS and toggling a class on the body or other container.

*”Should I use BOSH for XMPP on the iPhone?”

Probably not. If you have a long-running low latency XMPP connection, you’ll probably want to use a socket from the CFNetwork package. That’s the most we know about iPhone development right now.

Interesting Things

  • New tracker updates with better burndown charting!
  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Edward Hieatt

Webcast: Unit testing with the Palm Mojo SDK

Edward Hieatt
Friday, July 10, 2009

Next Tuesday, July 14, at 10pm PST, Chris Sepulveda from Pivotal Labs will be broadcasting an O’Reilly WebCast on automated unit testing with the Palm Mojo SDK. Developer testing is at the heart of Pivotal Labs’s development practices, and we’re excited to be involved in bringing testing to Mojo development. The WebCast will cover the following:

  • Introduce BDD & Jasmine
  • Installing Jasmine & add related code to the app to support BDD
  • Discuss how to write a failing test first, then add functionality to make a test pass
  • Develop a simple webOS application test first, with the Mojo SDK

There’s more information about the WebCast on webOSHelp.net.

Date: Tuesday, July 14th at 10 am PT
Price: Free
Duration: Approximately 60 minutes
To register: http://oreilly.com/go/palmmojo

  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Joe Moore

Standup 06/26/2009: Poor ScrewUnit…

Joe Moore
Friday, June 26, 2009
  • JQuery Events/live + ScrewUnit = :-(. ScrewUnit swaps the DOM “out from under” the elements that Events/live is watching, which messes with ScrewUnit. Call die on the DOM elements that live events are watching.

  • ScrewUnit + CI + IE = :’-( Also, When ScrewUnit suites become large, they trigger IE’s “slow script” warning, which can freeze your continuous integration build. Check out the Registry Hack to set your own timeout.

  • We have a fan of Thor in the house: “Map options to a class. Simply create a class with the appropriate annotations, and have options automatically map to functions and parameters.” Which, as is (not) obvious, indicates that Thor is a replacement for rake.

  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Joe Moore

Standup 06/23/2009: Multi-table Inheritance?

Joe Moore
Tuesday, June 23, 2009

Ask for Help

“Has anyone implemented mutli-table (class table) inheritance in Rails, as apposed to single table inheritance (STI)?”

  • There are some plugins that nobody has tried, such as inherits_from
  • What about a view to represent the super set of tables and rows?

“We’re looking for a dead-simple, drop-in JS rating or ‘starting’ plugin.”

Check out the start-rating jQuery plugin. Any other suggestions?

  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Pivotal Labs

Standup 3/27/2009: Gem repo forked?

Pivotal Labs
Friday, March 27, 2009

Interesting Things

  • IE doesn’t allow you to change the type of an input. If you create an input with createElement, IE will not allow you to change that element to a button. This was discovered when a project’s javascript dom builder code was modified to generate inputs of type=button rather than type=submit. The cross-browser solution was to create some other temporary dom element such as a div and then set the innerHtml of that element to a type=button input, then extract that child element and return it in the builder call. Yeah!

Ask for Help

“What’s the best way to get gems for forked repos?”

There was quite a discussion on this. The specific issue is that the team is trying to use Compass (Chris Eppstein gave a talk on Compass at Pivotal on 3/18-look for the future video on our Talks Page.) For the moment, since compass depends on the edge version of sass you must first manually install sass before installing the compass gem.

  • One suggestion was to submit a fix for the gem. This is not a good solution in this case since the new version of sass/haml is expected to be released soon, fixing compass and simplifying its installation.
  • Pivotal will likely host its own internal gem server at some point to deal with issues like this.
  • The Has My Gem Built Yet? service might be useful in some situations, but not for this specific problem.
  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Pivotal Labs

Standup 3/25/2009: Branches + JSUnit + CI + IE = :-(

Pivotal Labs
Wednesday, March 25, 2009

Interesting Things

  • Branches + JsUnit + CI + IE = :-( : Apparently it is difficult to manage IE’s cache in CI. One project apparently has a bat file on CI that clears the cache every 30 minutes. Another team solved this by making the cache directory read only. Often browser/OS combinations have some technique for disabling caching.
  • Test Swarm Alpha: this is a crowd sourced javascript testing solution (think seti@home for javascript testing) being developed by John Resig.

Ask for Help

“AR attribute appears to be skipped by text field helper?!” Apparently the model method is bypassed by the text field helper if a column of the same name is present in the underlying table. This was experienced in Rails 2.2.

Others have apparently experienced this in the past but a clear answer did not surface.

  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Pivotal Labs

Standup 3/24/2009: Browser History with Javascript and Page Based Json

Pivotal Labs
Tuesday, March 24, 2009

Interesting Things

  • Browser History with Javascript and Page Based Json: One of our projects solved the vexing problem of browser history for a page that has initial page provided json with subsequent ajax updates. A simple page back operation will display the originally downloaded data, not the updated data. The solution is to add a unique id for each page, and store these ids in a cookie. When an ajax request updates the page it removes its page id from the cookie. When you use the back button, each page checks to see if its unique id is in the cookie, and if it is not, it forces a reload.
    Really Simple History was mentioned as another way to manage javascript/ajax history.
  • Rubymine Build 784 has the Weirdest. Bug. Ever.: This may only be a problem if you work on a mac and you need to enter capital letters in rubymine dialogs like find and replace ;-). Many of us are fans of intellij/rubymine, but we wish they had a better test process. To be fair, rubymine is in public preview, so expect the occasional bug or two.
  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Pivotal Labs

Run JavaScript in Selenium tests. Easily.

Pivotal Labs
Thursday, March 5, 2009

Here’s the gist of this post: gist.github.com/58876

Ever since I’ve started using Webrat, a lot of the pain of Selenium has gone away
for me. There’s still a little bit of pain though. Part of it is caused by the fact
that it’s harder than it should be to just execute arbitrary bits of JavaScript in
in your current window under test. Well no more. Here’s a helper:

module SeleniumHelpers
  # Execute JavaScript in the context of your Selenium window
  def run_javascript(javascript)
    driver.get_eval <<-JS
      (function() {
        with(this) {
          #{javascript}
        }
      }).call(selenium.browserbot.getCurrentWindow());
    JS
  end

  private

  # If running in regular Selenium context, get_eval is defined on self.
  def driver
    respond_to?(:selenium) ? send(:selenium) : self
  end
end

To use it with Cucumber, do like so:

World do |world|
  world.extend(SeleniumHelpers)
  world
end

To use it with POS, do like so:

class JavaScriptHelperTest < SeleniumTestCase
  include SeleniumHelpers

  # your tests go here...
end

Now what?

Now to run JavaScript in your Selenium window, just call run_javascript. Note
that it’s always going to return a String, so you may have to massage the output
a tad:

checked_boxes_count = run_javascript <<-JS
  jQuery('input[type=checkbox]:checked').size();
JS

checked_boxes_count         # => "3"
checked_boxes_count.to_i   # => 3

Cooler stuff

While Webrat’s DSL for traversing web apps is awesome, I’ve always found the
alternatives (Polonium for example) to not jive well with how I think. They’re
way better than talking directly to Selenium, you’re still locked in to a certain
style. The run_javascript helper makes it easier to write your own helpers that
fit your own style.

module ElementHelpers
  class Element
    def initialize(context, selector)
      @context, @selector = context, selector
    end

    def hide!
      call(:hide)
    end

    def show!
      call(:show)
    end

    def visible?
      call(:is, ':visible') == 'true'
    end

    private

    def call(fn, *args)
      @context.run_javascript <<-JS
        return jQuery(#{@selector.inspect})[#{fn.to_s.inspect}](#{args.map(&:inspect).join(', ')});
      JS
    end
  end

  def locate(selector)
    Element.new(self, selector)
  end
end

Now you can write your tests like so:

class JavaScriptHelperTest < ActiveSupport::TestCase
  include SeleniumHelpers
  include ElementHelpers

  def setup
    @element = locate('#all')
  end

  def test_visible_by_default
    assert @element.visible?
  end

  def test_hide_element
    @element.hide!
    assert ! @element.visible?
  end

  def test_show_element
    @element.hide! # setup
    @element.show!
    assert @element.visible?
  end
end

Credit should go to Brian Takita, since he did most of the hard work and I just wrote a method. Let me
know if you have any issues or ideas with the helper, and may all your tests be green.

  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Pivotal Labs

Standup 11/12/2008: JSON2.js borked?

Pivotal Labs
Thursday, November 13, 2008

Interesting Things

  • JSON version 2 has problems with its JavaScript implementation json2.js, specifically when calling JSON.stringify() on arrays:

    // JSON version 1
    [1] => "[1]"
    
    
    // JSON version 2
    [1] => ""[1]""
    

    We’re not sure if this is a bug or a feature. We’re sticking with JSON version 1 until further notice.

  • Pivot Adam has a very interesting blog post about functors called Give up the func. Check it out!

Ask for Help

“We were having problems when mocking an ActiveRecord association under Mocha when we called expects on a method that calls a method.”

The solution was basically to not mock associations.

“Mod_rewrite + SSL was causing problems when redirecting to a subdomain behind SSL.”

A wild-card SSL certificate solves the problem.

  • 0 Shares
  • Share on Facebook
  • Share on Twitter

Topics

  • agile (783)
  • rails (117)
  • testing (90)
  • ruby (86)
  • ruby on rails (71)
  • jobs (62)
  • javascript (59)
  • techtalk (44)
  • ironblogger (42)
  • rspec (39)
  • bloggerdome (34)
  • productivity (34)
  • activerecord (30)
  • rubymine (30)
  • git (29)
  • gogaruco (29)
  • nyc (27)
  • design (24)
  • mobile (23)
  • pivotal tracker (22)
  • process (21)
  • cucumber (21)
  • jasmine (19)
  • ios (18)
  • tracker ecosystem (17)
  • webos (17)
  • objective-c (17)
  • fun (16)
  • android (16)
  • palm (16)
  • ci (16)
  • "soft" ware (16)
  • bdd (15)
  • tdd (15)
  • cedar (15)
  • rails3 (14)
  • performance (14)
  • css (14)
  • gem (13)
  • mouse-free development (12)
  • selenium (12)
  • goruco (12)
  • bundler (12)
  • api (12)
  • keyboard (11)
  • meetup (11)
  • railsconf (11)
  • nyc-standup (11)
  • capybara (10)
  • mac (10)
Subscribe to javascript Feed
  1. ←
  2. 1
  3. 2
  4. 3
  5. 4
  6. 5
  7. 6
  8. →
  • About
  • Case Studies
  • Team
  • Community
  • Careers
  • Tools
  • Contact
  • Labs
  • Events

Contact Us

contact@pivotallabs.com
+1 415-77-PIVOT
TwitterLinkedInFacebook

Pivotal Tracker

Tracker is the award-winning agile project management tool that enables real-time collaboration around a shared, prioritized backlog.
Visit pivotaltracker.com >