Flowerbox

A multi-environment, multi-runner, super-easy JavaScript testing framework framework.


Super-fast unit testing getting started super guide!

(you need Firefox at the very least)

gem install flowerbox
flowerbox plant jasmine
flowerbox spec/javascripts

...and what about integration testing?

(whoa nelly, pure JS Cucumber?)

flowerbox plant cucumber
flowerbox js-features

Hey, I'm already using jasmine-gem or jasmine-headless-webkit

(you're smart!)

flowerbox transplant spec/javascripts
flowerbox spec/javascripts

I use Sprockets and need to configure asset paths and templates and stuff!

(...may the force be with you...)

# 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

Firefox is so 2008. Can I run my tests on Chrome?

(we like Selenium here!)

Flowerbox.configure do |c|
  c.run_with :chrome
end

Chrome is so 2010. Can I run my tests on node.js?

(evented hipness! jsdom will give you a fake DOM to work with.)

# 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"

Where'd headless support go?!

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.


Plant some Jasmine


Plant a Cucumber or two

Make a feature like in big boy Cucumber

(that's 'cause it is big boy Cucumber, just in JS form)

# 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

Write some steps

(Flowerbox gives you a donut-full of syntactic sugar that wraps around Cucumber.js. Be sure to drink lots of water!)

# 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)

Get some hooks up in here!

(and other fun environment stuff)

# js-features/support/env.js.coffee
#
#= require ../steps

Flowerbox.World ->
  @Before (callback) ->
    @something = 'is available everywhere'
    callback()

  @After (callback) ->
    Put = 'some stuff back'
    callback()

Auto-generate missing steps

(see cucumber-step_writer for my philosophy)

# 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

Flowerbox! Yea...wha?

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.

You already did once...

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.

Selenium faster than headless? But CI servers--

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.

But you said fake browsers are teh bad--

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.

Cucumber.js? Full-stack testing is the only way!

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.