├── .gitignore
├── .jshintrc
├── Gruntfile.js
├── LICENSE-MIT
├── README.md
├── build.js
├── cuke-browser-watcher.js
├── cuke-watcher.js
├── features
├── add-item-view.feature
├── add-item.feature
├── step_definitions
│ ├── add-item-view.steps.js
│ ├── add-item.steps.js
│ └── background-open-application.steps.js
└── support
│ └── world.js
├── gulpfile.js
├── karma.conf.js
├── package.json
├── script
├── app.js
└── model
│ └── grocery-list.js
├── template
├── app-main.us
├── testrunner-wrapper.us
└── wrapper.us
├── test
├── addItemSteps.js
├── addItemViewSteps.js
├── backgroundOpenApplicationSteps.js
├── cucumber-testrunner.html
├── features.js
├── lib
│ └── cucumber.js
├── script
│ ├── app.js
│ └── tap-listener.js
└── world.js
└── testem.json
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | npm-debug.log
3 | *.sublime*
4 | node_modules
5 | build
--------------------------------------------------------------------------------
/.jshintrc:
--------------------------------------------------------------------------------
1 | {
2 | "curly": true,
3 | "eqeqeq": true,
4 | "immed": true,
5 | "latedef": "nofunc",
6 | "newcap": true,
7 | "noarg": true,
8 | "sub": true,
9 | "undef": true,
10 | "unused": true,
11 | "boss": true,
12 | "eqnull": true,
13 | "node": true
14 | }
--------------------------------------------------------------------------------
/Gruntfile.js:
--------------------------------------------------------------------------------
1 | module.exports = function(grunt) {
2 | 'use strict';
3 |
4 | grunt.initConfig({
5 | pkg: grunt.file.readJSON('package.json'),
6 | watch: {
7 | cucumber: {
8 | files: ['features/**/*.js', 'script/**/*.js'],
9 | tasks: ['cucumberjs']
10 | }
11 | },
12 | cucumberjs: {
13 | src: 'features',
14 | options: {
15 | steps: 'features/step_definitions',
16 | format: 'pretty'
17 | }
18 | }
19 | });
20 |
21 | grunt.loadNpmTasks('grunt-contrib-watch');
22 | grunt.loadNpmTasks('grunt-cucumber');
23 |
24 | grunt.registerTask('watch-tests', 'Starts a watch for test automation.', ['watch:cucumber']);
25 |
26 | };
--------------------------------------------------------------------------------
/LICENSE-MIT:
--------------------------------------------------------------------------------
1 | Copyright (c) 2014 Todd Anderson
2 |
3 | Permission is hereby granted, free of charge, to any person
4 | obtaining a copy of this software and associated documentation
5 | files (the "Software"), to deal in the Software without
6 | restriction, including without limitation the rights to use,
7 | copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | copies of the Software, and to permit persons to whom the
9 | Software is furnished to do so, subject to the following
10 | conditions:
11 |
12 | The above copyright notice and this permission notice shall be
13 | included in all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 | OTHER DEALINGS IN THE SOFTWARE.
23 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | cucumberjs-examples
2 | ===================
3 |
4 | > Source for post series: [BDD in JavaScript: CucumberJS](http://custardbelly.com/blog/blog-posts/2014/01/08/bdd-in-js-cucumberjs/index.html)
5 |
6 | [](https://ci.testling.com/bustardcelly/cucumberjs-examples)
7 |
8 |
9 |
10 |
11 |
12 | Requirements
13 | ===
14 |
15 | ## Node & NPM
16 |
17 | Once [installed](http://www.joyent.com/blog/installing-node-and-npm/), run:
18 |
19 | ```
20 | $ npm install
21 | ```
22 |
23 | Tasks
24 | ===
25 |
26 | ## Test
27 |
28 | Runs basic [cucumberjs](https://github.com/cucumber/cucumber-js) cli tool.
29 |
30 | ```
31 | $ npm run test
32 | ```
33 |
34 | ## Watch
35 |
36 | Runs basic file watch to automate [cucumberjs](https://github.com/cucumber/cucumber-js) cli tool
37 |
38 | ```
39 | $ npm run watch
40 | ```
41 |
42 | ## Watch-Browser
43 |
44 | Runs [cucumberjs-browser](https://github.com/bustardcelly/cucumberjs-browser) cuke bundler to run [cucumberjs](https://github.com/cucumber/cucumber-js) tool in browser!
45 |
46 | ```
47 | $ npm run watch-browser
48 | ```
49 |
50 | ## Build
51 |
52 | Build the app for to live in the wild.
53 |
54 | ```
55 | $ npm run build
56 | ```
57 |
58 | License
59 | ===
60 | Copyright (c) 2014 Todd Anderson
61 |
62 | Permission is hereby granted, free of charge, to any person
63 | obtaining a copy of this software and associated documentation
64 | files (the "Software"), to deal in the Software without
65 | restriction, including without limitation the rights to use,
66 | copy, modify, merge, publish, distribute, sublicense, and/or sell
67 | copies of the Software, and to permit persons to whom the
68 | Software is furnished to do so, subject to the following
69 | conditions:
70 |
71 | The above copyright notice and this permission notice shall be
72 | included in all copies or substantial portions of the Software.
73 |
74 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
75 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
76 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
77 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
78 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
79 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
80 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
81 | OTHER DEALINGS IN THE SOFTWARE.
--------------------------------------------------------------------------------
/build.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | var fs = require('fs');
3 | var path = require('path');
4 | var map = require('map-stream');
5 | var tmpl = require('lodash.template');
6 | var browserify = require('browserify');
7 | var mkdirp = require('mkdirp');
8 |
9 | var output = process.cwd() + '/build';
10 |
11 | var wrap = function(wrapperTemplate) {
12 | return map(function(file, cb) {
13 | var content = file.toString();
14 | fs.readFile(path.resolve(wrapperTemplate), 'utf8', function(err, filedata) {
15 | cb(null, tmpl(filedata, {yield:content}));
16 | });
17 | });
18 | };
19 |
20 | var bundleApp = function(callback) {
21 | browserify(process.cwd() + '/script/app.js')
22 | .bundle({
23 | standalone: 'app'
24 | })
25 | .pipe(fs.createWriteStream(output + '/script/app.js'))
26 | .on('close', function() {
27 | if(callback) {
28 | callback();
29 | }
30 | });
31 | };
32 |
33 | var templateApp = function(callback) {
34 | fs.createReadStream(process.cwd() + '/template/app-main.us')
35 | .pipe(wrap(process.cwd() + '/template/wrapper.us'))
36 | .pipe(fs.createWriteStream(output + '/index.html'))
37 | .on('close', function() {
38 | if(callback) {
39 | callback();
40 | }
41 | });
42 | };
43 |
44 | mkdirp.sync(output + '/script');
45 | bundleApp(templateApp);
--------------------------------------------------------------------------------
/cuke-browser-watcher.js:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 | var fs = require('fs');
3 | var path = require('path');
4 | var map = require('map-stream');
5 | var tmpl = require('lodash.template');
6 | var watch = require('node-watch');
7 | var child_process = require('child_process');
8 | var mkdirp = require('mkdirp');
9 | var rimraf = require('rimraf');
10 | var browserify = require('browserify');
11 |
12 | var http = require('http');
13 | var tinylr = require('tiny-lr');
14 | var connect = require('connect');
15 | var open = require('open');
16 | var S = require('string');
17 |
18 | var tempdir = '.tmp';
19 | var outdir = 'test';
20 | var browserCukes;
21 |
22 | var livereloadPort = 35729;
23 | var connectPort = 8080;
24 | var JS_EXT = /^.*\.js/i;
25 | var options = ['-f', 'tap',
26 | '-o', outdir,
27 | '--tmpl', tempdir + '/testrunner.html'];
28 |
29 | var wrap = function(wrapperTemplate) {
30 | return map(function(file, cb) {
31 | var content = file.toString();
32 | fs.readFile(path.resolve(wrapperTemplate), 'utf8', function(err, filedata) {
33 | cb(null, filedata.replace(/[^]<%= yield %>/i, content));
34 | });
35 | });
36 | };
37 |
38 | // [TASKS]
39 | // a. re-bundle the app.
40 | var bundleApplication = function(f, callback) {
41 | return function() {
42 | browserify(__dirname + '/script/app.js')
43 | .bundle({
44 | standalone: 'app'
45 | })
46 | .pipe(fs.createWriteStream(path.resolve(outdir + '/script/app.js')))
47 | .on('close', function() {
48 | console.log('changed app.js...');
49 | if(callback) {
50 | callback();
51 | }
52 | });
53 | };
54 | };
55 | // b. template testrunner with app partial.
56 | var templateTestRunner = function(callback) {
57 | fs.createReadStream(__dirname + '/template/app-main.us')
58 | .pipe(wrap(__dirname + '/template/testrunner-wrapper.us'))
59 | .pipe(fs.createWriteStream(path.resolve(tempdir + '/testrunner.html')))
60 | .on('close', function() {
61 | if(callback) {
62 | callback();
63 | }
64 | });
65 | };
66 | // c. rerun cucumberjs-browser tool.
67 | var cuke = function(f, callback) {
68 | return function() {
69 | var filename = S(path.basename(f, '.js').split('.').join('-')).camelize().s;
70 | templateTestRunner(function() {
71 | browserCukes = child_process.spawn('cucumberjs-browser', options)
72 | .on('exit', function() {
73 | console.log('changed ' + filename + '...');
74 | rimraf(tempdir, function() {
75 | if(callback) {
76 | callback();
77 | }
78 | });
79 | });
80 | });
81 | };
82 | };
83 |
84 | // 1. Recursive mkdir /test/script if not exist.
85 | mkdirp.sync(outdir + '/script');
86 | mkdirp.sync(tempdir);
87 |
88 | // 2. Create tiny-livereload server.
89 | var lr = tinylr();
90 | lr.listen(livereloadPort, function() {
91 | console.log('livereload listening on ' + livereloadPort + '...');
92 | });
93 |
94 | // 3. Start server on localhost.
95 | var app = connect().use(connect.static(__dirname + '/test'));
96 | var server = http.createServer(app).listen(connectPort, function() {
97 | console.log('local server started on ' + connectPort + '...');
98 | console.log('Note: Remember to start the livereload browser extension!');
99 | console.log('http://feedback.livereload.com/knowledgebase/articles/86242-how-do-i-install-and-use-the-browser-extensions-');
100 | cuke('./features/support/world', function() {
101 | bundleApplication('./script/app.js', function() {
102 | open('http://localhost:' + connectPort + '/cucumber-testrunner.html');
103 | })();
104 | })();
105 | });
106 |
107 | // 4. Watch source and generate bundles.
108 | watch(['./features', './script'], {recursive:true}, function(filename) {
109 | // Used to resolve when running operation(s) are complete.
110 | var resolver;
111 | var running = false;
112 | var resolveWatch = function(limit) {
113 | var count = 0;
114 | running = true;
115 | return function() {
116 | if(++count === limit) {
117 | count = 0;
118 | running = false;
119 | }
120 | else {
121 | running = true;
122 | }
123 | };
124 | };
125 |
126 | if(!running && filename.match(JS_EXT)) {
127 | var bundleAppInvoke = bundleApplication(filename, function() {
128 | lr.changed({
129 | body: {
130 | files: ['script/app']
131 | }
132 | });
133 | resolver();
134 | });
135 | if(/^script?/i.test(filename)) {
136 | resolver = resolveWatch(1);
137 | bundleAppInvoke();
138 | }
139 | else if(/^features?/i.test(filename)) {
140 | resolver = resolveWatch(2);
141 | cuke(filename, function() {
142 | lr.changed({
143 | body: {
144 | files: [filename]
145 | }
146 | });
147 | resolver();
148 | bundleAppInvoke();
149 | })();
150 | }
151 | }
152 |
153 | });
--------------------------------------------------------------------------------
/cuke-watcher.js:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 | var watch = require('node-watch');
3 | var child_process = require('child_process');
4 | var running = false;
5 | var cucumber;
6 |
7 | var JS_EXT = /^.*\.js/i;
8 | var options = ['node_modules/.bin/cucumber-js',
9 | 'features',
10 | '-r', 'features/step_definitions',
11 | '-f', 'pretty'];
12 |
13 | watch(['./features/step_definitions', './script'], {recursive:true}, function(filename) {
14 |
15 | if(!running && filename.match(JS_EXT)) {
16 |
17 | running = true;
18 |
19 | cucumber = child_process.spawn('node', options)
20 | .on('exit', function() {
21 | running = false;
22 | });
23 |
24 | cucumber.stdout.on('data', function(d) {
25 | console.log(String(d));
26 | });
27 |
28 | cucumber.stderr.on('data', function(d) {
29 | console.error(String(d));
30 | });
31 |
32 | }
33 |
34 | });
--------------------------------------------------------------------------------
/features/add-item-view.feature:
--------------------------------------------------------------------------------
1 | Feature: Shopper can add and view new item in Grocery List
2 | As a shopper using the browser-based app
3 | I want to add an item to my grocery list view
4 | So that I can remember to buy that item at the grocery store
5 |
6 | Background: Grocery List Application is Open
7 | Given I have opened the grocery list application
8 |
9 | Scenario: Submit of valid item adds item to list
10 | Given I have an empty grocery list view
11 | When I provide a valid grocery list item name
12 | And I select to add an item
13 | Then The item is added to the grocery list view
14 |
15 | Scenario: Submit of valid item adds item to collection
16 | Given I have an empty grocery list view
17 | When I provide a valid grocery list item name
18 | And I select to add an item
19 | Then The item is accessible from the grocery list collection
--------------------------------------------------------------------------------
/features/add-item.feature:
--------------------------------------------------------------------------------
1 | Feature: Shopper can add an item to their Grocery List
2 | As a shopper
3 | I want to add an item to my grocery list
4 | So that I can remember to buy that item at the grocery store
5 |
6 | Background: Grocery List Application is Open
7 | Given I have opened the grocery list application
8 |
9 | Scenario: Item added to grocery list
10 | Given I have an empty grocery list
11 | When I add an item to the list
12 | Then The grocery list contains a single item
13 |
14 | Scenario: Item accessible from grocery list
15 | Given I have an empty grocery list
16 | When I add an item to the list
17 | Then I can access that item from the grocery list
--------------------------------------------------------------------------------
/features/step_definitions/add-item-view.steps.js:
--------------------------------------------------------------------------------
1 | var assert = require('assert');
2 |
3 | module.exports = function() {
4 | 'use strict';
5 |
6 | var enteredItem;
7 |
8 | this.World = require('../support/world').World;
9 |
10 | this.Given(/^I have an empty grocery list view$/, function(callback) {
11 | this.emptyGroceryListView();
12 | assert.equal(this.getGroceryListView().childNodes.length, 0);
13 | callback();
14 | });
15 |
16 | this.When(/^I provide a valid grocery list item name$/, function(callback) {
17 | enteredItem = this.createGroceryItem();
18 | this.enterNewGorceryListItem(enteredItem);
19 | callback();
20 | });
21 |
22 | this.When(/^I select to add an item$/, function(callback) {
23 | this.clickAddGroceryListItem();
24 | callback();
25 | });
26 |
27 | this.Then(/^The item is added to the grocery list view$/, function(callback) {
28 | assert.equal(this.getGroceryListViewItemAtIndex(0), enteredItem, 'Entered item should be first in empty list.');
29 | callback();
30 | });
31 |
32 | this.Then(/^The item is accessible from the grocery list collection$/, function(callback) {
33 | assert.equal(this.groceryListApplication.list.getItemIndex(enteredItem), 0, 'Added item should be found at first index.');
34 | callback();
35 | });
36 |
37 | };
--------------------------------------------------------------------------------
/features/step_definitions/add-item.steps.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | var assert = require('assert');
3 |
4 | module.exports = function() {
5 |
6 | var listItem;
7 |
8 | this.World = require('../support/world').World;
9 |
10 | this.Given(/^I have an empty grocery list$/, function(callback) {
11 | this.groceryListApplication.list.empty();
12 | callback();
13 | });
14 |
15 | this.When(/^I add an item to the list$/, function(callback) {
16 | listItem = this.createGroceryItem();
17 | this.groceryListApplication.list.add(listItem);
18 | callback();
19 | });
20 |
21 | this.Then(/^The grocery list contains a single item$/, function(callback) {
22 | assert.equal(this.groceryListApplication.list.getAll().length, 1, 'Grocery List should grow by one item.');
23 | callback();
24 | });
25 |
26 | this.Then(/^I can access that item from the grocery list$/, function(callback) {
27 | assert.notEqual(this.groceryListApplication.list.getItemIndex(listItem), -1, 'Added item should be found at non-negative index.');
28 | callback();
29 | });
30 |
31 | };
--------------------------------------------------------------------------------
/features/step_definitions/background-open-application.steps.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | var assert = require('assert');
3 |
4 | module.exports = function() {
5 |
6 | this.World = require('../support/world').World;
7 |
8 | this.Given(/^I have opened the grocery list application$/, function(callback) {
9 | (function(world) {
10 | world.domload(function() {
11 | world.groceryListApplication = world.openGroceryList();
12 | assert(world.groceryListApplication, 'Grocery List Application is required to be open for editability.');
13 | callback();
14 | });
15 | }(this));
16 | });
17 |
18 | };
--------------------------------------------------------------------------------
/features/support/world.js:
--------------------------------------------------------------------------------
1 | /*global window, document*/
2 | 'use strict';
3 |
4 | var World = function World(callback) {
5 |
6 | this.window = process.browser ? window : {};
7 | this.app = undefined;
8 | this.groceryListApplication = undefined;
9 |
10 | var defineGlobals = function(w, doc) {
11 | this.app = w.app;
12 | };
13 |
14 | this.domload = function(callback) {
15 | (function(world) {
16 | if(document.readyState === 'complete') {
17 | defineGlobals.call(world, window, document);
18 | callback();
19 | }
20 | else {
21 | var delegate = document.addEventListener ? 'addEventListener' : 'attachEvent';
22 | var eventType = document.addEventListener ? 'load' : 'onload';
23 | window[delegate](eventType, function() {
24 | defineGlobals.call(world, window, document);
25 | callback();
26 | });
27 | }
28 | }(this));
29 | };
30 |
31 | this.openGroceryList = function() {
32 | return this.app.newSession();
33 | };
34 | this.createGroceryItem = function() {
35 | return 'apple';
36 | };
37 |
38 | this.getGroceryListView = function() {
39 | return this.groceryListApplication.$listview;
40 | };
41 |
42 | this.getGroceryListViewItemAtIndex = function(index) {
43 | return this.groceryListApplication.$listview.childNodes[index].textContent;
44 | }
45 |
46 | this.emptyGroceryListView = function() {
47 | this.groceryListApplication.empty();
48 | };
49 |
50 | this.enterNewGorceryListItem = function(item) {
51 | this.groceryListApplication.enterNewItem(item);
52 | };
53 |
54 | this.createClickEvent = function() {
55 | var event = document.createEvent('MouseEvents');
56 | event.initEvent('click', true, false);
57 | return event;
58 | };
59 |
60 | this.clickAddGroceryListItem = function() {
61 | var clickevent = this.createClickEvent();
62 | this.groceryListApplication.$addbutton.dispatchEvent(clickevent);
63 | };
64 |
65 | callback();
66 |
67 | };
68 |
69 | module.exports.World = World;
--------------------------------------------------------------------------------
/gulpfile.js:
--------------------------------------------------------------------------------
1 | var gulp = require('gulp');
2 | var watch = require('gulp-watch');
3 | var child_process = require('child_process');
4 |
5 | var cucumber;
6 | var running = false;
7 | var options = ['node_modules/.bin/cucumber-js',
8 | 'features',
9 | '-r', 'features/step_definitions',
10 | '-f', 'pretty'];
11 |
12 | gulp.task('cucumber', function() {
13 | if(!running) {
14 | running = true;
15 | cucumber = child_process.spawn('node', options)
16 | .on('exit', function() {
17 | running = false;
18 | });
19 | cucumber.stdout.on('data', function(d) {
20 | console.log(String(d));
21 | });
22 |
23 | cucumber.stderr.on('data', function(d) {
24 | console.error(String(d));
25 | });
26 | }
27 | });
28 |
29 | gulp.task('watch-tests', function() {
30 | gulp.src(['features/**/*.js', 'script/**/*.js'])
31 | .pipe(watch(function() {
32 | gulp.run('cucumber');
33 | }));
34 | });
--------------------------------------------------------------------------------
/karma.conf.js:
--------------------------------------------------------------------------------
1 | module.exports = function(config) {
2 | config.set({
3 | preprocessors: {
4 | '**/*.html': ['html2js']
5 | },
6 |
7 | files: [
8 | '*.js',
9 | '*.html'
10 | ],
11 |
12 | browsers: ['Chrome'],
13 |
14 | reporters: ['dots'],
15 |
16 | plugins: [
17 | 'karma-html2js-preprocessor',
18 | 'karma-chrome-launcher'
19 | ]
20 | });
21 | };
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "cucumberjs-examples",
3 | "version": "0.5.1",
4 | "description": "Examples of using CucumberJS.",
5 | "author": {
6 | "name": "Todd Anderson",
7 | "email": "toddanderson@taanderson.com",
8 | "url": "http://custardbelly.com/blog"
9 | },
10 | "keywords": [
11 | "todd anderson",
12 | "cucumberjs",
13 | "bdd",
14 | "tdd"
15 | ],
16 | "homepage": "https://github.com/bustardcelly/cucumberjs-examples",
17 | "repository": {
18 | "type": "git",
19 | "url": "https://github.com/bustardcelly/cucumberjs-examples"
20 | },
21 | "bugs": {
22 | "url": "https://github.com/bustardcelly/cucumberjs-examples/issues"
23 | },
24 | "licenses": [
25 | {
26 | "type": "MIT",
27 | "url": "https://github.com/bustardcelly/cucumberjs-examples/LICENSE-MIT"
28 | }
29 | ],
30 | "scripts": {
31 | "test": "node node_modules/.bin/cucumber-js",
32 | "watch": "node cuke-watcher.js",
33 | "watch-browser": "node cuke-browser-watcher",
34 | "build": "node build.js"
35 | },
36 | "testling" : {
37 | "html" : "test/cucumber-testrunner.html",
38 | "browsers" : [
39 | "ie/6..latest",
40 | "chrome/latest",
41 | "firefox/latest",
42 | "safari/latest",
43 | "iphone/6", "ipad/6"
44 | ]
45 | },
46 | "devDependencies": {
47 | "cucumber": "~0.3.3",
48 | "node-watch": "~0.3.4",
49 | "grunt": "~0.4.2",
50 | "grunt-cucumber": "~0.2.3",
51 | "grunt-contrib-watch": "~0.5.3",
52 | "gulp": "~3.5.0",
53 | "gulp-watch": "~0.5.0",
54 | "karma-script-launcher": "~0.1.0",
55 | "karma-chrome-launcher": "~0.1.2",
56 | "karma-firefox-launcher": "~0.1.3",
57 | "karma-jasmine": "~0.1.5",
58 | "requirejs": "~2.1.10",
59 | "karma-requirejs": "~0.2.1",
60 | "karma-coffee-preprocessor": "~0.1.2",
61 | "karma-phantomjs-launcher": "~0.1.2",
62 | "karma": "~0.10.9",
63 | "karma-html2js-preprocessor": "~0.1.0",
64 | "browserify": "~3.28.1",
65 | "mkdirp": "~0.3.5",
66 | "tiny-lr": "0.0.5",
67 | "connect": "~2.12.0",
68 | "open": "0.0.4",
69 | "string": "~1.8.0",
70 | "map-stream": "~0.1.0",
71 | "rimraf": "~2.2.6",
72 | "lodash.template": "~2.4.1"
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/script/app.js:
--------------------------------------------------------------------------------
1 | /*global document*/
2 | 'use strict';
3 |
4 | var GroceryList = require('./model/grocery-list');
5 |
6 | var application = {
7 | init: function(list) {
8 | this.list = list;
9 | this.$listview = document.querySelector('#grocery-list');
10 | this.$itemInputView = document.querySelector('#item-input');
11 | this.$addbutton = document.querySelector('#add-button');
12 | (function(app) {
13 | app.$addbutton.addEventListener('click', function(event) {
14 | var item = app.$itemInputView.value;
15 | app.addItemToView(item);
16 | app.list.add(item);
17 | });
18 | }(this));
19 | return this;
20 | },
21 | empty: function() {
22 | var gl = this.$listview;
23 | while (gl.hasChildNodes()) {
24 | gl.removeChild(gl.lastChild);
25 | }
26 | this.list.empty();
27 | },
28 | enterNewItem: function(item) {
29 | this.$itemInputView.value = item;
30 | },
31 | addItemToView: function(item) {
32 | var li = document.createElement('li');
33 | var text = document.createTextNode(item);
34 | li.appendChild(text);
35 | this.$listview.appendChild(li);
36 | }
37 | };
38 |
39 | module.exports = {
40 | newSession: function() {
41 | var newList = GroceryList.create();
42 | return Object.create(application).init(newList);
43 | }
44 | };
--------------------------------------------------------------------------------
/script/model/grocery-list.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var groceryList = {
4 | empty: function() {
5 | this.list.length = 0;
6 | },
7 | add: function(item) {
8 | this.list.push(item);
9 | },
10 | getAll: function() {
11 | return this.list;
12 | },
13 | getItemIndex: function(value) {
14 | var index = this.list.length;
15 | while(--index > -1) {
16 | if(this.list[index] === value) {
17 | return index;
18 | }
19 | }
20 | return -1;
21 | }
22 | };
23 |
24 | module.exports = {
25 | create: function() {
26 | return Object.create(groceryList, {
27 | 'list': {
28 | value: [],
29 | writable: false,
30 | enumerable: true
31 | }
32 | });
33 | }
34 | };
--------------------------------------------------------------------------------
/template/app-main.us:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/template/testrunner-wrapper.us:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | <% if(listener.format === 'testem') { %>
7 |
8 | <% }; %>
9 |
10 | <% _.each(modules, function(module) { %>
11 |
12 | <% }); %>
13 | <% if(listener.exists) { %>
14 |
15 | <% }; %>
16 | <% if(listener.exists && /^ui?/i.test(listener.filename)) { %>
17 |
47 | <% }; %>
48 |
49 |
50 |
81 | <%= yield %>
82 |
83 |
84 |
--------------------------------------------------------------------------------
/template/wrapper.us:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | cucumberjs example
6 |
7 |
8 | <%= yield %>
9 |
10 |
13 |
14 |
--------------------------------------------------------------------------------
/test/addItemSteps.js:
--------------------------------------------------------------------------------
1 | !function(e){if("object"==typeof exports)module.exports=e();else if("function"==typeof define&&define.amd)define(e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.addItemSteps=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o
8 | //
9 | // Permission is hereby granted, free of charge, to any person obtaining a copy
10 | // of this software and associated documentation files (the 'Software'), to
11 | // deal in the Software without restriction, including without limitation the
12 | // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
13 | // sell copies of the Software, and to permit persons to whom the Software is
14 | // furnished to do so, subject to the following conditions:
15 | //
16 | // The above copyright notice and this permission notice shall be included in
17 | // all copies or substantial portions of the Software.
18 | //
19 | // THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 | // AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
23 | // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 |
26 | // when used in node, this will actually load the util module we depend on
27 | // versus loading the builtin util module as happens otherwise
28 | // this is a bug in node module loading as far as I am concerned
29 | var util = _dereq_('util/');
30 |
31 | var pSlice = Array.prototype.slice;
32 | var hasOwn = Object.prototype.hasOwnProperty;
33 |
34 | // 1. The assert module provides functions that throw
35 | // AssertionError's when particular conditions are not met. The
36 | // assert module must conform to the following interface.
37 |
38 | var assert = module.exports = ok;
39 |
40 | // 2. The AssertionError is defined in assert.
41 | // new assert.AssertionError({ message: message,
42 | // actual: actual,
43 | // expected: expected })
44 |
45 | assert.AssertionError = function AssertionError(options) {
46 | this.name = 'AssertionError';
47 | this.actual = options.actual;
48 | this.expected = options.expected;
49 | this.operator = options.operator;
50 | if (options.message) {
51 | this.message = options.message;
52 | this.generatedMessage = false;
53 | } else {
54 | this.message = getMessage(this);
55 | this.generatedMessage = true;
56 | }
57 | var stackStartFunction = options.stackStartFunction || fail;
58 |
59 | if (Error.captureStackTrace) {
60 | Error.captureStackTrace(this, stackStartFunction);
61 | }
62 | else {
63 | // non v8 browsers so we can have a stacktrace
64 | var err = new Error();
65 | if (err.stack) {
66 | var out = err.stack;
67 |
68 | // try to strip useless frames
69 | var fn_name = stackStartFunction.name;
70 | var idx = out.indexOf('\n' + fn_name);
71 | if (idx >= 0) {
72 | // once we have located the function frame
73 | // we need to strip out everything before it (and its line)
74 | var next_line = out.indexOf('\n', idx + 1);
75 | out = out.substring(next_line + 1);
76 | }
77 |
78 | this.stack = out;
79 | }
80 | }
81 | };
82 |
83 | // assert.AssertionError instanceof Error
84 | util.inherits(assert.AssertionError, Error);
85 |
86 | function replacer(key, value) {
87 | if (util.isUndefined(value)) {
88 | return '' + value;
89 | }
90 | if (util.isNumber(value) && (isNaN(value) || !isFinite(value))) {
91 | return value.toString();
92 | }
93 | if (util.isFunction(value) || util.isRegExp(value)) {
94 | return value.toString();
95 | }
96 | return value;
97 | }
98 |
99 | function truncate(s, n) {
100 | if (util.isString(s)) {
101 | return s.length < n ? s : s.slice(0, n);
102 | } else {
103 | return s;
104 | }
105 | }
106 |
107 | function getMessage(self) {
108 | return truncate(JSON.stringify(self.actual, replacer), 128) + ' ' +
109 | self.operator + ' ' +
110 | truncate(JSON.stringify(self.expected, replacer), 128);
111 | }
112 |
113 | // At present only the three keys mentioned above are used and
114 | // understood by the spec. Implementations or sub modules can pass
115 | // other keys to the AssertionError's constructor - they will be
116 | // ignored.
117 |
118 | // 3. All of the following functions must throw an AssertionError
119 | // when a corresponding condition is not met, with a message that
120 | // may be undefined if not provided. All assertion methods provide
121 | // both the actual and expected values to the assertion error for
122 | // display purposes.
123 |
124 | function fail(actual, expected, message, operator, stackStartFunction) {
125 | throw new assert.AssertionError({
126 | message: message,
127 | actual: actual,
128 | expected: expected,
129 | operator: operator,
130 | stackStartFunction: stackStartFunction
131 | });
132 | }
133 |
134 | // EXTENSION! allows for well behaved errors defined elsewhere.
135 | assert.fail = fail;
136 |
137 | // 4. Pure assertion tests whether a value is truthy, as determined
138 | // by !!guard.
139 | // assert.ok(guard, message_opt);
140 | // This statement is equivalent to assert.equal(true, !!guard,
141 | // message_opt);. To test strictly for the value true, use
142 | // assert.strictEqual(true, guard, message_opt);.
143 |
144 | function ok(value, message) {
145 | if (!value) fail(value, true, message, '==', assert.ok);
146 | }
147 | assert.ok = ok;
148 |
149 | // 5. The equality assertion tests shallow, coercive equality with
150 | // ==.
151 | // assert.equal(actual, expected, message_opt);
152 |
153 | assert.equal = function equal(actual, expected, message) {
154 | if (actual != expected) fail(actual, expected, message, '==', assert.equal);
155 | };
156 |
157 | // 6. The non-equality assertion tests for whether two objects are not equal
158 | // with != assert.notEqual(actual, expected, message_opt);
159 |
160 | assert.notEqual = function notEqual(actual, expected, message) {
161 | if (actual == expected) {
162 | fail(actual, expected, message, '!=', assert.notEqual);
163 | }
164 | };
165 |
166 | // 7. The equivalence assertion tests a deep equality relation.
167 | // assert.deepEqual(actual, expected, message_opt);
168 |
169 | assert.deepEqual = function deepEqual(actual, expected, message) {
170 | if (!_deepEqual(actual, expected)) {
171 | fail(actual, expected, message, 'deepEqual', assert.deepEqual);
172 | }
173 | };
174 |
175 | function _deepEqual(actual, expected) {
176 | // 7.1. All identical values are equivalent, as determined by ===.
177 | if (actual === expected) {
178 | return true;
179 |
180 | } else if (util.isBuffer(actual) && util.isBuffer(expected)) {
181 | if (actual.length != expected.length) return false;
182 |
183 | for (var i = 0; i < actual.length; i++) {
184 | if (actual[i] !== expected[i]) return false;
185 | }
186 |
187 | return true;
188 |
189 | // 7.2. If the expected value is a Date object, the actual value is
190 | // equivalent if it is also a Date object that refers to the same time.
191 | } else if (util.isDate(actual) && util.isDate(expected)) {
192 | return actual.getTime() === expected.getTime();
193 |
194 | // 7.3 If the expected value is a RegExp object, the actual value is
195 | // equivalent if it is also a RegExp object with the same source and
196 | // properties (`global`, `multiline`, `lastIndex`, `ignoreCase`).
197 | } else if (util.isRegExp(actual) && util.isRegExp(expected)) {
198 | return actual.source === expected.source &&
199 | actual.global === expected.global &&
200 | actual.multiline === expected.multiline &&
201 | actual.lastIndex === expected.lastIndex &&
202 | actual.ignoreCase === expected.ignoreCase;
203 |
204 | // 7.4. Other pairs that do not both pass typeof value == 'object',
205 | // equivalence is determined by ==.
206 | } else if (!util.isObject(actual) && !util.isObject(expected)) {
207 | return actual == expected;
208 |
209 | // 7.5 For all other Object pairs, including Array objects, equivalence is
210 | // determined by having the same number of owned properties (as verified
211 | // with Object.prototype.hasOwnProperty.call), the same set of keys
212 | // (although not necessarily the same order), equivalent values for every
213 | // corresponding key, and an identical 'prototype' property. Note: this
214 | // accounts for both named and indexed properties on Arrays.
215 | } else {
216 | return objEquiv(actual, expected);
217 | }
218 | }
219 |
220 | function isArguments(object) {
221 | return Object.prototype.toString.call(object) == '[object Arguments]';
222 | }
223 |
224 | function objEquiv(a, b) {
225 | if (util.isNullOrUndefined(a) || util.isNullOrUndefined(b))
226 | return false;
227 | // an identical 'prototype' property.
228 | if (a.prototype !== b.prototype) return false;
229 | //~~~I've managed to break Object.keys through screwy arguments passing.
230 | // Converting to array solves the problem.
231 | if (isArguments(a)) {
232 | if (!isArguments(b)) {
233 | return false;
234 | }
235 | a = pSlice.call(a);
236 | b = pSlice.call(b);
237 | return _deepEqual(a, b);
238 | }
239 | try {
240 | var ka = objectKeys(a),
241 | kb = objectKeys(b),
242 | key, i;
243 | } catch (e) {//happens when one is a string literal and the other isn't
244 | return false;
245 | }
246 | // having the same number of owned properties (keys incorporates
247 | // hasOwnProperty)
248 | if (ka.length != kb.length)
249 | return false;
250 | //the same set of keys (although not necessarily the same order),
251 | ka.sort();
252 | kb.sort();
253 | //~~~cheap key test
254 | for (i = ka.length - 1; i >= 0; i--) {
255 | if (ka[i] != kb[i])
256 | return false;
257 | }
258 | //equivalent values for every corresponding key, and
259 | //~~~possibly expensive deep test
260 | for (i = ka.length - 1; i >= 0; i--) {
261 | key = ka[i];
262 | if (!_deepEqual(a[key], b[key])) return false;
263 | }
264 | return true;
265 | }
266 |
267 | // 8. The non-equivalence assertion tests for any deep inequality.
268 | // assert.notDeepEqual(actual, expected, message_opt);
269 |
270 | assert.notDeepEqual = function notDeepEqual(actual, expected, message) {
271 | if (_deepEqual(actual, expected)) {
272 | fail(actual, expected, message, 'notDeepEqual', assert.notDeepEqual);
273 | }
274 | };
275 |
276 | // 9. The strict equality assertion tests strict equality, as determined by ===.
277 | // assert.strictEqual(actual, expected, message_opt);
278 |
279 | assert.strictEqual = function strictEqual(actual, expected, message) {
280 | if (actual !== expected) {
281 | fail(actual, expected, message, '===', assert.strictEqual);
282 | }
283 | };
284 |
285 | // 10. The strict non-equality assertion tests for strict inequality, as
286 | // determined by !==. assert.notStrictEqual(actual, expected, message_opt);
287 |
288 | assert.notStrictEqual = function notStrictEqual(actual, expected, message) {
289 | if (actual === expected) {
290 | fail(actual, expected, message, '!==', assert.notStrictEqual);
291 | }
292 | };
293 |
294 | function expectedException(actual, expected) {
295 | if (!actual || !expected) {
296 | return false;
297 | }
298 |
299 | if (Object.prototype.toString.call(expected) == '[object RegExp]') {
300 | return expected.test(actual);
301 | } else if (actual instanceof expected) {
302 | return true;
303 | } else if (expected.call({}, actual) === true) {
304 | return true;
305 | }
306 |
307 | return false;
308 | }
309 |
310 | function _throws(shouldThrow, block, expected, message) {
311 | var actual;
312 |
313 | if (util.isString(expected)) {
314 | message = expected;
315 | expected = null;
316 | }
317 |
318 | try {
319 | block();
320 | } catch (e) {
321 | actual = e;
322 | }
323 |
324 | message = (expected && expected.name ? ' (' + expected.name + ').' : '.') +
325 | (message ? ' ' + message : '.');
326 |
327 | if (shouldThrow && !actual) {
328 | fail(actual, expected, 'Missing expected exception' + message);
329 | }
330 |
331 | if (!shouldThrow && expectedException(actual, expected)) {
332 | fail(actual, expected, 'Got unwanted exception' + message);
333 | }
334 |
335 | if ((shouldThrow && actual && expected &&
336 | !expectedException(actual, expected)) || (!shouldThrow && actual)) {
337 | throw actual;
338 | }
339 | }
340 |
341 | // 11. Expected to throw an error:
342 | // assert.throws(block, Error_opt, message_opt);
343 |
344 | assert.throws = function(block, /*optional*/error, /*optional*/message) {
345 | _throws.apply(this, [true].concat(pSlice.call(arguments)));
346 | };
347 |
348 | // EXTENSION! This is annoying to write outside this module.
349 | assert.doesNotThrow = function(block, /*optional*/message) {
350 | _throws.apply(this, [false].concat(pSlice.call(arguments)));
351 | };
352 |
353 | assert.ifError = function(err) { if (err) {throw err;}};
354 |
355 | var objectKeys = Object.keys || function (obj) {
356 | var keys = [];
357 | for (var key in obj) {
358 | if (hasOwn.call(obj, key)) keys.push(key);
359 | }
360 | return keys;
361 | };
362 |
363 | },{"util/":5}],2:[function(_dereq_,module,exports){
364 | if (typeof Object.create === 'function') {
365 | // implementation from standard node.js 'util' module
366 | module.exports = function inherits(ctor, superCtor) {
367 | ctor.super_ = superCtor
368 | ctor.prototype = Object.create(superCtor.prototype, {
369 | constructor: {
370 | value: ctor,
371 | enumerable: false,
372 | writable: true,
373 | configurable: true
374 | }
375 | });
376 | };
377 | } else {
378 | // old school shim for old browsers
379 | module.exports = function inherits(ctor, superCtor) {
380 | ctor.super_ = superCtor
381 | var TempCtor = function () {}
382 | TempCtor.prototype = superCtor.prototype
383 | ctor.prototype = new TempCtor()
384 | ctor.prototype.constructor = ctor
385 | }
386 | }
387 |
388 | },{}],3:[function(_dereq_,module,exports){
389 | // shim for using process in browser
390 |
391 | var process = module.exports = {};
392 |
393 | process.nextTick = (function () {
394 | var canSetImmediate = typeof window !== 'undefined'
395 | && window.setImmediate;
396 | var canPost = typeof window !== 'undefined'
397 | && window.postMessage && window.addEventListener
398 | ;
399 |
400 | if (canSetImmediate) {
401 | return function (f) { return window.setImmediate(f) };
402 | }
403 |
404 | if (canPost) {
405 | var queue = [];
406 | window.addEventListener('message', function (ev) {
407 | var source = ev.source;
408 | if ((source === window || source === null) && ev.data === 'process-tick') {
409 | ev.stopPropagation();
410 | if (queue.length > 0) {
411 | var fn = queue.shift();
412 | fn();
413 | }
414 | }
415 | }, true);
416 |
417 | return function nextTick(fn) {
418 | queue.push(fn);
419 | window.postMessage('process-tick', '*');
420 | };
421 | }
422 |
423 | return function nextTick(fn) {
424 | setTimeout(fn, 0);
425 | };
426 | })();
427 |
428 | process.title = 'browser';
429 | process.browser = true;
430 | process.env = {};
431 | process.argv = [];
432 |
433 | process.binding = function (name) {
434 | throw new Error('process.binding is not supported');
435 | }
436 |
437 | // TODO(shtylman)
438 | process.cwd = function () { return '/' };
439 | process.chdir = function (dir) {
440 | throw new Error('process.chdir is not supported');
441 | };
442 |
443 | },{}],4:[function(_dereq_,module,exports){
444 | module.exports = function isBuffer(arg) {
445 | return arg && typeof arg === 'object'
446 | && typeof arg.copy === 'function'
447 | && typeof arg.fill === 'function'
448 | && typeof arg.readUInt8 === 'function';
449 | }
450 | },{}],5:[function(_dereq_,module,exports){
451 | (function (process,global){// Copyright Joyent, Inc. and other Node contributors.
452 | //
453 | // Permission is hereby granted, free of charge, to any person obtaining a
454 | // copy of this software and associated documentation files (the
455 | // "Software"), to deal in the Software without restriction, including
456 | // without limitation the rights to use, copy, modify, merge, publish,
457 | // distribute, sublicense, and/or sell copies of the Software, and to permit
458 | // persons to whom the Software is furnished to do so, subject to the
459 | // following conditions:
460 | //
461 | // The above copyright notice and this permission notice shall be included
462 | // in all copies or substantial portions of the Software.
463 | //
464 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
465 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
466 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
467 | // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
468 | // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
469 | // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
470 | // USE OR OTHER DEALINGS IN THE SOFTWARE.
471 |
472 | var formatRegExp = /%[sdj%]/g;
473 | exports.format = function(f) {
474 | if (!isString(f)) {
475 | var objects = [];
476 | for (var i = 0; i < arguments.length; i++) {
477 | objects.push(inspect(arguments[i]));
478 | }
479 | return objects.join(' ');
480 | }
481 |
482 | var i = 1;
483 | var args = arguments;
484 | var len = args.length;
485 | var str = String(f).replace(formatRegExp, function(x) {
486 | if (x === '%%') return '%';
487 | if (i >= len) return x;
488 | switch (x) {
489 | case '%s': return String(args[i++]);
490 | case '%d': return Number(args[i++]);
491 | case '%j':
492 | try {
493 | return JSON.stringify(args[i++]);
494 | } catch (_) {
495 | return '[Circular]';
496 | }
497 | default:
498 | return x;
499 | }
500 | });
501 | for (var x = args[i]; i < len; x = args[++i]) {
502 | if (isNull(x) || !isObject(x)) {
503 | str += ' ' + x;
504 | } else {
505 | str += ' ' + inspect(x);
506 | }
507 | }
508 | return str;
509 | };
510 |
511 |
512 | // Mark that a method should not be used.
513 | // Returns a modified function which warns once by default.
514 | // If --no-deprecation is set, then it is a no-op.
515 | exports.deprecate = function(fn, msg) {
516 | // Allow for deprecating things in the process of starting up.
517 | if (isUndefined(global.process)) {
518 | return function() {
519 | return exports.deprecate(fn, msg).apply(this, arguments);
520 | };
521 | }
522 |
523 | if (process.noDeprecation === true) {
524 | return fn;
525 | }
526 |
527 | var warned = false;
528 | function deprecated() {
529 | if (!warned) {
530 | if (process.throwDeprecation) {
531 | throw new Error(msg);
532 | } else if (process.traceDeprecation) {
533 | console.trace(msg);
534 | } else {
535 | console.error(msg);
536 | }
537 | warned = true;
538 | }
539 | return fn.apply(this, arguments);
540 | }
541 |
542 | return deprecated;
543 | };
544 |
545 |
546 | var debugs = {};
547 | var debugEnviron;
548 | exports.debuglog = function(set) {
549 | if (isUndefined(debugEnviron))
550 | debugEnviron = process.env.NODE_DEBUG || '';
551 | set = set.toUpperCase();
552 | if (!debugs[set]) {
553 | if (new RegExp('\\b' + set + '\\b', 'i').test(debugEnviron)) {
554 | var pid = process.pid;
555 | debugs[set] = function() {
556 | var msg = exports.format.apply(exports, arguments);
557 | console.error('%s %d: %s', set, pid, msg);
558 | };
559 | } else {
560 | debugs[set] = function() {};
561 | }
562 | }
563 | return debugs[set];
564 | };
565 |
566 |
567 | /**
568 | * Echos the value of a value. Trys to print the value out
569 | * in the best way possible given the different types.
570 | *
571 | * @param {Object} obj The object to print out.
572 | * @param {Object} opts Optional options object that alters the output.
573 | */
574 | /* legacy: obj, showHidden, depth, colors*/
575 | function inspect(obj, opts) {
576 | // default options
577 | var ctx = {
578 | seen: [],
579 | stylize: stylizeNoColor
580 | };
581 | // legacy...
582 | if (arguments.length >= 3) ctx.depth = arguments[2];
583 | if (arguments.length >= 4) ctx.colors = arguments[3];
584 | if (isBoolean(opts)) {
585 | // legacy...
586 | ctx.showHidden = opts;
587 | } else if (opts) {
588 | // got an "options" object
589 | exports._extend(ctx, opts);
590 | }
591 | // set default options
592 | if (isUndefined(ctx.showHidden)) ctx.showHidden = false;
593 | if (isUndefined(ctx.depth)) ctx.depth = 2;
594 | if (isUndefined(ctx.colors)) ctx.colors = false;
595 | if (isUndefined(ctx.customInspect)) ctx.customInspect = true;
596 | if (ctx.colors) ctx.stylize = stylizeWithColor;
597 | return formatValue(ctx, obj, ctx.depth);
598 | }
599 | exports.inspect = inspect;
600 |
601 |
602 | // http://en.wikipedia.org/wiki/ANSI_escape_code#graphics
603 | inspect.colors = {
604 | 'bold' : [1, 22],
605 | 'italic' : [3, 23],
606 | 'underline' : [4, 24],
607 | 'inverse' : [7, 27],
608 | 'white' : [37, 39],
609 | 'grey' : [90, 39],
610 | 'black' : [30, 39],
611 | 'blue' : [34, 39],
612 | 'cyan' : [36, 39],
613 | 'green' : [32, 39],
614 | 'magenta' : [35, 39],
615 | 'red' : [31, 39],
616 | 'yellow' : [33, 39]
617 | };
618 |
619 | // Don't use 'blue' not visible on cmd.exe
620 | inspect.styles = {
621 | 'special': 'cyan',
622 | 'number': 'yellow',
623 | 'boolean': 'yellow',
624 | 'undefined': 'grey',
625 | 'null': 'bold',
626 | 'string': 'green',
627 | 'date': 'magenta',
628 | // "name": intentionally not styling
629 | 'regexp': 'red'
630 | };
631 |
632 |
633 | function stylizeWithColor(str, styleType) {
634 | var style = inspect.styles[styleType];
635 |
636 | if (style) {
637 | return '\u001b[' + inspect.colors[style][0] + 'm' + str +
638 | '\u001b[' + inspect.colors[style][1] + 'm';
639 | } else {
640 | return str;
641 | }
642 | }
643 |
644 |
645 | function stylizeNoColor(str, styleType) {
646 | return str;
647 | }
648 |
649 |
650 | function arrayToHash(array) {
651 | var hash = {};
652 |
653 | array.forEach(function(val, idx) {
654 | hash[val] = true;
655 | });
656 |
657 | return hash;
658 | }
659 |
660 |
661 | function formatValue(ctx, value, recurseTimes) {
662 | // Provide a hook for user-specified inspect functions.
663 | // Check that value is an object with an inspect function on it
664 | if (ctx.customInspect &&
665 | value &&
666 | isFunction(value.inspect) &&
667 | // Filter out the util module, it's inspect function is special
668 | value.inspect !== exports.inspect &&
669 | // Also filter out any prototype objects using the circular check.
670 | !(value.constructor && value.constructor.prototype === value)) {
671 | var ret = value.inspect(recurseTimes, ctx);
672 | if (!isString(ret)) {
673 | ret = formatValue(ctx, ret, recurseTimes);
674 | }
675 | return ret;
676 | }
677 |
678 | // Primitive types cannot have properties
679 | var primitive = formatPrimitive(ctx, value);
680 | if (primitive) {
681 | return primitive;
682 | }
683 |
684 | // Look up the keys of the object.
685 | var keys = Object.keys(value);
686 | var visibleKeys = arrayToHash(keys);
687 |
688 | if (ctx.showHidden) {
689 | keys = Object.getOwnPropertyNames(value);
690 | }
691 |
692 | // IE doesn't make error fields non-enumerable
693 | // http://msdn.microsoft.com/en-us/library/ie/dww52sbt(v=vs.94).aspx
694 | if (isError(value)
695 | && (keys.indexOf('message') >= 0 || keys.indexOf('description') >= 0)) {
696 | return formatError(value);
697 | }
698 |
699 | // Some type of object without properties can be shortcutted.
700 | if (keys.length === 0) {
701 | if (isFunction(value)) {
702 | var name = value.name ? ': ' + value.name : '';
703 | return ctx.stylize('[Function' + name + ']', 'special');
704 | }
705 | if (isRegExp(value)) {
706 | return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');
707 | }
708 | if (isDate(value)) {
709 | return ctx.stylize(Date.prototype.toString.call(value), 'date');
710 | }
711 | if (isError(value)) {
712 | return formatError(value);
713 | }
714 | }
715 |
716 | var base = '', array = false, braces = ['{', '}'];
717 |
718 | // Make Array say that they are Array
719 | if (isArray(value)) {
720 | array = true;
721 | braces = ['[', ']'];
722 | }
723 |
724 | // Make functions say that they are functions
725 | if (isFunction(value)) {
726 | var n = value.name ? ': ' + value.name : '';
727 | base = ' [Function' + n + ']';
728 | }
729 |
730 | // Make RegExps say that they are RegExps
731 | if (isRegExp(value)) {
732 | base = ' ' + RegExp.prototype.toString.call(value);
733 | }
734 |
735 | // Make dates with properties first say the date
736 | if (isDate(value)) {
737 | base = ' ' + Date.prototype.toUTCString.call(value);
738 | }
739 |
740 | // Make error with message first say the error
741 | if (isError(value)) {
742 | base = ' ' + formatError(value);
743 | }
744 |
745 | if (keys.length === 0 && (!array || value.length == 0)) {
746 | return braces[0] + base + braces[1];
747 | }
748 |
749 | if (recurseTimes < 0) {
750 | if (isRegExp(value)) {
751 | return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');
752 | } else {
753 | return ctx.stylize('[Object]', 'special');
754 | }
755 | }
756 |
757 | ctx.seen.push(value);
758 |
759 | var output;
760 | if (array) {
761 | output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);
762 | } else {
763 | output = keys.map(function(key) {
764 | return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);
765 | });
766 | }
767 |
768 | ctx.seen.pop();
769 |
770 | return reduceToSingleString(output, base, braces);
771 | }
772 |
773 |
774 | function formatPrimitive(ctx, value) {
775 | if (isUndefined(value))
776 | return ctx.stylize('undefined', 'undefined');
777 | if (isString(value)) {
778 | var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '')
779 | .replace(/'/g, "\\'")
780 | .replace(/\\"/g, '"') + '\'';
781 | return ctx.stylize(simple, 'string');
782 | }
783 | if (isNumber(value))
784 | return ctx.stylize('' + value, 'number');
785 | if (isBoolean(value))
786 | return ctx.stylize('' + value, 'boolean');
787 | // For some reason typeof null is "object", so special case here.
788 | if (isNull(value))
789 | return ctx.stylize('null', 'null');
790 | }
791 |
792 |
793 | function formatError(value) {
794 | return '[' + Error.prototype.toString.call(value) + ']';
795 | }
796 |
797 |
798 | function formatArray(ctx, value, recurseTimes, visibleKeys, keys) {
799 | var output = [];
800 | for (var i = 0, l = value.length; i < l; ++i) {
801 | if (hasOwnProperty(value, String(i))) {
802 | output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,
803 | String(i), true));
804 | } else {
805 | output.push('');
806 | }
807 | }
808 | keys.forEach(function(key) {
809 | if (!key.match(/^\d+$/)) {
810 | output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,
811 | key, true));
812 | }
813 | });
814 | return output;
815 | }
816 |
817 |
818 | function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {
819 | var name, str, desc;
820 | desc = Object.getOwnPropertyDescriptor(value, key) || { value: value[key] };
821 | if (desc.get) {
822 | if (desc.set) {
823 | str = ctx.stylize('[Getter/Setter]', 'special');
824 | } else {
825 | str = ctx.stylize('[Getter]', 'special');
826 | }
827 | } else {
828 | if (desc.set) {
829 | str = ctx.stylize('[Setter]', 'special');
830 | }
831 | }
832 | if (!hasOwnProperty(visibleKeys, key)) {
833 | name = '[' + key + ']';
834 | }
835 | if (!str) {
836 | if (ctx.seen.indexOf(desc.value) < 0) {
837 | if (isNull(recurseTimes)) {
838 | str = formatValue(ctx, desc.value, null);
839 | } else {
840 | str = formatValue(ctx, desc.value, recurseTimes - 1);
841 | }
842 | if (str.indexOf('\n') > -1) {
843 | if (array) {
844 | str = str.split('\n').map(function(line) {
845 | return ' ' + line;
846 | }).join('\n').substr(2);
847 | } else {
848 | str = '\n' + str.split('\n').map(function(line) {
849 | return ' ' + line;
850 | }).join('\n');
851 | }
852 | }
853 | } else {
854 | str = ctx.stylize('[Circular]', 'special');
855 | }
856 | }
857 | if (isUndefined(name)) {
858 | if (array && key.match(/^\d+$/)) {
859 | return str;
860 | }
861 | name = JSON.stringify('' + key);
862 | if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) {
863 | name = name.substr(1, name.length - 2);
864 | name = ctx.stylize(name, 'name');
865 | } else {
866 | name = name.replace(/'/g, "\\'")
867 | .replace(/\\"/g, '"')
868 | .replace(/(^"|"$)/g, "'");
869 | name = ctx.stylize(name, 'string');
870 | }
871 | }
872 |
873 | return name + ': ' + str;
874 | }
875 |
876 |
877 | function reduceToSingleString(output, base, braces) {
878 | var numLinesEst = 0;
879 | var length = output.reduce(function(prev, cur) {
880 | numLinesEst++;
881 | if (cur.indexOf('\n') >= 0) numLinesEst++;
882 | return prev + cur.replace(/\u001b\[\d\d?m/g, '').length + 1;
883 | }, 0);
884 |
885 | if (length > 60) {
886 | return braces[0] +
887 | (base === '' ? '' : base + '\n ') +
888 | ' ' +
889 | output.join(',\n ') +
890 | ' ' +
891 | braces[1];
892 | }
893 |
894 | return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];
895 | }
896 |
897 |
898 | // NOTE: These type checking functions intentionally don't use `instanceof`
899 | // because it is fragile and can be easily faked with `Object.create()`.
900 | function isArray(ar) {
901 | return Array.isArray(ar);
902 | }
903 | exports.isArray = isArray;
904 |
905 | function isBoolean(arg) {
906 | return typeof arg === 'boolean';
907 | }
908 | exports.isBoolean = isBoolean;
909 |
910 | function isNull(arg) {
911 | return arg === null;
912 | }
913 | exports.isNull = isNull;
914 |
915 | function isNullOrUndefined(arg) {
916 | return arg == null;
917 | }
918 | exports.isNullOrUndefined = isNullOrUndefined;
919 |
920 | function isNumber(arg) {
921 | return typeof arg === 'number';
922 | }
923 | exports.isNumber = isNumber;
924 |
925 | function isString(arg) {
926 | return typeof arg === 'string';
927 | }
928 | exports.isString = isString;
929 |
930 | function isSymbol(arg) {
931 | return typeof arg === 'symbol';
932 | }
933 | exports.isSymbol = isSymbol;
934 |
935 | function isUndefined(arg) {
936 | return arg === void 0;
937 | }
938 | exports.isUndefined = isUndefined;
939 |
940 | function isRegExp(re) {
941 | return isObject(re) && objectToString(re) === '[object RegExp]';
942 | }
943 | exports.isRegExp = isRegExp;
944 |
945 | function isObject(arg) {
946 | return typeof arg === 'object' && arg !== null;
947 | }
948 | exports.isObject = isObject;
949 |
950 | function isDate(d) {
951 | return isObject(d) && objectToString(d) === '[object Date]';
952 | }
953 | exports.isDate = isDate;
954 |
955 | function isError(e) {
956 | return isObject(e) &&
957 | (objectToString(e) === '[object Error]' || e instanceof Error);
958 | }
959 | exports.isError = isError;
960 |
961 | function isFunction(arg) {
962 | return typeof arg === 'function';
963 | }
964 | exports.isFunction = isFunction;
965 |
966 | function isPrimitive(arg) {
967 | return arg === null ||
968 | typeof arg === 'boolean' ||
969 | typeof arg === 'number' ||
970 | typeof arg === 'string' ||
971 | typeof arg === 'symbol' || // ES6 symbol
972 | typeof arg === 'undefined';
973 | }
974 | exports.isPrimitive = isPrimitive;
975 |
976 | exports.isBuffer = _dereq_('./support/isBuffer');
977 |
978 | function objectToString(o) {
979 | return Object.prototype.toString.call(o);
980 | }
981 |
982 |
983 | function pad(n) {
984 | return n < 10 ? '0' + n.toString(10) : n.toString(10);
985 | }
986 |
987 |
988 | var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
989 | 'Oct', 'Nov', 'Dec'];
990 |
991 | // 26 Feb 16:19:34
992 | function timestamp() {
993 | var d = new Date();
994 | var time = [pad(d.getHours()),
995 | pad(d.getMinutes()),
996 | pad(d.getSeconds())].join(':');
997 | return [d.getDate(), months[d.getMonth()], time].join(' ');
998 | }
999 |
1000 |
1001 | // log is just a thin wrapper to console.log that prepends a timestamp
1002 | exports.log = function() {
1003 | console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments));
1004 | };
1005 |
1006 |
1007 | /**
1008 | * Inherit the prototype methods from one constructor into another.
1009 | *
1010 | * The Function.prototype.inherits from lang.js rewritten as a standalone
1011 | * function (not on Function.prototype). NOTE: If this file is to be loaded
1012 | * during bootstrapping this function needs to be rewritten using some native
1013 | * functions as prototype setup using normal JavaScript does not work as
1014 | * expected during bootstrapping (see mirror.js in r114903).
1015 | *
1016 | * @param {function} ctor Constructor function which needs to inherit the
1017 | * prototype.
1018 | * @param {function} superCtor Constructor function to inherit prototype from.
1019 | */
1020 | exports.inherits = _dereq_('inherits');
1021 |
1022 | exports._extend = function(origin, add) {
1023 | // Don't do anything if add isn't an object
1024 | if (!add || !isObject(add)) return origin;
1025 |
1026 | var keys = Object.keys(add);
1027 | var i = keys.length;
1028 | while (i--) {
1029 | origin[keys[i]] = add[keys[i]];
1030 | }
1031 | return origin;
1032 | };
1033 |
1034 | function hasOwnProperty(obj, prop) {
1035 | return Object.prototype.hasOwnProperty.call(obj, prop);
1036 | }
1037 | }).call(this,_dereq_("/Users/toddanderson/Documents/workspace/custardbelly/cucumberjs-browser/node_modules/browserify/node_modules/insert-module-globals/node_modules/process/browser.js"),typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
1038 | },{"./support/isBuffer":4,"/Users/toddanderson/Documents/workspace/custardbelly/cucumberjs-browser/node_modules/browserify/node_modules/insert-module-globals/node_modules/process/browser.js":3,"inherits":2}],6:[function(_dereq_,module,exports){
1039 | 'use strict';
1040 | var assert = _dereq_('assert');
1041 |
1042 | module.exports = function() {
1043 |
1044 | var listItem;
1045 |
1046 | this.World = _dereq_('../support/world').World;
1047 |
1048 | this.Given(/^I have an empty grocery list$/, function(callback) {
1049 | this.groceryListApplication.list.empty();
1050 | callback();
1051 | });
1052 |
1053 | this.When(/^I add an item to the list$/, function(callback) {
1054 | listItem = this.createGroceryItem();
1055 | this.groceryListApplication.list.add(listItem);
1056 | callback();
1057 | });
1058 |
1059 | this.Then(/^The grocery list contains a single item$/, function(callback) {
1060 | assert.equal(this.groceryListApplication.list.getAll().length, 1, 'Grocery List should grow by one item.');
1061 | callback();
1062 | });
1063 |
1064 | this.Then(/^I can access that item from the grocery list$/, function(callback) {
1065 | assert.notEqual(this.groceryListApplication.list.getItemIndex(listItem), -1, 'Added item should be found at non-negative index.');
1066 | callback();
1067 | });
1068 |
1069 | };
1070 | },{"../support/world":7,"assert":1}],7:[function(_dereq_,module,exports){
1071 | (function (process){/*global window, document*/
1072 | 'use strict';
1073 |
1074 | var World = function World(callback) {
1075 |
1076 | this.window = process.browser ? window : {};
1077 | this.app = undefined;
1078 | this.groceryListApplication = undefined;
1079 |
1080 | var defineGlobals = function(w, doc) {
1081 | this.app = w.app;
1082 | };
1083 |
1084 | this.domload = function(callback) {
1085 | (function(world) {
1086 | if(document.readyState === 'complete') {
1087 | defineGlobals.call(world, window, document);
1088 | callback();
1089 | }
1090 | else {
1091 | var delegate = document.addEventListener ? 'addEventListener' : 'attachEvent';
1092 | var eventType = document.addEventListener ? 'load' : 'onload';
1093 | window[delegate](eventType, function() {
1094 | defineGlobals.call(world, window, document);
1095 | callback();
1096 | });
1097 | }
1098 | }(this));
1099 | };
1100 |
1101 | this.openGroceryList = function() {
1102 | return this.app.newSession();
1103 | };
1104 | this.createGroceryItem = function() {
1105 | return 'apple';
1106 | };
1107 |
1108 | this.getGroceryListView = function() {
1109 | return this.groceryListApplication.$listview;
1110 | };
1111 |
1112 | this.getGroceryListViewItemAtIndex = function(index) {
1113 | return this.groceryListApplication.$listview.childNodes[index].textContent;
1114 | }
1115 |
1116 | this.emptyGroceryListView = function() {
1117 | this.groceryListApplication.empty();
1118 | };
1119 |
1120 | this.enterNewGorceryListItem = function(item) {
1121 | this.groceryListApplication.enterNewItem(item);
1122 | };
1123 |
1124 | this.createClickEvent = function() {
1125 | var event = document.createEvent('MouseEvents');
1126 | event.initEvent('click', true, false);
1127 | return event;
1128 | };
1129 |
1130 | this.clickAddGroceryListItem = function() {
1131 | var clickevent = this.createClickEvent();
1132 | this.groceryListApplication.$addbutton.dispatchEvent(clickevent);
1133 | };
1134 |
1135 | callback();
1136 |
1137 | };
1138 |
1139 | module.exports.World = World;}).call(this,_dereq_("/Users/toddanderson/Documents/workspace/custardbelly/cucumberjs-browser/node_modules/browserify/node_modules/insert-module-globals/node_modules/process/browser.js"))
1140 | },{"/Users/toddanderson/Documents/workspace/custardbelly/cucumberjs-browser/node_modules/browserify/node_modules/insert-module-globals/node_modules/process/browser.js":3}]},{},[6])
1141 | (6)
1142 | });
--------------------------------------------------------------------------------
/test/addItemViewSteps.js:
--------------------------------------------------------------------------------
1 | !function(e){if("object"==typeof exports)module.exports=e();else if("function"==typeof define&&define.amd)define(e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.addItemViewSteps=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o
8 | //
9 | // Permission is hereby granted, free of charge, to any person obtaining a copy
10 | // of this software and associated documentation files (the 'Software'), to
11 | // deal in the Software without restriction, including without limitation the
12 | // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
13 | // sell copies of the Software, and to permit persons to whom the Software is
14 | // furnished to do so, subject to the following conditions:
15 | //
16 | // The above copyright notice and this permission notice shall be included in
17 | // all copies or substantial portions of the Software.
18 | //
19 | // THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 | // AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
23 | // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 |
26 | // when used in node, this will actually load the util module we depend on
27 | // versus loading the builtin util module as happens otherwise
28 | // this is a bug in node module loading as far as I am concerned
29 | var util = _dereq_('util/');
30 |
31 | var pSlice = Array.prototype.slice;
32 | var hasOwn = Object.prototype.hasOwnProperty;
33 |
34 | // 1. The assert module provides functions that throw
35 | // AssertionError's when particular conditions are not met. The
36 | // assert module must conform to the following interface.
37 |
38 | var assert = module.exports = ok;
39 |
40 | // 2. The AssertionError is defined in assert.
41 | // new assert.AssertionError({ message: message,
42 | // actual: actual,
43 | // expected: expected })
44 |
45 | assert.AssertionError = function AssertionError(options) {
46 | this.name = 'AssertionError';
47 | this.actual = options.actual;
48 | this.expected = options.expected;
49 | this.operator = options.operator;
50 | if (options.message) {
51 | this.message = options.message;
52 | this.generatedMessage = false;
53 | } else {
54 | this.message = getMessage(this);
55 | this.generatedMessage = true;
56 | }
57 | var stackStartFunction = options.stackStartFunction || fail;
58 |
59 | if (Error.captureStackTrace) {
60 | Error.captureStackTrace(this, stackStartFunction);
61 | }
62 | else {
63 | // non v8 browsers so we can have a stacktrace
64 | var err = new Error();
65 | if (err.stack) {
66 | var out = err.stack;
67 |
68 | // try to strip useless frames
69 | var fn_name = stackStartFunction.name;
70 | var idx = out.indexOf('\n' + fn_name);
71 | if (idx >= 0) {
72 | // once we have located the function frame
73 | // we need to strip out everything before it (and its line)
74 | var next_line = out.indexOf('\n', idx + 1);
75 | out = out.substring(next_line + 1);
76 | }
77 |
78 | this.stack = out;
79 | }
80 | }
81 | };
82 |
83 | // assert.AssertionError instanceof Error
84 | util.inherits(assert.AssertionError, Error);
85 |
86 | function replacer(key, value) {
87 | if (util.isUndefined(value)) {
88 | return '' + value;
89 | }
90 | if (util.isNumber(value) && (isNaN(value) || !isFinite(value))) {
91 | return value.toString();
92 | }
93 | if (util.isFunction(value) || util.isRegExp(value)) {
94 | return value.toString();
95 | }
96 | return value;
97 | }
98 |
99 | function truncate(s, n) {
100 | if (util.isString(s)) {
101 | return s.length < n ? s : s.slice(0, n);
102 | } else {
103 | return s;
104 | }
105 | }
106 |
107 | function getMessage(self) {
108 | return truncate(JSON.stringify(self.actual, replacer), 128) + ' ' +
109 | self.operator + ' ' +
110 | truncate(JSON.stringify(self.expected, replacer), 128);
111 | }
112 |
113 | // At present only the three keys mentioned above are used and
114 | // understood by the spec. Implementations or sub modules can pass
115 | // other keys to the AssertionError's constructor - they will be
116 | // ignored.
117 |
118 | // 3. All of the following functions must throw an AssertionError
119 | // when a corresponding condition is not met, with a message that
120 | // may be undefined if not provided. All assertion methods provide
121 | // both the actual and expected values to the assertion error for
122 | // display purposes.
123 |
124 | function fail(actual, expected, message, operator, stackStartFunction) {
125 | throw new assert.AssertionError({
126 | message: message,
127 | actual: actual,
128 | expected: expected,
129 | operator: operator,
130 | stackStartFunction: stackStartFunction
131 | });
132 | }
133 |
134 | // EXTENSION! allows for well behaved errors defined elsewhere.
135 | assert.fail = fail;
136 |
137 | // 4. Pure assertion tests whether a value is truthy, as determined
138 | // by !!guard.
139 | // assert.ok(guard, message_opt);
140 | // This statement is equivalent to assert.equal(true, !!guard,
141 | // message_opt);. To test strictly for the value true, use
142 | // assert.strictEqual(true, guard, message_opt);.
143 |
144 | function ok(value, message) {
145 | if (!value) fail(value, true, message, '==', assert.ok);
146 | }
147 | assert.ok = ok;
148 |
149 | // 5. The equality assertion tests shallow, coercive equality with
150 | // ==.
151 | // assert.equal(actual, expected, message_opt);
152 |
153 | assert.equal = function equal(actual, expected, message) {
154 | if (actual != expected) fail(actual, expected, message, '==', assert.equal);
155 | };
156 |
157 | // 6. The non-equality assertion tests for whether two objects are not equal
158 | // with != assert.notEqual(actual, expected, message_opt);
159 |
160 | assert.notEqual = function notEqual(actual, expected, message) {
161 | if (actual == expected) {
162 | fail(actual, expected, message, '!=', assert.notEqual);
163 | }
164 | };
165 |
166 | // 7. The equivalence assertion tests a deep equality relation.
167 | // assert.deepEqual(actual, expected, message_opt);
168 |
169 | assert.deepEqual = function deepEqual(actual, expected, message) {
170 | if (!_deepEqual(actual, expected)) {
171 | fail(actual, expected, message, 'deepEqual', assert.deepEqual);
172 | }
173 | };
174 |
175 | function _deepEqual(actual, expected) {
176 | // 7.1. All identical values are equivalent, as determined by ===.
177 | if (actual === expected) {
178 | return true;
179 |
180 | } else if (util.isBuffer(actual) && util.isBuffer(expected)) {
181 | if (actual.length != expected.length) return false;
182 |
183 | for (var i = 0; i < actual.length; i++) {
184 | if (actual[i] !== expected[i]) return false;
185 | }
186 |
187 | return true;
188 |
189 | // 7.2. If the expected value is a Date object, the actual value is
190 | // equivalent if it is also a Date object that refers to the same time.
191 | } else if (util.isDate(actual) && util.isDate(expected)) {
192 | return actual.getTime() === expected.getTime();
193 |
194 | // 7.3 If the expected value is a RegExp object, the actual value is
195 | // equivalent if it is also a RegExp object with the same source and
196 | // properties (`global`, `multiline`, `lastIndex`, `ignoreCase`).
197 | } else if (util.isRegExp(actual) && util.isRegExp(expected)) {
198 | return actual.source === expected.source &&
199 | actual.global === expected.global &&
200 | actual.multiline === expected.multiline &&
201 | actual.lastIndex === expected.lastIndex &&
202 | actual.ignoreCase === expected.ignoreCase;
203 |
204 | // 7.4. Other pairs that do not both pass typeof value == 'object',
205 | // equivalence is determined by ==.
206 | } else if (!util.isObject(actual) && !util.isObject(expected)) {
207 | return actual == expected;
208 |
209 | // 7.5 For all other Object pairs, including Array objects, equivalence is
210 | // determined by having the same number of owned properties (as verified
211 | // with Object.prototype.hasOwnProperty.call), the same set of keys
212 | // (although not necessarily the same order), equivalent values for every
213 | // corresponding key, and an identical 'prototype' property. Note: this
214 | // accounts for both named and indexed properties on Arrays.
215 | } else {
216 | return objEquiv(actual, expected);
217 | }
218 | }
219 |
220 | function isArguments(object) {
221 | return Object.prototype.toString.call(object) == '[object Arguments]';
222 | }
223 |
224 | function objEquiv(a, b) {
225 | if (util.isNullOrUndefined(a) || util.isNullOrUndefined(b))
226 | return false;
227 | // an identical 'prototype' property.
228 | if (a.prototype !== b.prototype) return false;
229 | //~~~I've managed to break Object.keys through screwy arguments passing.
230 | // Converting to array solves the problem.
231 | if (isArguments(a)) {
232 | if (!isArguments(b)) {
233 | return false;
234 | }
235 | a = pSlice.call(a);
236 | b = pSlice.call(b);
237 | return _deepEqual(a, b);
238 | }
239 | try {
240 | var ka = objectKeys(a),
241 | kb = objectKeys(b),
242 | key, i;
243 | } catch (e) {//happens when one is a string literal and the other isn't
244 | return false;
245 | }
246 | // having the same number of owned properties (keys incorporates
247 | // hasOwnProperty)
248 | if (ka.length != kb.length)
249 | return false;
250 | //the same set of keys (although not necessarily the same order),
251 | ka.sort();
252 | kb.sort();
253 | //~~~cheap key test
254 | for (i = ka.length - 1; i >= 0; i--) {
255 | if (ka[i] != kb[i])
256 | return false;
257 | }
258 | //equivalent values for every corresponding key, and
259 | //~~~possibly expensive deep test
260 | for (i = ka.length - 1; i >= 0; i--) {
261 | key = ka[i];
262 | if (!_deepEqual(a[key], b[key])) return false;
263 | }
264 | return true;
265 | }
266 |
267 | // 8. The non-equivalence assertion tests for any deep inequality.
268 | // assert.notDeepEqual(actual, expected, message_opt);
269 |
270 | assert.notDeepEqual = function notDeepEqual(actual, expected, message) {
271 | if (_deepEqual(actual, expected)) {
272 | fail(actual, expected, message, 'notDeepEqual', assert.notDeepEqual);
273 | }
274 | };
275 |
276 | // 9. The strict equality assertion tests strict equality, as determined by ===.
277 | // assert.strictEqual(actual, expected, message_opt);
278 |
279 | assert.strictEqual = function strictEqual(actual, expected, message) {
280 | if (actual !== expected) {
281 | fail(actual, expected, message, '===', assert.strictEqual);
282 | }
283 | };
284 |
285 | // 10. The strict non-equality assertion tests for strict inequality, as
286 | // determined by !==. assert.notStrictEqual(actual, expected, message_opt);
287 |
288 | assert.notStrictEqual = function notStrictEqual(actual, expected, message) {
289 | if (actual === expected) {
290 | fail(actual, expected, message, '!==', assert.notStrictEqual);
291 | }
292 | };
293 |
294 | function expectedException(actual, expected) {
295 | if (!actual || !expected) {
296 | return false;
297 | }
298 |
299 | if (Object.prototype.toString.call(expected) == '[object RegExp]') {
300 | return expected.test(actual);
301 | } else if (actual instanceof expected) {
302 | return true;
303 | } else if (expected.call({}, actual) === true) {
304 | return true;
305 | }
306 |
307 | return false;
308 | }
309 |
310 | function _throws(shouldThrow, block, expected, message) {
311 | var actual;
312 |
313 | if (util.isString(expected)) {
314 | message = expected;
315 | expected = null;
316 | }
317 |
318 | try {
319 | block();
320 | } catch (e) {
321 | actual = e;
322 | }
323 |
324 | message = (expected && expected.name ? ' (' + expected.name + ').' : '.') +
325 | (message ? ' ' + message : '.');
326 |
327 | if (shouldThrow && !actual) {
328 | fail(actual, expected, 'Missing expected exception' + message);
329 | }
330 |
331 | if (!shouldThrow && expectedException(actual, expected)) {
332 | fail(actual, expected, 'Got unwanted exception' + message);
333 | }
334 |
335 | if ((shouldThrow && actual && expected &&
336 | !expectedException(actual, expected)) || (!shouldThrow && actual)) {
337 | throw actual;
338 | }
339 | }
340 |
341 | // 11. Expected to throw an error:
342 | // assert.throws(block, Error_opt, message_opt);
343 |
344 | assert.throws = function(block, /*optional*/error, /*optional*/message) {
345 | _throws.apply(this, [true].concat(pSlice.call(arguments)));
346 | };
347 |
348 | // EXTENSION! This is annoying to write outside this module.
349 | assert.doesNotThrow = function(block, /*optional*/message) {
350 | _throws.apply(this, [false].concat(pSlice.call(arguments)));
351 | };
352 |
353 | assert.ifError = function(err) { if (err) {throw err;}};
354 |
355 | var objectKeys = Object.keys || function (obj) {
356 | var keys = [];
357 | for (var key in obj) {
358 | if (hasOwn.call(obj, key)) keys.push(key);
359 | }
360 | return keys;
361 | };
362 |
363 | },{"util/":5}],2:[function(_dereq_,module,exports){
364 | if (typeof Object.create === 'function') {
365 | // implementation from standard node.js 'util' module
366 | module.exports = function inherits(ctor, superCtor) {
367 | ctor.super_ = superCtor
368 | ctor.prototype = Object.create(superCtor.prototype, {
369 | constructor: {
370 | value: ctor,
371 | enumerable: false,
372 | writable: true,
373 | configurable: true
374 | }
375 | });
376 | };
377 | } else {
378 | // old school shim for old browsers
379 | module.exports = function inherits(ctor, superCtor) {
380 | ctor.super_ = superCtor
381 | var TempCtor = function () {}
382 | TempCtor.prototype = superCtor.prototype
383 | ctor.prototype = new TempCtor()
384 | ctor.prototype.constructor = ctor
385 | }
386 | }
387 |
388 | },{}],3:[function(_dereq_,module,exports){
389 | // shim for using process in browser
390 |
391 | var process = module.exports = {};
392 |
393 | process.nextTick = (function () {
394 | var canSetImmediate = typeof window !== 'undefined'
395 | && window.setImmediate;
396 | var canPost = typeof window !== 'undefined'
397 | && window.postMessage && window.addEventListener
398 | ;
399 |
400 | if (canSetImmediate) {
401 | return function (f) { return window.setImmediate(f) };
402 | }
403 |
404 | if (canPost) {
405 | var queue = [];
406 | window.addEventListener('message', function (ev) {
407 | var source = ev.source;
408 | if ((source === window || source === null) && ev.data === 'process-tick') {
409 | ev.stopPropagation();
410 | if (queue.length > 0) {
411 | var fn = queue.shift();
412 | fn();
413 | }
414 | }
415 | }, true);
416 |
417 | return function nextTick(fn) {
418 | queue.push(fn);
419 | window.postMessage('process-tick', '*');
420 | };
421 | }
422 |
423 | return function nextTick(fn) {
424 | setTimeout(fn, 0);
425 | };
426 | })();
427 |
428 | process.title = 'browser';
429 | process.browser = true;
430 | process.env = {};
431 | process.argv = [];
432 |
433 | process.binding = function (name) {
434 | throw new Error('process.binding is not supported');
435 | }
436 |
437 | // TODO(shtylman)
438 | process.cwd = function () { return '/' };
439 | process.chdir = function (dir) {
440 | throw new Error('process.chdir is not supported');
441 | };
442 |
443 | },{}],4:[function(_dereq_,module,exports){
444 | module.exports = function isBuffer(arg) {
445 | return arg && typeof arg === 'object'
446 | && typeof arg.copy === 'function'
447 | && typeof arg.fill === 'function'
448 | && typeof arg.readUInt8 === 'function';
449 | }
450 | },{}],5:[function(_dereq_,module,exports){
451 | (function (process,global){// Copyright Joyent, Inc. and other Node contributors.
452 | //
453 | // Permission is hereby granted, free of charge, to any person obtaining a
454 | // copy of this software and associated documentation files (the
455 | // "Software"), to deal in the Software without restriction, including
456 | // without limitation the rights to use, copy, modify, merge, publish,
457 | // distribute, sublicense, and/or sell copies of the Software, and to permit
458 | // persons to whom the Software is furnished to do so, subject to the
459 | // following conditions:
460 | //
461 | // The above copyright notice and this permission notice shall be included
462 | // in all copies or substantial portions of the Software.
463 | //
464 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
465 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
466 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
467 | // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
468 | // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
469 | // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
470 | // USE OR OTHER DEALINGS IN THE SOFTWARE.
471 |
472 | var formatRegExp = /%[sdj%]/g;
473 | exports.format = function(f) {
474 | if (!isString(f)) {
475 | var objects = [];
476 | for (var i = 0; i < arguments.length; i++) {
477 | objects.push(inspect(arguments[i]));
478 | }
479 | return objects.join(' ');
480 | }
481 |
482 | var i = 1;
483 | var args = arguments;
484 | var len = args.length;
485 | var str = String(f).replace(formatRegExp, function(x) {
486 | if (x === '%%') return '%';
487 | if (i >= len) return x;
488 | switch (x) {
489 | case '%s': return String(args[i++]);
490 | case '%d': return Number(args[i++]);
491 | case '%j':
492 | try {
493 | return JSON.stringify(args[i++]);
494 | } catch (_) {
495 | return '[Circular]';
496 | }
497 | default:
498 | return x;
499 | }
500 | });
501 | for (var x = args[i]; i < len; x = args[++i]) {
502 | if (isNull(x) || !isObject(x)) {
503 | str += ' ' + x;
504 | } else {
505 | str += ' ' + inspect(x);
506 | }
507 | }
508 | return str;
509 | };
510 |
511 |
512 | // Mark that a method should not be used.
513 | // Returns a modified function which warns once by default.
514 | // If --no-deprecation is set, then it is a no-op.
515 | exports.deprecate = function(fn, msg) {
516 | // Allow for deprecating things in the process of starting up.
517 | if (isUndefined(global.process)) {
518 | return function() {
519 | return exports.deprecate(fn, msg).apply(this, arguments);
520 | };
521 | }
522 |
523 | if (process.noDeprecation === true) {
524 | return fn;
525 | }
526 |
527 | var warned = false;
528 | function deprecated() {
529 | if (!warned) {
530 | if (process.throwDeprecation) {
531 | throw new Error(msg);
532 | } else if (process.traceDeprecation) {
533 | console.trace(msg);
534 | } else {
535 | console.error(msg);
536 | }
537 | warned = true;
538 | }
539 | return fn.apply(this, arguments);
540 | }
541 |
542 | return deprecated;
543 | };
544 |
545 |
546 | var debugs = {};
547 | var debugEnviron;
548 | exports.debuglog = function(set) {
549 | if (isUndefined(debugEnviron))
550 | debugEnviron = process.env.NODE_DEBUG || '';
551 | set = set.toUpperCase();
552 | if (!debugs[set]) {
553 | if (new RegExp('\\b' + set + '\\b', 'i').test(debugEnviron)) {
554 | var pid = process.pid;
555 | debugs[set] = function() {
556 | var msg = exports.format.apply(exports, arguments);
557 | console.error('%s %d: %s', set, pid, msg);
558 | };
559 | } else {
560 | debugs[set] = function() {};
561 | }
562 | }
563 | return debugs[set];
564 | };
565 |
566 |
567 | /**
568 | * Echos the value of a value. Trys to print the value out
569 | * in the best way possible given the different types.
570 | *
571 | * @param {Object} obj The object to print out.
572 | * @param {Object} opts Optional options object that alters the output.
573 | */
574 | /* legacy: obj, showHidden, depth, colors*/
575 | function inspect(obj, opts) {
576 | // default options
577 | var ctx = {
578 | seen: [],
579 | stylize: stylizeNoColor
580 | };
581 | // legacy...
582 | if (arguments.length >= 3) ctx.depth = arguments[2];
583 | if (arguments.length >= 4) ctx.colors = arguments[3];
584 | if (isBoolean(opts)) {
585 | // legacy...
586 | ctx.showHidden = opts;
587 | } else if (opts) {
588 | // got an "options" object
589 | exports._extend(ctx, opts);
590 | }
591 | // set default options
592 | if (isUndefined(ctx.showHidden)) ctx.showHidden = false;
593 | if (isUndefined(ctx.depth)) ctx.depth = 2;
594 | if (isUndefined(ctx.colors)) ctx.colors = false;
595 | if (isUndefined(ctx.customInspect)) ctx.customInspect = true;
596 | if (ctx.colors) ctx.stylize = stylizeWithColor;
597 | return formatValue(ctx, obj, ctx.depth);
598 | }
599 | exports.inspect = inspect;
600 |
601 |
602 | // http://en.wikipedia.org/wiki/ANSI_escape_code#graphics
603 | inspect.colors = {
604 | 'bold' : [1, 22],
605 | 'italic' : [3, 23],
606 | 'underline' : [4, 24],
607 | 'inverse' : [7, 27],
608 | 'white' : [37, 39],
609 | 'grey' : [90, 39],
610 | 'black' : [30, 39],
611 | 'blue' : [34, 39],
612 | 'cyan' : [36, 39],
613 | 'green' : [32, 39],
614 | 'magenta' : [35, 39],
615 | 'red' : [31, 39],
616 | 'yellow' : [33, 39]
617 | };
618 |
619 | // Don't use 'blue' not visible on cmd.exe
620 | inspect.styles = {
621 | 'special': 'cyan',
622 | 'number': 'yellow',
623 | 'boolean': 'yellow',
624 | 'undefined': 'grey',
625 | 'null': 'bold',
626 | 'string': 'green',
627 | 'date': 'magenta',
628 | // "name": intentionally not styling
629 | 'regexp': 'red'
630 | };
631 |
632 |
633 | function stylizeWithColor(str, styleType) {
634 | var style = inspect.styles[styleType];
635 |
636 | if (style) {
637 | return '\u001b[' + inspect.colors[style][0] + 'm' + str +
638 | '\u001b[' + inspect.colors[style][1] + 'm';
639 | } else {
640 | return str;
641 | }
642 | }
643 |
644 |
645 | function stylizeNoColor(str, styleType) {
646 | return str;
647 | }
648 |
649 |
650 | function arrayToHash(array) {
651 | var hash = {};
652 |
653 | array.forEach(function(val, idx) {
654 | hash[val] = true;
655 | });
656 |
657 | return hash;
658 | }
659 |
660 |
661 | function formatValue(ctx, value, recurseTimes) {
662 | // Provide a hook for user-specified inspect functions.
663 | // Check that value is an object with an inspect function on it
664 | if (ctx.customInspect &&
665 | value &&
666 | isFunction(value.inspect) &&
667 | // Filter out the util module, it's inspect function is special
668 | value.inspect !== exports.inspect &&
669 | // Also filter out any prototype objects using the circular check.
670 | !(value.constructor && value.constructor.prototype === value)) {
671 | var ret = value.inspect(recurseTimes, ctx);
672 | if (!isString(ret)) {
673 | ret = formatValue(ctx, ret, recurseTimes);
674 | }
675 | return ret;
676 | }
677 |
678 | // Primitive types cannot have properties
679 | var primitive = formatPrimitive(ctx, value);
680 | if (primitive) {
681 | return primitive;
682 | }
683 |
684 | // Look up the keys of the object.
685 | var keys = Object.keys(value);
686 | var visibleKeys = arrayToHash(keys);
687 |
688 | if (ctx.showHidden) {
689 | keys = Object.getOwnPropertyNames(value);
690 | }
691 |
692 | // IE doesn't make error fields non-enumerable
693 | // http://msdn.microsoft.com/en-us/library/ie/dww52sbt(v=vs.94).aspx
694 | if (isError(value)
695 | && (keys.indexOf('message') >= 0 || keys.indexOf('description') >= 0)) {
696 | return formatError(value);
697 | }
698 |
699 | // Some type of object without properties can be shortcutted.
700 | if (keys.length === 0) {
701 | if (isFunction(value)) {
702 | var name = value.name ? ': ' + value.name : '';
703 | return ctx.stylize('[Function' + name + ']', 'special');
704 | }
705 | if (isRegExp(value)) {
706 | return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');
707 | }
708 | if (isDate(value)) {
709 | return ctx.stylize(Date.prototype.toString.call(value), 'date');
710 | }
711 | if (isError(value)) {
712 | return formatError(value);
713 | }
714 | }
715 |
716 | var base = '', array = false, braces = ['{', '}'];
717 |
718 | // Make Array say that they are Array
719 | if (isArray(value)) {
720 | array = true;
721 | braces = ['[', ']'];
722 | }
723 |
724 | // Make functions say that they are functions
725 | if (isFunction(value)) {
726 | var n = value.name ? ': ' + value.name : '';
727 | base = ' [Function' + n + ']';
728 | }
729 |
730 | // Make RegExps say that they are RegExps
731 | if (isRegExp(value)) {
732 | base = ' ' + RegExp.prototype.toString.call(value);
733 | }
734 |
735 | // Make dates with properties first say the date
736 | if (isDate(value)) {
737 | base = ' ' + Date.prototype.toUTCString.call(value);
738 | }
739 |
740 | // Make error with message first say the error
741 | if (isError(value)) {
742 | base = ' ' + formatError(value);
743 | }
744 |
745 | if (keys.length === 0 && (!array || value.length == 0)) {
746 | return braces[0] + base + braces[1];
747 | }
748 |
749 | if (recurseTimes < 0) {
750 | if (isRegExp(value)) {
751 | return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');
752 | } else {
753 | return ctx.stylize('[Object]', 'special');
754 | }
755 | }
756 |
757 | ctx.seen.push(value);
758 |
759 | var output;
760 | if (array) {
761 | output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);
762 | } else {
763 | output = keys.map(function(key) {
764 | return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);
765 | });
766 | }
767 |
768 | ctx.seen.pop();
769 |
770 | return reduceToSingleString(output, base, braces);
771 | }
772 |
773 |
774 | function formatPrimitive(ctx, value) {
775 | if (isUndefined(value))
776 | return ctx.stylize('undefined', 'undefined');
777 | if (isString(value)) {
778 | var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '')
779 | .replace(/'/g, "\\'")
780 | .replace(/\\"/g, '"') + '\'';
781 | return ctx.stylize(simple, 'string');
782 | }
783 | if (isNumber(value))
784 | return ctx.stylize('' + value, 'number');
785 | if (isBoolean(value))
786 | return ctx.stylize('' + value, 'boolean');
787 | // For some reason typeof null is "object", so special case here.
788 | if (isNull(value))
789 | return ctx.stylize('null', 'null');
790 | }
791 |
792 |
793 | function formatError(value) {
794 | return '[' + Error.prototype.toString.call(value) + ']';
795 | }
796 |
797 |
798 | function formatArray(ctx, value, recurseTimes, visibleKeys, keys) {
799 | var output = [];
800 | for (var i = 0, l = value.length; i < l; ++i) {
801 | if (hasOwnProperty(value, String(i))) {
802 | output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,
803 | String(i), true));
804 | } else {
805 | output.push('');
806 | }
807 | }
808 | keys.forEach(function(key) {
809 | if (!key.match(/^\d+$/)) {
810 | output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,
811 | key, true));
812 | }
813 | });
814 | return output;
815 | }
816 |
817 |
818 | function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {
819 | var name, str, desc;
820 | desc = Object.getOwnPropertyDescriptor(value, key) || { value: value[key] };
821 | if (desc.get) {
822 | if (desc.set) {
823 | str = ctx.stylize('[Getter/Setter]', 'special');
824 | } else {
825 | str = ctx.stylize('[Getter]', 'special');
826 | }
827 | } else {
828 | if (desc.set) {
829 | str = ctx.stylize('[Setter]', 'special');
830 | }
831 | }
832 | if (!hasOwnProperty(visibleKeys, key)) {
833 | name = '[' + key + ']';
834 | }
835 | if (!str) {
836 | if (ctx.seen.indexOf(desc.value) < 0) {
837 | if (isNull(recurseTimes)) {
838 | str = formatValue(ctx, desc.value, null);
839 | } else {
840 | str = formatValue(ctx, desc.value, recurseTimes - 1);
841 | }
842 | if (str.indexOf('\n') > -1) {
843 | if (array) {
844 | str = str.split('\n').map(function(line) {
845 | return ' ' + line;
846 | }).join('\n').substr(2);
847 | } else {
848 | str = '\n' + str.split('\n').map(function(line) {
849 | return ' ' + line;
850 | }).join('\n');
851 | }
852 | }
853 | } else {
854 | str = ctx.stylize('[Circular]', 'special');
855 | }
856 | }
857 | if (isUndefined(name)) {
858 | if (array && key.match(/^\d+$/)) {
859 | return str;
860 | }
861 | name = JSON.stringify('' + key);
862 | if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) {
863 | name = name.substr(1, name.length - 2);
864 | name = ctx.stylize(name, 'name');
865 | } else {
866 | name = name.replace(/'/g, "\\'")
867 | .replace(/\\"/g, '"')
868 | .replace(/(^"|"$)/g, "'");
869 | name = ctx.stylize(name, 'string');
870 | }
871 | }
872 |
873 | return name + ': ' + str;
874 | }
875 |
876 |
877 | function reduceToSingleString(output, base, braces) {
878 | var numLinesEst = 0;
879 | var length = output.reduce(function(prev, cur) {
880 | numLinesEst++;
881 | if (cur.indexOf('\n') >= 0) numLinesEst++;
882 | return prev + cur.replace(/\u001b\[\d\d?m/g, '').length + 1;
883 | }, 0);
884 |
885 | if (length > 60) {
886 | return braces[0] +
887 | (base === '' ? '' : base + '\n ') +
888 | ' ' +
889 | output.join(',\n ') +
890 | ' ' +
891 | braces[1];
892 | }
893 |
894 | return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];
895 | }
896 |
897 |
898 | // NOTE: These type checking functions intentionally don't use `instanceof`
899 | // because it is fragile and can be easily faked with `Object.create()`.
900 | function isArray(ar) {
901 | return Array.isArray(ar);
902 | }
903 | exports.isArray = isArray;
904 |
905 | function isBoolean(arg) {
906 | return typeof arg === 'boolean';
907 | }
908 | exports.isBoolean = isBoolean;
909 |
910 | function isNull(arg) {
911 | return arg === null;
912 | }
913 | exports.isNull = isNull;
914 |
915 | function isNullOrUndefined(arg) {
916 | return arg == null;
917 | }
918 | exports.isNullOrUndefined = isNullOrUndefined;
919 |
920 | function isNumber(arg) {
921 | return typeof arg === 'number';
922 | }
923 | exports.isNumber = isNumber;
924 |
925 | function isString(arg) {
926 | return typeof arg === 'string';
927 | }
928 | exports.isString = isString;
929 |
930 | function isSymbol(arg) {
931 | return typeof arg === 'symbol';
932 | }
933 | exports.isSymbol = isSymbol;
934 |
935 | function isUndefined(arg) {
936 | return arg === void 0;
937 | }
938 | exports.isUndefined = isUndefined;
939 |
940 | function isRegExp(re) {
941 | return isObject(re) && objectToString(re) === '[object RegExp]';
942 | }
943 | exports.isRegExp = isRegExp;
944 |
945 | function isObject(arg) {
946 | return typeof arg === 'object' && arg !== null;
947 | }
948 | exports.isObject = isObject;
949 |
950 | function isDate(d) {
951 | return isObject(d) && objectToString(d) === '[object Date]';
952 | }
953 | exports.isDate = isDate;
954 |
955 | function isError(e) {
956 | return isObject(e) &&
957 | (objectToString(e) === '[object Error]' || e instanceof Error);
958 | }
959 | exports.isError = isError;
960 |
961 | function isFunction(arg) {
962 | return typeof arg === 'function';
963 | }
964 | exports.isFunction = isFunction;
965 |
966 | function isPrimitive(arg) {
967 | return arg === null ||
968 | typeof arg === 'boolean' ||
969 | typeof arg === 'number' ||
970 | typeof arg === 'string' ||
971 | typeof arg === 'symbol' || // ES6 symbol
972 | typeof arg === 'undefined';
973 | }
974 | exports.isPrimitive = isPrimitive;
975 |
976 | exports.isBuffer = _dereq_('./support/isBuffer');
977 |
978 | function objectToString(o) {
979 | return Object.prototype.toString.call(o);
980 | }
981 |
982 |
983 | function pad(n) {
984 | return n < 10 ? '0' + n.toString(10) : n.toString(10);
985 | }
986 |
987 |
988 | var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
989 | 'Oct', 'Nov', 'Dec'];
990 |
991 | // 26 Feb 16:19:34
992 | function timestamp() {
993 | var d = new Date();
994 | var time = [pad(d.getHours()),
995 | pad(d.getMinutes()),
996 | pad(d.getSeconds())].join(':');
997 | return [d.getDate(), months[d.getMonth()], time].join(' ');
998 | }
999 |
1000 |
1001 | // log is just a thin wrapper to console.log that prepends a timestamp
1002 | exports.log = function() {
1003 | console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments));
1004 | };
1005 |
1006 |
1007 | /**
1008 | * Inherit the prototype methods from one constructor into another.
1009 | *
1010 | * The Function.prototype.inherits from lang.js rewritten as a standalone
1011 | * function (not on Function.prototype). NOTE: If this file is to be loaded
1012 | * during bootstrapping this function needs to be rewritten using some native
1013 | * functions as prototype setup using normal JavaScript does not work as
1014 | * expected during bootstrapping (see mirror.js in r114903).
1015 | *
1016 | * @param {function} ctor Constructor function which needs to inherit the
1017 | * prototype.
1018 | * @param {function} superCtor Constructor function to inherit prototype from.
1019 | */
1020 | exports.inherits = _dereq_('inherits');
1021 |
1022 | exports._extend = function(origin, add) {
1023 | // Don't do anything if add isn't an object
1024 | if (!add || !isObject(add)) return origin;
1025 |
1026 | var keys = Object.keys(add);
1027 | var i = keys.length;
1028 | while (i--) {
1029 | origin[keys[i]] = add[keys[i]];
1030 | }
1031 | return origin;
1032 | };
1033 |
1034 | function hasOwnProperty(obj, prop) {
1035 | return Object.prototype.hasOwnProperty.call(obj, prop);
1036 | }
1037 | }).call(this,_dereq_("/Users/toddanderson/Documents/workspace/custardbelly/cucumberjs-browser/node_modules/browserify/node_modules/insert-module-globals/node_modules/process/browser.js"),typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
1038 | },{"./support/isBuffer":4,"/Users/toddanderson/Documents/workspace/custardbelly/cucumberjs-browser/node_modules/browserify/node_modules/insert-module-globals/node_modules/process/browser.js":3,"inherits":2}],6:[function(_dereq_,module,exports){
1039 | var assert = _dereq_('assert');
1040 |
1041 | module.exports = function() {
1042 | 'use strict';
1043 |
1044 | var enteredItem;
1045 |
1046 | this.World = _dereq_('../support/world').World;
1047 |
1048 | this.Given(/^I have an empty grocery list view$/, function(callback) {
1049 | this.emptyGroceryListView();
1050 | assert.equal(this.getGroceryListView().childNodes.length, 0);
1051 | callback();
1052 | });
1053 |
1054 | this.When(/^I provide a valid grocery list item name$/, function(callback) {
1055 | enteredItem = this.createGroceryItem();
1056 | this.enterNewGorceryListItem(enteredItem);
1057 | callback();
1058 | });
1059 |
1060 | this.When(/^I select to add an item$/, function(callback) {
1061 | this.clickAddGroceryListItem();
1062 | callback();
1063 | });
1064 |
1065 | this.Then(/^The item is added to the grocery list view$/, function(callback) {
1066 | assert.equal(this.getGroceryListViewItemAtIndex(0), enteredItem, 'Entered item should be first in empty list.');
1067 | callback();
1068 | });
1069 |
1070 | this.Then(/^The item is accessible from the grocery list collection$/, function(callback) {
1071 | assert.equal(this.groceryListApplication.list.getItemIndex(enteredItem), 0, 'Added item should be found at first index.');
1072 | callback();
1073 | });
1074 |
1075 | };
1076 | },{"../support/world":7,"assert":1}],7:[function(_dereq_,module,exports){
1077 | (function (process){/*global window, document*/
1078 | 'use strict';
1079 |
1080 | var World = function World(callback) {
1081 |
1082 | this.window = process.browser ? window : {};
1083 | this.app = undefined;
1084 | this.groceryListApplication = undefined;
1085 |
1086 | var defineGlobals = function(w, doc) {
1087 | this.app = w.app;
1088 | };
1089 |
1090 | this.domload = function(callback) {
1091 | (function(world) {
1092 | if(document.readyState === 'complete') {
1093 | defineGlobals.call(world, window, document);
1094 | callback();
1095 | }
1096 | else {
1097 | var delegate = document.addEventListener ? 'addEventListener' : 'attachEvent';
1098 | var eventType = document.addEventListener ? 'load' : 'onload';
1099 | window[delegate](eventType, function() {
1100 | defineGlobals.call(world, window, document);
1101 | callback();
1102 | });
1103 | }
1104 | }(this));
1105 | };
1106 |
1107 | this.openGroceryList = function() {
1108 | return this.app.newSession();
1109 | };
1110 | this.createGroceryItem = function() {
1111 | return 'apple';
1112 | };
1113 |
1114 | this.getGroceryListView = function() {
1115 | return this.groceryListApplication.$listview;
1116 | };
1117 |
1118 | this.getGroceryListViewItemAtIndex = function(index) {
1119 | return this.groceryListApplication.$listview.childNodes[index].textContent;
1120 | }
1121 |
1122 | this.emptyGroceryListView = function() {
1123 | this.groceryListApplication.empty();
1124 | };
1125 |
1126 | this.enterNewGorceryListItem = function(item) {
1127 | this.groceryListApplication.enterNewItem(item);
1128 | };
1129 |
1130 | this.createClickEvent = function() {
1131 | var event = document.createEvent('MouseEvents');
1132 | event.initEvent('click', true, false);
1133 | return event;
1134 | };
1135 |
1136 | this.clickAddGroceryListItem = function() {
1137 | var clickevent = this.createClickEvent();
1138 | this.groceryListApplication.$addbutton.dispatchEvent(clickevent);
1139 | };
1140 |
1141 | callback();
1142 |
1143 | };
1144 |
1145 | module.exports.World = World;}).call(this,_dereq_("/Users/toddanderson/Documents/workspace/custardbelly/cucumberjs-browser/node_modules/browserify/node_modules/insert-module-globals/node_modules/process/browser.js"))
1146 | },{"/Users/toddanderson/Documents/workspace/custardbelly/cucumberjs-browser/node_modules/browserify/node_modules/insert-module-globals/node_modules/process/browser.js":3}]},{},[6])
1147 | (6)
1148 | });
--------------------------------------------------------------------------------
/test/backgroundOpenApplicationSteps.js:
--------------------------------------------------------------------------------
1 | !function(e){if("object"==typeof exports)module.exports=e();else if("function"==typeof define&&define.amd)define(e);else{var n;"undefined"!=typeof window?n=window:"undefined"!=typeof global?n=global:"undefined"!=typeof self&&(n=self),n.backgroundOpenApplicationSteps=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o
8 | //
9 | // Permission is hereby granted, free of charge, to any person obtaining a copy
10 | // of this software and associated documentation files (the 'Software'), to
11 | // deal in the Software without restriction, including without limitation the
12 | // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
13 | // sell copies of the Software, and to permit persons to whom the Software is
14 | // furnished to do so, subject to the following conditions:
15 | //
16 | // The above copyright notice and this permission notice shall be included in
17 | // all copies or substantial portions of the Software.
18 | //
19 | // THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 | // AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
23 | // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 |
26 | // when used in node, this will actually load the util module we depend on
27 | // versus loading the builtin util module as happens otherwise
28 | // this is a bug in node module loading as far as I am concerned
29 | var util = _dereq_('util/');
30 |
31 | var pSlice = Array.prototype.slice;
32 | var hasOwn = Object.prototype.hasOwnProperty;
33 |
34 | // 1. The assert module provides functions that throw
35 | // AssertionError's when particular conditions are not met. The
36 | // assert module must conform to the following interface.
37 |
38 | var assert = module.exports = ok;
39 |
40 | // 2. The AssertionError is defined in assert.
41 | // new assert.AssertionError({ message: message,
42 | // actual: actual,
43 | // expected: expected })
44 |
45 | assert.AssertionError = function AssertionError(options) {
46 | this.name = 'AssertionError';
47 | this.actual = options.actual;
48 | this.expected = options.expected;
49 | this.operator = options.operator;
50 | if (options.message) {
51 | this.message = options.message;
52 | this.generatedMessage = false;
53 | } else {
54 | this.message = getMessage(this);
55 | this.generatedMessage = true;
56 | }
57 | var stackStartFunction = options.stackStartFunction || fail;
58 |
59 | if (Error.captureStackTrace) {
60 | Error.captureStackTrace(this, stackStartFunction);
61 | }
62 | else {
63 | // non v8 browsers so we can have a stacktrace
64 | var err = new Error();
65 | if (err.stack) {
66 | var out = err.stack;
67 |
68 | // try to strip useless frames
69 | var fn_name = stackStartFunction.name;
70 | var idx = out.indexOf('\n' + fn_name);
71 | if (idx >= 0) {
72 | // once we have located the function frame
73 | // we need to strip out everything before it (and its line)
74 | var next_line = out.indexOf('\n', idx + 1);
75 | out = out.substring(next_line + 1);
76 | }
77 |
78 | this.stack = out;
79 | }
80 | }
81 | };
82 |
83 | // assert.AssertionError instanceof Error
84 | util.inherits(assert.AssertionError, Error);
85 |
86 | function replacer(key, value) {
87 | if (util.isUndefined(value)) {
88 | return '' + value;
89 | }
90 | if (util.isNumber(value) && (isNaN(value) || !isFinite(value))) {
91 | return value.toString();
92 | }
93 | if (util.isFunction(value) || util.isRegExp(value)) {
94 | return value.toString();
95 | }
96 | return value;
97 | }
98 |
99 | function truncate(s, n) {
100 | if (util.isString(s)) {
101 | return s.length < n ? s : s.slice(0, n);
102 | } else {
103 | return s;
104 | }
105 | }
106 |
107 | function getMessage(self) {
108 | return truncate(JSON.stringify(self.actual, replacer), 128) + ' ' +
109 | self.operator + ' ' +
110 | truncate(JSON.stringify(self.expected, replacer), 128);
111 | }
112 |
113 | // At present only the three keys mentioned above are used and
114 | // understood by the spec. Implementations or sub modules can pass
115 | // other keys to the AssertionError's constructor - they will be
116 | // ignored.
117 |
118 | // 3. All of the following functions must throw an AssertionError
119 | // when a corresponding condition is not met, with a message that
120 | // may be undefined if not provided. All assertion methods provide
121 | // both the actual and expected values to the assertion error for
122 | // display purposes.
123 |
124 | function fail(actual, expected, message, operator, stackStartFunction) {
125 | throw new assert.AssertionError({
126 | message: message,
127 | actual: actual,
128 | expected: expected,
129 | operator: operator,
130 | stackStartFunction: stackStartFunction
131 | });
132 | }
133 |
134 | // EXTENSION! allows for well behaved errors defined elsewhere.
135 | assert.fail = fail;
136 |
137 | // 4. Pure assertion tests whether a value is truthy, as determined
138 | // by !!guard.
139 | // assert.ok(guard, message_opt);
140 | // This statement is equivalent to assert.equal(true, !!guard,
141 | // message_opt);. To test strictly for the value true, use
142 | // assert.strictEqual(true, guard, message_opt);.
143 |
144 | function ok(value, message) {
145 | if (!value) fail(value, true, message, '==', assert.ok);
146 | }
147 | assert.ok = ok;
148 |
149 | // 5. The equality assertion tests shallow, coercive equality with
150 | // ==.
151 | // assert.equal(actual, expected, message_opt);
152 |
153 | assert.equal = function equal(actual, expected, message) {
154 | if (actual != expected) fail(actual, expected, message, '==', assert.equal);
155 | };
156 |
157 | // 6. The non-equality assertion tests for whether two objects are not equal
158 | // with != assert.notEqual(actual, expected, message_opt);
159 |
160 | assert.notEqual = function notEqual(actual, expected, message) {
161 | if (actual == expected) {
162 | fail(actual, expected, message, '!=', assert.notEqual);
163 | }
164 | };
165 |
166 | // 7. The equivalence assertion tests a deep equality relation.
167 | // assert.deepEqual(actual, expected, message_opt);
168 |
169 | assert.deepEqual = function deepEqual(actual, expected, message) {
170 | if (!_deepEqual(actual, expected)) {
171 | fail(actual, expected, message, 'deepEqual', assert.deepEqual);
172 | }
173 | };
174 |
175 | function _deepEqual(actual, expected) {
176 | // 7.1. All identical values are equivalent, as determined by ===.
177 | if (actual === expected) {
178 | return true;
179 |
180 | } else if (util.isBuffer(actual) && util.isBuffer(expected)) {
181 | if (actual.length != expected.length) return false;
182 |
183 | for (var i = 0; i < actual.length; i++) {
184 | if (actual[i] !== expected[i]) return false;
185 | }
186 |
187 | return true;
188 |
189 | // 7.2. If the expected value is a Date object, the actual value is
190 | // equivalent if it is also a Date object that refers to the same time.
191 | } else if (util.isDate(actual) && util.isDate(expected)) {
192 | return actual.getTime() === expected.getTime();
193 |
194 | // 7.3 If the expected value is a RegExp object, the actual value is
195 | // equivalent if it is also a RegExp object with the same source and
196 | // properties (`global`, `multiline`, `lastIndex`, `ignoreCase`).
197 | } else if (util.isRegExp(actual) && util.isRegExp(expected)) {
198 | return actual.source === expected.source &&
199 | actual.global === expected.global &&
200 | actual.multiline === expected.multiline &&
201 | actual.lastIndex === expected.lastIndex &&
202 | actual.ignoreCase === expected.ignoreCase;
203 |
204 | // 7.4. Other pairs that do not both pass typeof value == 'object',
205 | // equivalence is determined by ==.
206 | } else if (!util.isObject(actual) && !util.isObject(expected)) {
207 | return actual == expected;
208 |
209 | // 7.5 For all other Object pairs, including Array objects, equivalence is
210 | // determined by having the same number of owned properties (as verified
211 | // with Object.prototype.hasOwnProperty.call), the same set of keys
212 | // (although not necessarily the same order), equivalent values for every
213 | // corresponding key, and an identical 'prototype' property. Note: this
214 | // accounts for both named and indexed properties on Arrays.
215 | } else {
216 | return objEquiv(actual, expected);
217 | }
218 | }
219 |
220 | function isArguments(object) {
221 | return Object.prototype.toString.call(object) == '[object Arguments]';
222 | }
223 |
224 | function objEquiv(a, b) {
225 | if (util.isNullOrUndefined(a) || util.isNullOrUndefined(b))
226 | return false;
227 | // an identical 'prototype' property.
228 | if (a.prototype !== b.prototype) return false;
229 | //~~~I've managed to break Object.keys through screwy arguments passing.
230 | // Converting to array solves the problem.
231 | if (isArguments(a)) {
232 | if (!isArguments(b)) {
233 | return false;
234 | }
235 | a = pSlice.call(a);
236 | b = pSlice.call(b);
237 | return _deepEqual(a, b);
238 | }
239 | try {
240 | var ka = objectKeys(a),
241 | kb = objectKeys(b),
242 | key, i;
243 | } catch (e) {//happens when one is a string literal and the other isn't
244 | return false;
245 | }
246 | // having the same number of owned properties (keys incorporates
247 | // hasOwnProperty)
248 | if (ka.length != kb.length)
249 | return false;
250 | //the same set of keys (although not necessarily the same order),
251 | ka.sort();
252 | kb.sort();
253 | //~~~cheap key test
254 | for (i = ka.length - 1; i >= 0; i--) {
255 | if (ka[i] != kb[i])
256 | return false;
257 | }
258 | //equivalent values for every corresponding key, and
259 | //~~~possibly expensive deep test
260 | for (i = ka.length - 1; i >= 0; i--) {
261 | key = ka[i];
262 | if (!_deepEqual(a[key], b[key])) return false;
263 | }
264 | return true;
265 | }
266 |
267 | // 8. The non-equivalence assertion tests for any deep inequality.
268 | // assert.notDeepEqual(actual, expected, message_opt);
269 |
270 | assert.notDeepEqual = function notDeepEqual(actual, expected, message) {
271 | if (_deepEqual(actual, expected)) {
272 | fail(actual, expected, message, 'notDeepEqual', assert.notDeepEqual);
273 | }
274 | };
275 |
276 | // 9. The strict equality assertion tests strict equality, as determined by ===.
277 | // assert.strictEqual(actual, expected, message_opt);
278 |
279 | assert.strictEqual = function strictEqual(actual, expected, message) {
280 | if (actual !== expected) {
281 | fail(actual, expected, message, '===', assert.strictEqual);
282 | }
283 | };
284 |
285 | // 10. The strict non-equality assertion tests for strict inequality, as
286 | // determined by !==. assert.notStrictEqual(actual, expected, message_opt);
287 |
288 | assert.notStrictEqual = function notStrictEqual(actual, expected, message) {
289 | if (actual === expected) {
290 | fail(actual, expected, message, '!==', assert.notStrictEqual);
291 | }
292 | };
293 |
294 | function expectedException(actual, expected) {
295 | if (!actual || !expected) {
296 | return false;
297 | }
298 |
299 | if (Object.prototype.toString.call(expected) == '[object RegExp]') {
300 | return expected.test(actual);
301 | } else if (actual instanceof expected) {
302 | return true;
303 | } else if (expected.call({}, actual) === true) {
304 | return true;
305 | }
306 |
307 | return false;
308 | }
309 |
310 | function _throws(shouldThrow, block, expected, message) {
311 | var actual;
312 |
313 | if (util.isString(expected)) {
314 | message = expected;
315 | expected = null;
316 | }
317 |
318 | try {
319 | block();
320 | } catch (e) {
321 | actual = e;
322 | }
323 |
324 | message = (expected && expected.name ? ' (' + expected.name + ').' : '.') +
325 | (message ? ' ' + message : '.');
326 |
327 | if (shouldThrow && !actual) {
328 | fail(actual, expected, 'Missing expected exception' + message);
329 | }
330 |
331 | if (!shouldThrow && expectedException(actual, expected)) {
332 | fail(actual, expected, 'Got unwanted exception' + message);
333 | }
334 |
335 | if ((shouldThrow && actual && expected &&
336 | !expectedException(actual, expected)) || (!shouldThrow && actual)) {
337 | throw actual;
338 | }
339 | }
340 |
341 | // 11. Expected to throw an error:
342 | // assert.throws(block, Error_opt, message_opt);
343 |
344 | assert.throws = function(block, /*optional*/error, /*optional*/message) {
345 | _throws.apply(this, [true].concat(pSlice.call(arguments)));
346 | };
347 |
348 | // EXTENSION! This is annoying to write outside this module.
349 | assert.doesNotThrow = function(block, /*optional*/message) {
350 | _throws.apply(this, [false].concat(pSlice.call(arguments)));
351 | };
352 |
353 | assert.ifError = function(err) { if (err) {throw err;}};
354 |
355 | var objectKeys = Object.keys || function (obj) {
356 | var keys = [];
357 | for (var key in obj) {
358 | if (hasOwn.call(obj, key)) keys.push(key);
359 | }
360 | return keys;
361 | };
362 |
363 | },{"util/":5}],2:[function(_dereq_,module,exports){
364 | if (typeof Object.create === 'function') {
365 | // implementation from standard node.js 'util' module
366 | module.exports = function inherits(ctor, superCtor) {
367 | ctor.super_ = superCtor
368 | ctor.prototype = Object.create(superCtor.prototype, {
369 | constructor: {
370 | value: ctor,
371 | enumerable: false,
372 | writable: true,
373 | configurable: true
374 | }
375 | });
376 | };
377 | } else {
378 | // old school shim for old browsers
379 | module.exports = function inherits(ctor, superCtor) {
380 | ctor.super_ = superCtor
381 | var TempCtor = function () {}
382 | TempCtor.prototype = superCtor.prototype
383 | ctor.prototype = new TempCtor()
384 | ctor.prototype.constructor = ctor
385 | }
386 | }
387 |
388 | },{}],3:[function(_dereq_,module,exports){
389 | // shim for using process in browser
390 |
391 | var process = module.exports = {};
392 |
393 | process.nextTick = (function () {
394 | var canSetImmediate = typeof window !== 'undefined'
395 | && window.setImmediate;
396 | var canPost = typeof window !== 'undefined'
397 | && window.postMessage && window.addEventListener
398 | ;
399 |
400 | if (canSetImmediate) {
401 | return function (f) { return window.setImmediate(f) };
402 | }
403 |
404 | if (canPost) {
405 | var queue = [];
406 | window.addEventListener('message', function (ev) {
407 | var source = ev.source;
408 | if ((source === window || source === null) && ev.data === 'process-tick') {
409 | ev.stopPropagation();
410 | if (queue.length > 0) {
411 | var fn = queue.shift();
412 | fn();
413 | }
414 | }
415 | }, true);
416 |
417 | return function nextTick(fn) {
418 | queue.push(fn);
419 | window.postMessage('process-tick', '*');
420 | };
421 | }
422 |
423 | return function nextTick(fn) {
424 | setTimeout(fn, 0);
425 | };
426 | })();
427 |
428 | process.title = 'browser';
429 | process.browser = true;
430 | process.env = {};
431 | process.argv = [];
432 |
433 | process.binding = function (name) {
434 | throw new Error('process.binding is not supported');
435 | }
436 |
437 | // TODO(shtylman)
438 | process.cwd = function () { return '/' };
439 | process.chdir = function (dir) {
440 | throw new Error('process.chdir is not supported');
441 | };
442 |
443 | },{}],4:[function(_dereq_,module,exports){
444 | module.exports = function isBuffer(arg) {
445 | return arg && typeof arg === 'object'
446 | && typeof arg.copy === 'function'
447 | && typeof arg.fill === 'function'
448 | && typeof arg.readUInt8 === 'function';
449 | }
450 | },{}],5:[function(_dereq_,module,exports){
451 | (function (process,global){// Copyright Joyent, Inc. and other Node contributors.
452 | //
453 | // Permission is hereby granted, free of charge, to any person obtaining a
454 | // copy of this software and associated documentation files (the
455 | // "Software"), to deal in the Software without restriction, including
456 | // without limitation the rights to use, copy, modify, merge, publish,
457 | // distribute, sublicense, and/or sell copies of the Software, and to permit
458 | // persons to whom the Software is furnished to do so, subject to the
459 | // following conditions:
460 | //
461 | // The above copyright notice and this permission notice shall be included
462 | // in all copies or substantial portions of the Software.
463 | //
464 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
465 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
466 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
467 | // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
468 | // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
469 | // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
470 | // USE OR OTHER DEALINGS IN THE SOFTWARE.
471 |
472 | var formatRegExp = /%[sdj%]/g;
473 | exports.format = function(f) {
474 | if (!isString(f)) {
475 | var objects = [];
476 | for (var i = 0; i < arguments.length; i++) {
477 | objects.push(inspect(arguments[i]));
478 | }
479 | return objects.join(' ');
480 | }
481 |
482 | var i = 1;
483 | var args = arguments;
484 | var len = args.length;
485 | var str = String(f).replace(formatRegExp, function(x) {
486 | if (x === '%%') return '%';
487 | if (i >= len) return x;
488 | switch (x) {
489 | case '%s': return String(args[i++]);
490 | case '%d': return Number(args[i++]);
491 | case '%j':
492 | try {
493 | return JSON.stringify(args[i++]);
494 | } catch (_) {
495 | return '[Circular]';
496 | }
497 | default:
498 | return x;
499 | }
500 | });
501 | for (var x = args[i]; i < len; x = args[++i]) {
502 | if (isNull(x) || !isObject(x)) {
503 | str += ' ' + x;
504 | } else {
505 | str += ' ' + inspect(x);
506 | }
507 | }
508 | return str;
509 | };
510 |
511 |
512 | // Mark that a method should not be used.
513 | // Returns a modified function which warns once by default.
514 | // If --no-deprecation is set, then it is a no-op.
515 | exports.deprecate = function(fn, msg) {
516 | // Allow for deprecating things in the process of starting up.
517 | if (isUndefined(global.process)) {
518 | return function() {
519 | return exports.deprecate(fn, msg).apply(this, arguments);
520 | };
521 | }
522 |
523 | if (process.noDeprecation === true) {
524 | return fn;
525 | }
526 |
527 | var warned = false;
528 | function deprecated() {
529 | if (!warned) {
530 | if (process.throwDeprecation) {
531 | throw new Error(msg);
532 | } else if (process.traceDeprecation) {
533 | console.trace(msg);
534 | } else {
535 | console.error(msg);
536 | }
537 | warned = true;
538 | }
539 | return fn.apply(this, arguments);
540 | }
541 |
542 | return deprecated;
543 | };
544 |
545 |
546 | var debugs = {};
547 | var debugEnviron;
548 | exports.debuglog = function(set) {
549 | if (isUndefined(debugEnviron))
550 | debugEnviron = process.env.NODE_DEBUG || '';
551 | set = set.toUpperCase();
552 | if (!debugs[set]) {
553 | if (new RegExp('\\b' + set + '\\b', 'i').test(debugEnviron)) {
554 | var pid = process.pid;
555 | debugs[set] = function() {
556 | var msg = exports.format.apply(exports, arguments);
557 | console.error('%s %d: %s', set, pid, msg);
558 | };
559 | } else {
560 | debugs[set] = function() {};
561 | }
562 | }
563 | return debugs[set];
564 | };
565 |
566 |
567 | /**
568 | * Echos the value of a value. Trys to print the value out
569 | * in the best way possible given the different types.
570 | *
571 | * @param {Object} obj The object to print out.
572 | * @param {Object} opts Optional options object that alters the output.
573 | */
574 | /* legacy: obj, showHidden, depth, colors*/
575 | function inspect(obj, opts) {
576 | // default options
577 | var ctx = {
578 | seen: [],
579 | stylize: stylizeNoColor
580 | };
581 | // legacy...
582 | if (arguments.length >= 3) ctx.depth = arguments[2];
583 | if (arguments.length >= 4) ctx.colors = arguments[3];
584 | if (isBoolean(opts)) {
585 | // legacy...
586 | ctx.showHidden = opts;
587 | } else if (opts) {
588 | // got an "options" object
589 | exports._extend(ctx, opts);
590 | }
591 | // set default options
592 | if (isUndefined(ctx.showHidden)) ctx.showHidden = false;
593 | if (isUndefined(ctx.depth)) ctx.depth = 2;
594 | if (isUndefined(ctx.colors)) ctx.colors = false;
595 | if (isUndefined(ctx.customInspect)) ctx.customInspect = true;
596 | if (ctx.colors) ctx.stylize = stylizeWithColor;
597 | return formatValue(ctx, obj, ctx.depth);
598 | }
599 | exports.inspect = inspect;
600 |
601 |
602 | // http://en.wikipedia.org/wiki/ANSI_escape_code#graphics
603 | inspect.colors = {
604 | 'bold' : [1, 22],
605 | 'italic' : [3, 23],
606 | 'underline' : [4, 24],
607 | 'inverse' : [7, 27],
608 | 'white' : [37, 39],
609 | 'grey' : [90, 39],
610 | 'black' : [30, 39],
611 | 'blue' : [34, 39],
612 | 'cyan' : [36, 39],
613 | 'green' : [32, 39],
614 | 'magenta' : [35, 39],
615 | 'red' : [31, 39],
616 | 'yellow' : [33, 39]
617 | };
618 |
619 | // Don't use 'blue' not visible on cmd.exe
620 | inspect.styles = {
621 | 'special': 'cyan',
622 | 'number': 'yellow',
623 | 'boolean': 'yellow',
624 | 'undefined': 'grey',
625 | 'null': 'bold',
626 | 'string': 'green',
627 | 'date': 'magenta',
628 | // "name": intentionally not styling
629 | 'regexp': 'red'
630 | };
631 |
632 |
633 | function stylizeWithColor(str, styleType) {
634 | var style = inspect.styles[styleType];
635 |
636 | if (style) {
637 | return '\u001b[' + inspect.colors[style][0] + 'm' + str +
638 | '\u001b[' + inspect.colors[style][1] + 'm';
639 | } else {
640 | return str;
641 | }
642 | }
643 |
644 |
645 | function stylizeNoColor(str, styleType) {
646 | return str;
647 | }
648 |
649 |
650 | function arrayToHash(array) {
651 | var hash = {};
652 |
653 | array.forEach(function(val, idx) {
654 | hash[val] = true;
655 | });
656 |
657 | return hash;
658 | }
659 |
660 |
661 | function formatValue(ctx, value, recurseTimes) {
662 | // Provide a hook for user-specified inspect functions.
663 | // Check that value is an object with an inspect function on it
664 | if (ctx.customInspect &&
665 | value &&
666 | isFunction(value.inspect) &&
667 | // Filter out the util module, it's inspect function is special
668 | value.inspect !== exports.inspect &&
669 | // Also filter out any prototype objects using the circular check.
670 | !(value.constructor && value.constructor.prototype === value)) {
671 | var ret = value.inspect(recurseTimes, ctx);
672 | if (!isString(ret)) {
673 | ret = formatValue(ctx, ret, recurseTimes);
674 | }
675 | return ret;
676 | }
677 |
678 | // Primitive types cannot have properties
679 | var primitive = formatPrimitive(ctx, value);
680 | if (primitive) {
681 | return primitive;
682 | }
683 |
684 | // Look up the keys of the object.
685 | var keys = Object.keys(value);
686 | var visibleKeys = arrayToHash(keys);
687 |
688 | if (ctx.showHidden) {
689 | keys = Object.getOwnPropertyNames(value);
690 | }
691 |
692 | // IE doesn't make error fields non-enumerable
693 | // http://msdn.microsoft.com/en-us/library/ie/dww52sbt(v=vs.94).aspx
694 | if (isError(value)
695 | && (keys.indexOf('message') >= 0 || keys.indexOf('description') >= 0)) {
696 | return formatError(value);
697 | }
698 |
699 | // Some type of object without properties can be shortcutted.
700 | if (keys.length === 0) {
701 | if (isFunction(value)) {
702 | var name = value.name ? ': ' + value.name : '';
703 | return ctx.stylize('[Function' + name + ']', 'special');
704 | }
705 | if (isRegExp(value)) {
706 | return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');
707 | }
708 | if (isDate(value)) {
709 | return ctx.stylize(Date.prototype.toString.call(value), 'date');
710 | }
711 | if (isError(value)) {
712 | return formatError(value);
713 | }
714 | }
715 |
716 | var base = '', array = false, braces = ['{', '}'];
717 |
718 | // Make Array say that they are Array
719 | if (isArray(value)) {
720 | array = true;
721 | braces = ['[', ']'];
722 | }
723 |
724 | // Make functions say that they are functions
725 | if (isFunction(value)) {
726 | var n = value.name ? ': ' + value.name : '';
727 | base = ' [Function' + n + ']';
728 | }
729 |
730 | // Make RegExps say that they are RegExps
731 | if (isRegExp(value)) {
732 | base = ' ' + RegExp.prototype.toString.call(value);
733 | }
734 |
735 | // Make dates with properties first say the date
736 | if (isDate(value)) {
737 | base = ' ' + Date.prototype.toUTCString.call(value);
738 | }
739 |
740 | // Make error with message first say the error
741 | if (isError(value)) {
742 | base = ' ' + formatError(value);
743 | }
744 |
745 | if (keys.length === 0 && (!array || value.length == 0)) {
746 | return braces[0] + base + braces[1];
747 | }
748 |
749 | if (recurseTimes < 0) {
750 | if (isRegExp(value)) {
751 | return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');
752 | } else {
753 | return ctx.stylize('[Object]', 'special');
754 | }
755 | }
756 |
757 | ctx.seen.push(value);
758 |
759 | var output;
760 | if (array) {
761 | output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);
762 | } else {
763 | output = keys.map(function(key) {
764 | return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);
765 | });
766 | }
767 |
768 | ctx.seen.pop();
769 |
770 | return reduceToSingleString(output, base, braces);
771 | }
772 |
773 |
774 | function formatPrimitive(ctx, value) {
775 | if (isUndefined(value))
776 | return ctx.stylize('undefined', 'undefined');
777 | if (isString(value)) {
778 | var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '')
779 | .replace(/'/g, "\\'")
780 | .replace(/\\"/g, '"') + '\'';
781 | return ctx.stylize(simple, 'string');
782 | }
783 | if (isNumber(value))
784 | return ctx.stylize('' + value, 'number');
785 | if (isBoolean(value))
786 | return ctx.stylize('' + value, 'boolean');
787 | // For some reason typeof null is "object", so special case here.
788 | if (isNull(value))
789 | return ctx.stylize('null', 'null');
790 | }
791 |
792 |
793 | function formatError(value) {
794 | return '[' + Error.prototype.toString.call(value) + ']';
795 | }
796 |
797 |
798 | function formatArray(ctx, value, recurseTimes, visibleKeys, keys) {
799 | var output = [];
800 | for (var i = 0, l = value.length; i < l; ++i) {
801 | if (hasOwnProperty(value, String(i))) {
802 | output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,
803 | String(i), true));
804 | } else {
805 | output.push('');
806 | }
807 | }
808 | keys.forEach(function(key) {
809 | if (!key.match(/^\d+$/)) {
810 | output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,
811 | key, true));
812 | }
813 | });
814 | return output;
815 | }
816 |
817 |
818 | function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {
819 | var name, str, desc;
820 | desc = Object.getOwnPropertyDescriptor(value, key) || { value: value[key] };
821 | if (desc.get) {
822 | if (desc.set) {
823 | str = ctx.stylize('[Getter/Setter]', 'special');
824 | } else {
825 | str = ctx.stylize('[Getter]', 'special');
826 | }
827 | } else {
828 | if (desc.set) {
829 | str = ctx.stylize('[Setter]', 'special');
830 | }
831 | }
832 | if (!hasOwnProperty(visibleKeys, key)) {
833 | name = '[' + key + ']';
834 | }
835 | if (!str) {
836 | if (ctx.seen.indexOf(desc.value) < 0) {
837 | if (isNull(recurseTimes)) {
838 | str = formatValue(ctx, desc.value, null);
839 | } else {
840 | str = formatValue(ctx, desc.value, recurseTimes - 1);
841 | }
842 | if (str.indexOf('\n') > -1) {
843 | if (array) {
844 | str = str.split('\n').map(function(line) {
845 | return ' ' + line;
846 | }).join('\n').substr(2);
847 | } else {
848 | str = '\n' + str.split('\n').map(function(line) {
849 | return ' ' + line;
850 | }).join('\n');
851 | }
852 | }
853 | } else {
854 | str = ctx.stylize('[Circular]', 'special');
855 | }
856 | }
857 | if (isUndefined(name)) {
858 | if (array && key.match(/^\d+$/)) {
859 | return str;
860 | }
861 | name = JSON.stringify('' + key);
862 | if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) {
863 | name = name.substr(1, name.length - 2);
864 | name = ctx.stylize(name, 'name');
865 | } else {
866 | name = name.replace(/'/g, "\\'")
867 | .replace(/\\"/g, '"')
868 | .replace(/(^"|"$)/g, "'");
869 | name = ctx.stylize(name, 'string');
870 | }
871 | }
872 |
873 | return name + ': ' + str;
874 | }
875 |
876 |
877 | function reduceToSingleString(output, base, braces) {
878 | var numLinesEst = 0;
879 | var length = output.reduce(function(prev, cur) {
880 | numLinesEst++;
881 | if (cur.indexOf('\n') >= 0) numLinesEst++;
882 | return prev + cur.replace(/\u001b\[\d\d?m/g, '').length + 1;
883 | }, 0);
884 |
885 | if (length > 60) {
886 | return braces[0] +
887 | (base === '' ? '' : base + '\n ') +
888 | ' ' +
889 | output.join(',\n ') +
890 | ' ' +
891 | braces[1];
892 | }
893 |
894 | return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];
895 | }
896 |
897 |
898 | // NOTE: These type checking functions intentionally don't use `instanceof`
899 | // because it is fragile and can be easily faked with `Object.create()`.
900 | function isArray(ar) {
901 | return Array.isArray(ar);
902 | }
903 | exports.isArray = isArray;
904 |
905 | function isBoolean(arg) {
906 | return typeof arg === 'boolean';
907 | }
908 | exports.isBoolean = isBoolean;
909 |
910 | function isNull(arg) {
911 | return arg === null;
912 | }
913 | exports.isNull = isNull;
914 |
915 | function isNullOrUndefined(arg) {
916 | return arg == null;
917 | }
918 | exports.isNullOrUndefined = isNullOrUndefined;
919 |
920 | function isNumber(arg) {
921 | return typeof arg === 'number';
922 | }
923 | exports.isNumber = isNumber;
924 |
925 | function isString(arg) {
926 | return typeof arg === 'string';
927 | }
928 | exports.isString = isString;
929 |
930 | function isSymbol(arg) {
931 | return typeof arg === 'symbol';
932 | }
933 | exports.isSymbol = isSymbol;
934 |
935 | function isUndefined(arg) {
936 | return arg === void 0;
937 | }
938 | exports.isUndefined = isUndefined;
939 |
940 | function isRegExp(re) {
941 | return isObject(re) && objectToString(re) === '[object RegExp]';
942 | }
943 | exports.isRegExp = isRegExp;
944 |
945 | function isObject(arg) {
946 | return typeof arg === 'object' && arg !== null;
947 | }
948 | exports.isObject = isObject;
949 |
950 | function isDate(d) {
951 | return isObject(d) && objectToString(d) === '[object Date]';
952 | }
953 | exports.isDate = isDate;
954 |
955 | function isError(e) {
956 | return isObject(e) &&
957 | (objectToString(e) === '[object Error]' || e instanceof Error);
958 | }
959 | exports.isError = isError;
960 |
961 | function isFunction(arg) {
962 | return typeof arg === 'function';
963 | }
964 | exports.isFunction = isFunction;
965 |
966 | function isPrimitive(arg) {
967 | return arg === null ||
968 | typeof arg === 'boolean' ||
969 | typeof arg === 'number' ||
970 | typeof arg === 'string' ||
971 | typeof arg === 'symbol' || // ES6 symbol
972 | typeof arg === 'undefined';
973 | }
974 | exports.isPrimitive = isPrimitive;
975 |
976 | exports.isBuffer = _dereq_('./support/isBuffer');
977 |
978 | function objectToString(o) {
979 | return Object.prototype.toString.call(o);
980 | }
981 |
982 |
983 | function pad(n) {
984 | return n < 10 ? '0' + n.toString(10) : n.toString(10);
985 | }
986 |
987 |
988 | var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
989 | 'Oct', 'Nov', 'Dec'];
990 |
991 | // 26 Feb 16:19:34
992 | function timestamp() {
993 | var d = new Date();
994 | var time = [pad(d.getHours()),
995 | pad(d.getMinutes()),
996 | pad(d.getSeconds())].join(':');
997 | return [d.getDate(), months[d.getMonth()], time].join(' ');
998 | }
999 |
1000 |
1001 | // log is just a thin wrapper to console.log that prepends a timestamp
1002 | exports.log = function() {
1003 | console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments));
1004 | };
1005 |
1006 |
1007 | /**
1008 | * Inherit the prototype methods from one constructor into another.
1009 | *
1010 | * The Function.prototype.inherits from lang.js rewritten as a standalone
1011 | * function (not on Function.prototype). NOTE: If this file is to be loaded
1012 | * during bootstrapping this function needs to be rewritten using some native
1013 | * functions as prototype setup using normal JavaScript does not work as
1014 | * expected during bootstrapping (see mirror.js in r114903).
1015 | *
1016 | * @param {function} ctor Constructor function which needs to inherit the
1017 | * prototype.
1018 | * @param {function} superCtor Constructor function to inherit prototype from.
1019 | */
1020 | exports.inherits = _dereq_('inherits');
1021 |
1022 | exports._extend = function(origin, add) {
1023 | // Don't do anything if add isn't an object
1024 | if (!add || !isObject(add)) return origin;
1025 |
1026 | var keys = Object.keys(add);
1027 | var i = keys.length;
1028 | while (i--) {
1029 | origin[keys[i]] = add[keys[i]];
1030 | }
1031 | return origin;
1032 | };
1033 |
1034 | function hasOwnProperty(obj, prop) {
1035 | return Object.prototype.hasOwnProperty.call(obj, prop);
1036 | }
1037 | }).call(this,_dereq_("/Users/toddanderson/Documents/workspace/custardbelly/cucumberjs-browser/node_modules/browserify/node_modules/insert-module-globals/node_modules/process/browser.js"),typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
1038 | },{"./support/isBuffer":4,"/Users/toddanderson/Documents/workspace/custardbelly/cucumberjs-browser/node_modules/browserify/node_modules/insert-module-globals/node_modules/process/browser.js":3,"inherits":2}],6:[function(_dereq_,module,exports){
1039 | 'use strict';
1040 | var assert = _dereq_('assert');
1041 |
1042 | module.exports = function() {
1043 |
1044 | this.World = _dereq_('../support/world').World;
1045 |
1046 | this.Given(/^I have opened the grocery list application$/, function(callback) {
1047 | (function(world) {
1048 | world.domload(function() {
1049 | world.groceryListApplication = world.openGroceryList();
1050 | assert(world.groceryListApplication, 'Grocery List Application is required to be open for editability.');
1051 | callback();
1052 | });
1053 | }(this));
1054 | });
1055 |
1056 | };
1057 | },{"../support/world":7,"assert":1}],7:[function(_dereq_,module,exports){
1058 | (function (process){/*global window, document*/
1059 | 'use strict';
1060 |
1061 | var World = function World(callback) {
1062 |
1063 | this.window = process.browser ? window : {};
1064 | this.app = undefined;
1065 | this.groceryListApplication = undefined;
1066 |
1067 | var defineGlobals = function(w, doc) {
1068 | this.app = w.app;
1069 | };
1070 |
1071 | this.domload = function(callback) {
1072 | (function(world) {
1073 | if(document.readyState === 'complete') {
1074 | defineGlobals.call(world, window, document);
1075 | callback();
1076 | }
1077 | else {
1078 | var delegate = document.addEventListener ? 'addEventListener' : 'attachEvent';
1079 | var eventType = document.addEventListener ? 'load' : 'onload';
1080 | window[delegate](eventType, function() {
1081 | defineGlobals.call(world, window, document);
1082 | callback();
1083 | });
1084 | }
1085 | }(this));
1086 | };
1087 |
1088 | this.openGroceryList = function() {
1089 | return this.app.newSession();
1090 | };
1091 | this.createGroceryItem = function() {
1092 | return 'apple';
1093 | };
1094 |
1095 | this.getGroceryListView = function() {
1096 | return this.groceryListApplication.$listview;
1097 | };
1098 |
1099 | this.getGroceryListViewItemAtIndex = function(index) {
1100 | return this.groceryListApplication.$listview.childNodes[index].textContent;
1101 | }
1102 |
1103 | this.emptyGroceryListView = function() {
1104 | this.groceryListApplication.empty();
1105 | };
1106 |
1107 | this.enterNewGorceryListItem = function(item) {
1108 | this.groceryListApplication.enterNewItem(item);
1109 | };
1110 |
1111 | this.createClickEvent = function() {
1112 | var event = document.createEvent('MouseEvents');
1113 | event.initEvent('click', true, false);
1114 | return event;
1115 | };
1116 |
1117 | this.clickAddGroceryListItem = function() {
1118 | var clickevent = this.createClickEvent();
1119 | this.groceryListApplication.$addbutton.dispatchEvent(clickevent);
1120 | };
1121 |
1122 | callback();
1123 |
1124 | };
1125 |
1126 | module.exports.World = World;}).call(this,_dereq_("/Users/toddanderson/Documents/workspace/custardbelly/cucumberjs-browser/node_modules/browserify/node_modules/insert-module-globals/node_modules/process/browser.js"))
1127 | },{"/Users/toddanderson/Documents/workspace/custardbelly/cucumberjs-browser/node_modules/browserify/node_modules/insert-module-globals/node_modules/process/browser.js":3}]},{},[6])
1128 | (6)
1129 | });
--------------------------------------------------------------------------------
/test/cucumber-testrunner.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
56 |
57 |
62 |
63 |
64 |
--------------------------------------------------------------------------------
/test/features.js:
--------------------------------------------------------------------------------
1 | !function(e){if("object"==typeof exports)module.exports=e();else if("function"==typeof define&&define.amd)define(e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.cukefeatures=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o -1) {
62 | if(this.list[index] === value) {
63 | return index;
64 | }
65 | }
66 | return -1;
67 | }
68 | };
69 |
70 | module.exports = {
71 | create: function() {
72 | return Object.create(groceryList, {
73 | 'list': {
74 | value: [],
75 | writable: false,
76 | enumerable: true
77 | }
78 | });
79 | }
80 | };
81 | },{}]},{},[1])
82 | (1)
83 | });
--------------------------------------------------------------------------------
/test/world.js:
--------------------------------------------------------------------------------
1 | !function(e){if("object"==typeof exports)module.exports=e();else if("function"==typeof define&&define.amd)define(e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.world=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o 0) {
24 | var fn = queue.shift();
25 | fn();
26 | }
27 | }
28 | }, true);
29 |
30 | return function nextTick(fn) {
31 | queue.push(fn);
32 | window.postMessage('process-tick', '*');
33 | };
34 | }
35 |
36 | return function nextTick(fn) {
37 | setTimeout(fn, 0);
38 | };
39 | })();
40 |
41 | process.title = 'browser';
42 | process.browser = true;
43 | process.env = {};
44 | process.argv = [];
45 |
46 | process.binding = function (name) {
47 | throw new Error('process.binding is not supported');
48 | }
49 |
50 | // TODO(shtylman)
51 | process.cwd = function () { return '/' };
52 | process.chdir = function (dir) {
53 | throw new Error('process.chdir is not supported');
54 | };
55 |
56 | },{}],2:[function(_dereq_,module,exports){
57 | (function (process){/*global window, document*/
58 | 'use strict';
59 |
60 | var World = function World(callback) {
61 |
62 | this.window = process.browser ? window : {};
63 | this.app = undefined;
64 | this.groceryListApplication = undefined;
65 |
66 | var defineGlobals = function(w, doc) {
67 | this.app = w.app;
68 | };
69 |
70 | this.domload = function(callback) {
71 | (function(world) {
72 | if(document.readyState === 'complete') {
73 | defineGlobals.call(world, window, document);
74 | callback();
75 | }
76 | else {
77 | var delegate = document.addEventListener ? 'addEventListener' : 'attachEvent';
78 | var eventType = document.addEventListener ? 'load' : 'onload';
79 | window[delegate](eventType, function() {
80 | defineGlobals.call(world, window, document);
81 | callback();
82 | });
83 | }
84 | }(this));
85 | };
86 |
87 | this.openGroceryList = function() {
88 | return this.app.newSession();
89 | };
90 | this.createGroceryItem = function() {
91 | return 'apple';
92 | };
93 |
94 | this.getGroceryListView = function() {
95 | return this.groceryListApplication.$listview;
96 | };
97 |
98 | this.getGroceryListViewItemAtIndex = function(index) {
99 | return this.groceryListApplication.$listview.childNodes[index].textContent;
100 | }
101 |
102 | this.emptyGroceryListView = function() {
103 | this.groceryListApplication.empty();
104 | };
105 |
106 | this.enterNewGorceryListItem = function(item) {
107 | this.groceryListApplication.enterNewItem(item);
108 | };
109 |
110 | this.createClickEvent = function() {
111 | var event = document.createEvent('MouseEvents');
112 | event.initEvent('click', true, false);
113 | return event;
114 | };
115 |
116 | this.clickAddGroceryListItem = function() {
117 | var clickevent = this.createClickEvent();
118 | this.groceryListApplication.$addbutton.dispatchEvent(clickevent);
119 | };
120 |
121 | callback();
122 |
123 | };
124 |
125 | module.exports.World = World;}).call(this,_dereq_("/Users/toddanderson/Documents/workspace/custardbelly/cucumberjs-browser/node_modules/browserify/node_modules/insert-module-globals/node_modules/process/browser.js"))
126 | },{"/Users/toddanderson/Documents/workspace/custardbelly/cucumberjs-browser/node_modules/browserify/node_modules/insert-module-globals/node_modules/process/browser.js":1}]},{},[2])
127 | (2)
128 | });
--------------------------------------------------------------------------------
/testem.json:
--------------------------------------------------------------------------------
1 | {
2 | "test_page": "test/cucumber-testrunner.html",
3 | "launchers": {
4 | "Chrome": {
5 | "command": "open http://localhost:7357/test/cucumber-testrunner.html /Applications/Google\\ Chrome.app/",
6 | "protocol": "tap"
7 | },
8 | "Safari": {
9 | "command": "open http://localhost:7357/test/cucumber-testrunner.html /Applications/Safari.app/",
10 | "protocol": "tap"
11 | },
12 | "Firefox": {
13 | "command": "open http://localhost:7357/test/cucumber-testrunner.html /Applications/Firefox.app/",
14 | "protocol": "tap"
15 | }
16 | }
17 | }
--------------------------------------------------------------------------------