• Stars
    star
    178
  • Rank 208,131 (Top 5 %)
  • Language
    CoffeeScript
  • License
    MIT License
  • Created over 12 years ago
  • Updated over 8 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Like rspec-given, but for jasmine

Build Status

2.x series

We just released a version 2.0.0, thanks to the contributions of @ronen, to bring jasmine-given closer to parity with rspec-given. In particular, jasmine-given will now:

  • ensure that Given statements will always execute before any When statements. This is counter-intuitive at first, but can really help you DRY up specs that require variable setup.
  • allow users to use And in place of multiple Then statements; when using And following a Then, the set-up will only be executed for the first Then, which could be a significant speed-up depending on the test while looking cleaner than chaining Then statements with parentheses.

Keep in mind that the former will be a breaking change for many test suites that currently use jasmine-given, so be sure to allot yourself some time to address any test failures that occur because a Given was incidentally placed after a When in a way that doesn't agree with the new execution order.

jasmine-given

jasmine-given is a Jasmine helper that encourages leaner, meaner specs using Given, When, and Then. It is a shameless tribute to Jim Weirich's terrific rspec-given gem.

Download the latest version here.

The basic idea behind the "*-given" meme is a humble acknowledgement of given-when-then as the best English language analogue we have to arrange-act-assert. With rspec and jasmine, we often approximate "given-when-then" with "let-beforeEach-it" (noting that jasmine lacks let).

The big idea is "why approximate given-when-then, when we could actually just use them?"

The small idea is "if we couldn't write English along with our it blocks then we'd be encouraged to write cleaner, clearer matchers to articulate our expectations."

The subtle idea is that all "given"s should be evaluated before the "when"s. This can DRY up your specs: you don't need to repeat a series of "when"s in order to test the final result with different initial "given"s.

All ideas are pretty cool. Thanks, Jim!

Example (CoffeeScript)

Oh, and jasmine-given looks much nicer in CoffeeScript, so I'll show that example first:

describe "assigning stuff to this", ->
  Given -> @number = 24
  Given -> @number++
  When -> @number *= 2
  Then -> @number == 50
  # or
  Then -> expect(@number).toBe(50)

describe "assigning stuff to variables", ->
  subject=null
  Given -> subject = []
  When -> subject.push('foo')
  Then -> subject.length == 1
  # or
  Then -> expect(subject.length).toBe(1)

As you might infer from the above, Then will trigger a spec failure when the function passed to it returns false. As shown above, traditional expectations can still be used, but using simple booleans can make for significantly easier-to-read expectations when you're asserting something as obvious as equality.

Example (JavaScript)

Of course, jasmine-given also works fine in JavaScript; but as you can see, it's exceptionally clunky in comparison:

describe("assigning stuff to this", function() {
  Given(function() { this.number = 24; });
  Given(function() { this.number++; });
  When(function() { this.number *= 2; });
  Then(function() { return this.number === 50; });
  // or
  Then(function() { expect(this.number).toBe(50) });
});

describe("assigning stuff to variables", function() {
  var subject;
  Given(function() { subject = []; });
  When(function() { subject.push('foo'); });
  Then(function() { return subject.length === 1; });
  // or
  Then(function() { expect(subject.length).toBe(1); });
});

Execution order: Givens then Whens then Thens

The execution order for executing a Then is to execute all preceding Given blocks from the outside in, and next all the preceding When blocks from the outside in, and then the Then. This means that a later Given can affect an earlier When! While this may seem odd at first glance, it can DRY up your specs, especially if you are testing a series of When steps whose final outcome depends on an initial condition. For example:

    Given -> user
    When -> login user

    describe "clicking create", ->

        When -> createButton.click()
        Then -> expect(ajax).toHaveBeenCalled()

        describe "creation succeeds", ->
            When -> ajax.success()
            Then -> object_is_shown()

            describe "reports success message", ->
                Then -> feedback_message.hasContents "created"

            describe "novice gets congratulations message", ->
                Given -> user.isNovice = true
                Then -> feedback_message.hasContents "congratulations!"

            describe "expert gets no feedback", ->
                Given -> user.isExpert = true
                Then -> feedback_message.isEmpty()

