gem install flowerbox
flowerbox plant jasmine
flowerbox spec/javascripts
flowerbox plant cucumber
flowerbox js-features
jasmine-gem
or jasmine-headless-webkit
flowerbox transplant spec/javascripts
flowerbox spec/javascripts
# in spec/javascripts/spec_helper.rb
require 'haml-sprockets'
Flowerbox.configure do |c|
c.asset_paths << "app/assets/javascripts"
c.asset_paths << "vendor/assets/javascripts"
c.additional_files << "applications.js.coffee"
# ... other stuff ...
end
Flowerbox.configure do |c|
c.run_with :chrome
end
# make sure node and npm are in your path
# jsdom and ws get installed in your project under node_modules
Flowerbox.configure do |c|
c.run_with :node
end
# make sure you bind your global things to this
class @MyCoolClass extends @MyBaseClass
cool: -> "yeah man"
No, I knew you'd ask. Read the long bit of text below. tl;dr: Selenium with Chrome is pretty much the same setup, just as fast, and gives you stack traces and other debugging assistance.
# js-features/features/my_cool_thing.feature
Feature: My Cool Thing
Scenario: Show a cool thing
Given I have a cool thing
And I have a cool thing viewer
When I render the viewer
Then I should see the cool thing in the viewer
@wip # <= tags work, too!
Scenario: Maybe do something else
Given something
When yadda
Then BAM
# js-features/steps/given/i_have_a_cool_thing.js.coffee
Flowerbox.Given /^I have a cool thing$/, ->
@data =
one: 'two'
three: 'four'
@coolThing = new CoolThing(@data)
# js-features/steps/given/i_have_a_cool_thing_viewer.js.coffee
Flowerbox.Given /^I have a cool thing viewer$/, ->
@coolThingViewer = new CoolThingViewer(@coolThing)
# js-features/steps/when/i_render_the_viewer.js.coffee
Flowerbox.When /^I render the viewer$/, ->
@coolThingViewer.render()
# js-features/steps/then/i_should_see_the_cool_thing.js.coffee
Flowerbox.Then /^I should see the cool thing in the viewer$/, ->
@expect(
@coolThingViewer.$('input[name="one"]').val()
).toEqual(@data.one)
@expect(
@coolThingViewer.$('input[name="three"]').val()
).toEqual(@data.three)
# js-features/support/env.js.coffee
#
#= require ../steps
Flowerbox.World ->
@Before (callback) ->
@something = 'is available everywhere'
callback()
@After (callback) ->
Put = 'some stuff back'
callback()
# js-features/spec_helper.rb
Flowerbox.configure do |c|
c.report_with :verbose
c.reporters.add(
:step_writer,
:target => 'js-features/step_definitions',
:on_finish => lambda { |dir| system %{open #{dir}} }
)
end
So I (John) have been in this JavaScript testing game for a while, and, after about three years of doing JS testing for Web apps, decided to finally take all the knowledge I had and make something that was dead-simple to use.
jasmine-headless-webkit
was my first attempt, but it's a C++/Qt mess. Downloading all of
Qt is a total pain. Also, Qt4's JavaScript engine, JavaScriptCore, doesn't have stack trace
support, so it got pretty useless for me for bigger, messy projects (looking at you, Backbone).
Qt5 has V8, but whatever, I just decided to ditch the whole
compiling software thing and replace it with running tests in Selenium and/or node.js.
Sure, spinning up that instance of Firefox or Chrome is slower than starting up a small QtWebKit widget, but there's a lot less that can go wrong when using a full-blown browser. This also means your CI server config stays leaner. You may already have Qt installed for capybara-webkit, but one less thing depending on Qt just makes your life (and mine) easier.
Also, when running Flowerbox with Guard, your browser stays open between test runs, so you only pay the startup penalty once.
And, if you write everything correctly, you can just run your tests on node.js and not even have to worry about a browser.
I changed my mind. As long as I'm not testing for browser-only things, like CSS interaction or position elements, running tests on node.js with a browser-like DOM provided by jsdom really is good enough. I use full-blown Ruby Cucumber if I need to test more complex browser things.
Yeah, and it's slow. I'll carve out what I can in Cucumber.js while I work on Ruby Cucumber features. Makes the process of getting those complex integration tests written a lot faster.
Also, I've changed my views on unit testing as a process. Unit testing for me is now about two things:
Treating unit testing this way taught me how to better organize and design my code, and I only use it for really testing code when I need to test those big blobs of things. This is my opinion, YMMV, Flowerbox lets you do what you want. Never use Cucumber.js support if you don't want to. Write your integration bits in Jasmine. I don't mind.