For the final three Thens, the execution order is:

       Given -> user
       When -> login user
       When -> createButton.click()
       When -> ajax.success()
       Then -> feedback_message.hasContents "created"

       Given -> user
       Given -> user.isNovice = true
       When -> login user
       When -> createButton.click()
       When -> ajax.success()
       Then -> feedback_message.hasContents "congratulations!"

       Given -> user
       Given -> user.isExpert = true
       When -> login user
       When -> createButton.click()
       When -> ajax.success()
       Then -> feedback_message.isEmpty()

Without this Given/When execution order, the only straightforward way to get the above behavior would be to duplicate then Whens for each user case.

Supporting Idempotent "Then" statements

Jim mentioned to me that Then blocks ought to be idempotent (that is, since they're assertions they should not have any affect on the state of the subject being specified). As a result, one improvement he made to rspec-given 2.x was the And method, which—by following a Then—would be like invoked n Then expectations without executing each Then's depended-on Given and When blocks n times.

Take this example from jasmine-given's spec:

describe "eliminating redundant test execution", ->
  describe "a traditional spec with numerous Then statements", ->
    timesGivenWasInvoked = timesWhenWasInvoked = 0
    Given -> timesGivenWasInvoked++
    When -> timesWhenWasInvoked++
    Then -> timesGivenWasInvoked == 1
    Then -> timesWhenWasInvoked == 2
    Then -> timesGivenWasInvoked == 3
    Then -> timesWhenWasInvoked == 4

Because there are four Then statements, the Given and When are each executed four times. That's because it would be unreasonable for Jasmine to expect each it function to be idempotent.

However, spec authors can leverage idempotence safely when writing in a given-when-then format. You opt-in with jasmine-given by using And blocks, as shown below:

  describe "chaining Then statements", ->
    timesGivenWasInvoked = timesWhenWasInvoked = 0
    Given -> timesGivenWasInvoked++
    When -> timesWhenWasInvoked++

    Then -> timesGivenWasInvoked == 1
    And -> timesWhenWasInvoked == 1
    And -> timesGivenWasInvoked == 1
    And -> timesWhenWasInvoked == 1

    Then -> timesWhenWasInvoked == 2

In this example, Given and When are only invoked one time each for the first Then, because jasmine-given rolled all of those Then & And statements up into a single it in Jasmine. Note that the label of the it is taken from the Then only.

Leveraging this feature is likely to have the effect of speeding up your specs, especially if your specs are otherwise slow (integration specs or DOM-heavy).

The above spec can also be expressed in JavaScript:

describe("eliminating redundant test execution", function() {
  describe("a traditional spec with numerous Then statements", function() {
    var timesGivenWasInvoked = 0,
        timesWhenWasInvoked = 0;
    Given(function() { timesGivenWasInvoked++; });
    When(function() { timesWhenWasInvoked++; });
    Then(function() { return timesGivenWasInvoked == 1; });
    Then(function() { return timesWhenWasInvoked == 2; });
    Then(function() { return timesGivenWasInvoked == 3; });
    Then(function() { return timesWhenWasInvoked == 4; });
  });

  describe("chaining Then statements", function() {
    var timesGivenWasInvoked = 0,
        timesWhenWasInvoked = 0;
    Given(function() { timesGivenWasInvoked++; });
    When(function() { timesWhenWasInvoked++; });
    Then(function() { return timesGivenWasInvoked == 1; })
    And(function() { return timesWhenWasInvoked == 1; })
    And(function() { return timesGivenWasInvoked == 1; })
    And(function() { return timesWhenWasInvoked == 1; })
  });
});

Invariants

Rspec-given also introduced the notion of "Invariants". An Invariant lets you specify a condition which should always be true within the current scope. For example:


    Given -> @stack = new MyStack @initialContents

    Invariant -> @stack.empty? == (@stack.depth == 0)

    describe "With some initial contents", ->
        Given -> @initialContents = ["a", "b", "c"]
        Then -> @stack.depth == 3

        describe "Pop one", ->
           When -> @result = @stack.pop
           Then -> @stack.depth == 2

        describe "Clear all", ->
           When -> @stack.clear()
           Then -> @stack.depth == 0

    describe "With no contents", ->
      Then -> @stack.depth == 0

    …etc…

The Invariant will be checked before each Then block. Note that invariants do not appear as their own tests; if an invariant fails it will be reported as a failure within the Then block. Effectively, an Invariant defines an implicit And which gets prepended to each Then within the current scope. Thus the above example is a DRY version of:


    Given -> @stack = new MyStack @initialContents

    describe "With some initial contents", ->
        Given -> @initialContents = ["a", "b", "c"]
        Then -> @stack.depth == 3
        And -> @stack.empty? == false

        describe "Pop one", ->
           When -> @result = @stack.pop
           Then -> @stack.depth == 2
         And -> @stack.empty? == false

        describe "Clear all", ->
           When -> @stack.clear()
           Then -> @stack.depth == 0
           And -> @stack.empty? == true

    describe "With no contents", ->
      Then -> @stack.depth == 0
      And -> @stack.empty? == true

    …etc…

except that the Invariant is tested before each Then rather than after.

"it"-style test labels

Jasmine-given labels your underlying it blocks with the source expression itself, encouraging writing cleaner, clearer matchers -- and more DRY than saying the same thing twice, once in code and once in English. But there are times when we're using third-party libraries or matchers that just don't read cleanly as English, even when they're expressing a simple concept.

Or, perhaps you are using a collection of Then and And statements to express a single specification. So, when needed, you may use a label for your Then statements:

    Then "makes AJAX POST request to create item", -> expect(@ajax_spy).toHaveBeenCalled()
    And -> @ajax_spy.mostRecentCall.args[0].type = 'POST'
    And -> @ajax_spy.mostRecentCall.args[0].url == "/items"
    And -> @ajax_spy.mostRecentCall.args[0].data.item.user_id == userID
    And -> @ajax_spy.mostRecentCall.args[0].data.item.name == itemName

Testing Asynchronous Code

Following Jasmine 2.0's style for testing asynchronous code, the Given and When statements' functions can take a done parameter, which is a function to call when the asynchronous code completes. Subsequent statements won't be executed until the done completes. E.g.

    Given (done) -> $.get "/stuff"
                      .success (data) =>
                        @stuff = data
                        done()
                        
    When (done) -> $.post "/do", stuff: @stuff
                     .success (data) =>
                        @yay = true
                        done()
                        
    Then -> @stuff == "the stuff"
    Then -> @yay

The Then and And statement functions can also take a done parameter, if the expectation itself requires asynchronous executation to evalute. For example if you're using Selenium, you might want to check browser state in an expectation:

    Then (done) -> browser.find '.alert', (el) ->
        expect(el).toBeDefined()
        done()
    And (done) -> browser.find '.cancel', (el) ->
        expect(cancel).toBeDefined()
        done()

Using with Node.js

To use this helper with Jasmine under Node.js, simply add it to your package.json with

$ npm install jasmine-given --save-dev

And then from your spec (or in a spec helper), require('jasmine-given'). Be sure that it's loaded after jasmine itself is added to the global object, or else it will load minijasminenode which will, in turn, load jasmine into global for you (which you may not be intending).

More Repositories

1

todo_or_die

Write TODOs in code that ensure you actually do them
Ruby
331
star
2

jasmine-maven-plugin

Maven plugin to execute Jasmine Specs. Creates your HTML runners for you, runs headlessly, outputs JUnit XML
Java
291
star
3

jasmine-fixture

A script for injecting fixtures into the DOM to be cleaned up after each spec.
JavaScript
259
star
4

icloud-dotfiles

My iCloud Drive-based dev environment
Shell
201
star
5

soa

Helps you migrate from monolithic Ruby to services
Ruby
87
star
6

jasmine-stealth

extra stubbing & spying love for Jasmine
JavaScript
73
star
7

fine-ants

A gem that fetches bank accounts using Capybara
Ruby
69
star
8

gimme

A low-specification test double tool in ruby
Ruby
68
star
9

emoruby

A little emoji language that compiles down to Ruby. "It's just ruby."
Ruby
65
star
10

extend.js

a teeny-tiny JavaScript namespacing script
JavaScript
64
star
11

try-jasmine

An online sandbox for playing with Jasmine, a bunch of supporting scripts, and Backbone/Underscore/CoffeeScript
CoffeeScript
51
star
12

fine-ants-app

An app that uses the fine_ants gem to aggregate personal finance data
Ruby
43
star
13

remote-capybara-cucumber-example

A bare-bones project directory for remotely testing apps with Cucumber + Capybara
Ruby
35
star
14

jasmine-features

Integrated tests with Jasmine that can be bridged with Cucumber
JavaScript
25
star
15

matt-daemon

24
star
16

jasmine-all

run jasmine from a single script tag
JavaScript
22
star
17

TTResource

A first cut attempt to build a Three20 equivalent to ObjectiveResource, also backed by ObjectiveSupport
Objective-C
22
star
18

bar-of-progress

One of the hardest problems in computer science: Solved ✅
Ruby
21
star
19

simplisafe

A Node.js wrapper for the (undocumented!) SimpliSafe HTTP API
JavaScript
20
star
20

jasmine-coffee

A simple sinatra app running rack-coffee to compile your sources & Jasmine specs as CoffeeScript at runtime
JavaScript
18
star
21

feed2gram

Reads an Atom feed and posts its entries to Instagram (basically feed2toot, but for Instagram)
Ruby
16
star
22

jasmine-headless-webkit-rails-skeleton

Ruby
15
star
23

pressletter

A little tool for solving the game Letterpress (iOS)
Ruby
13
star
24

fill-all-the-things

A bookmarklet for filling all the fields on a page with dummy/test data
JavaScript
12
star
25

katsuyou

Conjugates Japanese words in pure Ruby
Ruby
11
star
26

game-of-life-java-example

An example repo designed to go along with a screencast series about Discovery TDD
Java
9
star
27

jasmine-intro

Slides introducing Jasmine BDD for JavaScript testing and some examples building on the out-of-the-box Jasmine example specs
JavaScript
9
star
28

must-stache

JavaScript
8
star
29

refactor-to-backbone-example

A little example repo demonstrating a refactor from jQuery to backbone.
JavaScript
7
star
30

eiwa

A ruby gem that parses the JMDict Japanese-English dictionary
Ruby
7
star
31

jasmine-archetype

A Maven 2 archetype for getting started with Jasmine and the jasmine-maven-plugin
JavaScript
6
star
32

testing-as-such

JavaScript
6
star
33

searls

Justin Searls' contact info
JavaScript
6
star
34

stupid-simple-spring-jdbc-example

Simple spike needed to remind myself what the minimum amount of yak shaving is to test a database connection using spring-jdbc. Seems like an annual exercise, so why not throw it on github.
Java
5
star
35

is-it-friday-somewhere

www.isitfridaysomewhere.com
Ruby
5
star
36

mockito-testng-example

A Mockito example that uses testng
Java
5
star
37

warez

A JavaScript library that detects which input devices are being used
JavaScript
5
star
38

pixel-killer

Makes pixels in a browser window look like they're dead 👾
JavaScript
5
star
39

nO_op.js

A port of @ymendel's nO_op Ruby gem for Node.js
JavaScript
4
star
40

tailwind-color-to-rgb

Converts tailwind colors to space-separated RGB values
JavaScript
4
star
41

stocks

JavaScript
4
star
42

doing-it

An html5 site for tracking its you have to do.
JavaScript
4
star
43

blight

ncurses with less cursing
Ruby
4
star
44

TagScraper

A straightforward way to perform XPath queries on HTML in a simple object model using the iPhone SDK
4
star
45

skip-circle-builds

Experiment to skip CircleCI builds based on which directories have changed
Shell
4
star
46

html-to-preact-h

Converts an HTML string to a string of preact hyperscript h() calls
JavaScript
4
star
47

dry_eraser

Like Active Record's validation feature, but for destroying models
Ruby
4
star
48

blog-2013

my blog
JavaScript
3
star
49

stream_deck_automation

A GPT-4 soundboard for manipulating and describing text
Ruby
3
star
50

depot-capybara

A port of Cheezy's Watir labs ( http://www.cheezyworld.com/2010/12/16/ui-tests-putting-it-all-together/ ) to Capybara
Ruby
3
star
51

codemash-jasmine-precompiler

Exercises from the Jasmine precompiler at Codemash 2013
JavaScript
3
star
52

chrome-ext-skeleton

A skeleton project for creating Google Chrome Extensions.
JavaScript
3
star
53

lunch_money_scripts

Some scripts for lunchmoney.app
Ruby
3
star
54

jasmine-coffee-archetype

Quickstart web dev for Java friends
JavaScript
3
star
55

whenkani

Tells you when you're ready to study WaniKani
Ruby
3
star
56

inside-out-browser

Chrome Extension that displays the source of the current page instead of the page itself.
JavaScript
2
star
57

conf-talk-ideas

Ideas for Talks I'm Thinking of Pitching
2
star
58

js-craftsmanshop

2
star
59

jasmine-fixture-2

A spike that rewrites jasmine-fixture
JavaScript
2
star
60

jasmine-node-skeleton

JavaScript
2
star
61

tweetconomy

Just about the simplest Twitter OAuth app you could think to write
Ruby
2
star
62

harvest-to-bigtime

Bookmarklet to convert Harvest expenses (csv) to bigtime to avoid using bigtime's god-awful web interface by hand.
JavaScript
2
star
63

data-calendar

JavaScript
1
star
64

examples

Example applications built using Ember.js or Ember Data.
JavaScript
1
star
65

codebreaker

Example app from the RSpec book w/ gimme for doubles
Ruby
1
star
66

todos-examples

JavaScript
1
star
67

who-writes-good-code

JavaScript
1
star
68

table-print-example

A silly little demo app for playing with table-print
Ruby
1
star
69

snapshot

Ruby
1
star
70

elixir_demo

Testing out some build tools. Nothing to see here
Elixir
1
star
71

js_rake_tasks

Ruby
1
star
72

create-y

For when `npm init -y` is too many keystrokes
JavaScript
1
star
73

git-filter-branch-sandbox

Ruby
1
star
74

euler-coffee

JavaScript
1
star
75

jqgrid-example

JavaScript
1
star
76

crb-2012-11

A little sandbox for CRB's meeting on 11/21/2011
JavaScript
1
star
77

testdouble-issue-171

https://github.com/testdouble/testdouble.js/issues/171
JavaScript
1
star
78

js-stack-ui

JavaScript
1
star
79

sample-maven-backbone-jasmine

Simple maven webapp with Backbone and Jasmine
JavaScript
1
star
80

intrinsic-motivator

Lua
1
star
81

neogaf-replies

A little webapp that hunts down replies made to your posts on NeoGAF
JavaScript
1
star
82

quibble-19-reproduction

Attempts to reproduce issue #19 in quibble
JavaScript
1
star
83

atom-js2coffee

An atom plugin for js2coffee
CoffeeScript
1
star
84

rails-repro-schema-squelch

A reproduction of an issue with schema.rb
Ruby
1
star
85

preact-sample-app

a bare-minimum preact app setup that just does string concatenation/minification/fingerprinting, no other cool stuff
JavaScript
1
star
86

javascript-confidence

a demo repo to show how to make a jQuery mess, characterize it in specs, and then clean it up.
JavaScript
1
star
87

minecraft-example-plugin

Building a little Minecraft plugin toy out in the open. (Using Bukkit, Maven)
Java
1
star
88

includes-vs-joins

Supporting repo for a blog post
Ruby
1
star