├── .npmignore ├── .gitignore ├── spec ├── helpers │ └── babel.js ├── vanilla.js ├── failfast.js ├── support │ └── jasmine.json ├── suite.js └── index.js ├── .jshintrc ├── .editorconfig ├── .travis.yml ├── package.json ├── src └── index.js └── README.md /.npmignore: -------------------------------------------------------------------------------- 1 | /src 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /dist 2 | /node_modules 3 | *.sublime* 4 | -------------------------------------------------------------------------------- /spec/helpers/babel.js: -------------------------------------------------------------------------------- 1 | require('babel/register'); 2 | -------------------------------------------------------------------------------- /spec/vanilla.js: -------------------------------------------------------------------------------- 1 | import suite from './suite'; 2 | suite(); 3 | -------------------------------------------------------------------------------- /spec/failfast.js: -------------------------------------------------------------------------------- 1 | import suite from './suite'; 2 | import {init} from '../src/index'; 3 | 4 | jasmine.getEnv().addReporter(init()); 5 | suite(); 6 | -------------------------------------------------------------------------------- /spec/support/jasmine.json: -------------------------------------------------------------------------------- 1 | { 2 | "spec_dir": "spec", 3 | "spec_files": [ 4 | "index.js" 5 | ], 6 | "helpers": [ 7 | "helpers/**/*.js" 8 | ] 9 | } 10 | -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "quotmark": "single", 3 | "undef": true, 4 | "unused": true, 5 | "maxlen": 100, 6 | "node": true, 7 | "jasmine": true, 8 | "esnext": true 9 | } 10 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # editorconfig.org 2 | root = true 3 | 4 | [*] 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | charset = utf-8 9 | trim_trailing_whitespace = true 10 | insert_final_newline = true 11 | 12 | [*.md] 13 | trim_trailing_whitespace = false 14 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - 10 4 | notifications: 5 | email: false 6 | before_install: 7 | - curl -o- -L https://yarnpkg.com/install.sh | bash 8 | - export PATH="$HOME/.yarn/bin:$PATH" 9 | after_success: 10 | - "[[ $TRAVIS_PULL_REQUEST != 'false' ]] && npx semantic-release-github-pr --debug" 11 | - npx semantic-release --debug 12 | cache: yarn 13 | -------------------------------------------------------------------------------- /spec/suite.js: -------------------------------------------------------------------------------- 1 | export default function() { 2 | describe('Pass-fail-pass', () => { 3 | it('passes', () => { 4 | expect(true).toBeTruthy(); 5 | }); 6 | 7 | it('fails', () => { 8 | expect(true).toBeFalsy(); 9 | }); 10 | 11 | it('passes slowly', (done) => { 12 | setTimeout(() => { 13 | expect(true).toBeTruthy(); 14 | done(); 15 | }, 2000); 16 | }); 17 | }); 18 | } 19 | -------------------------------------------------------------------------------- /spec/index.js: -------------------------------------------------------------------------------- 1 | import {exec} from 'child_process'; 2 | 3 | describe('a suite with a failing spec', () => { 4 | describe('running without fail-fast', () => { 5 | it('runs all tests', done => { 6 | exec('./node_modules/.bin/jasmine spec/vanilla.js', (err, stdout) => { 7 | expect(stdout).toMatch(/Finished in 2./); 8 | done(); 9 | }); 10 | }); 11 | }); 12 | 13 | describe('running with fail-fast', () => { 14 | it('skips the remaining test(s) after the first failure', done => { 15 | exec('./node_modules/.bin/jasmine spec/failfast.js', (err, stdout) => { 16 | expect(stdout).toMatch(/Finished in 0.0/); 17 | done(); 18 | }); 19 | }); 20 | }); 21 | }); 22 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jasmine-fail-fast", 3 | "version": "0.0.0-development", 4 | "description": "Allow Jasmine tests to \"fail-fast\", exiting on the first failure instead of running all tests no matter what. ", 5 | "repository": { 6 | "type": "git", 7 | "url": "git://github.com/Updater/jasmine-fail-fast.git" 8 | }, 9 | "main": "dist/jasmine-fail-fast.js", 10 | "scripts": { 11 | "prepublishOnly": "mkdirp dist && babel -o dist/jasmine-fail-fast.js src/index.js", 12 | "test": "jasmine" 13 | }, 14 | "keywords": [ 15 | "jasmine", 16 | "fail-fast" 17 | ], 18 | "author": "pmowrer@gmail.com", 19 | "license": "MIT", 20 | "dependencies": { 21 | "lodash": "^4.17.15" 22 | }, 23 | "devDependencies": { 24 | "babel": "5.6.23", 25 | "jasmine": "^2.3.1", 26 | "mkdirp": "^1.0.3", 27 | "semantic-release": "^17.0.2", 28 | "semantic-release-github-pr": "^6.0.0" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import _ from 'lodash'; 2 | 3 | let refs; 4 | 5 | // Jasmine doesn't yet have an option to fail fast. This "reporter" is a workaround for the time 6 | // being, making Jasmine essentially skip all tests after the first failure. 7 | // https://github.com/jasmine/jasmine/issues/414 8 | // https://github.com/juliemr/minijasminenode/issues/20 9 | export function init() { 10 | refs = getSpecReferences(); 11 | 12 | return { 13 | specDone(result) { 14 | if (result.status === 'failed') { 15 | disableSpecs(refs); 16 | } 17 | } 18 | }; 19 | } 20 | 21 | /** 22 | * Gather references to all jasmine specs and suites, through any (currently hacky) means possible. 23 | * 24 | * @return {Object} An object with `specs` and `suites` properties, arrays of respective types. 25 | */ 26 | export function getSpecReferences() { 27 | let specs = []; 28 | let suites = []; 29 | 30 | // Use specFilter to gather references to all specs. 31 | jasmine.getEnv().specFilter = spec => { 32 | specs.push(spec); 33 | return true; 34 | }; 35 | 36 | // Wrap jasmine's describe function to gather references to all suites. 37 | jasmine.getEnv().describe = _.wrap(jasmine.getEnv().describe, 38 | (describe, ...args) => { 39 | let suite = describe.apply(null, args); 40 | suites.push(suite); 41 | return suite; 42 | }); 43 | 44 | return { 45 | specs, 46 | suites 47 | }; 48 | } 49 | 50 | /** 51 | * Hacky workaround to facilitate "fail fast". Disable all specs (basically `xit`), then 52 | * remove references to all before/after functions, else they'll still run. Disabling the 53 | * suites themselves does not appear to have an effect. 54 | */ 55 | export function disableSpecs() { 56 | if (!refs) { 57 | throw new Error('jasmine-fail-fast: Must call init() before calling disableSpecs()!'); 58 | } 59 | 60 | refs.specs.forEach(spec => spec.disable()); 61 | 62 | refs.suites.forEach(suite => { 63 | suite.beforeFns = []; 64 | suite.afterFns = []; 65 | suite.beforeAllFns = []; 66 | suite.afterAllFns = []; 67 | }); 68 | } 69 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # jasmine-fail-fast [![build status](https://travis-ci.org/pmowrer/jasmine-fail-fast.svg?branch=master)](https://travis-ci.org/Updater/jasmine-fail-fast) 2 | 3 | Allow Jasmine tests to "fail-fast", exiting on the first failure instead of running all tests no matter what. This can save a great deal of time running slow, expensive tests, such as Protractor e2e tests. 4 | 5 | This module is a workaround to address the need for a fail-fast option in Jasmine, a feature that has been requested for years: 6 | 7 | * https://github.com/jasmine/jasmine/issues/414 8 | * https://github.com/juliemr/minijasminenode/issues/20 9 | 10 | Inspired by https://github.com/goodeggs/jasmine-bail-fast, which doesn't seem to be working with Jasmine 2.x. 11 | 12 | ## Usage 13 | This module is implemented as a Jasmine reporter. 14 | 15 | ### Jasmine as browser global 16 | ```javascript 17 | var failFast = require('jasmine-fail-fast'); 18 | jasmine.getEnv().addReporter(failFast.init()); 19 | ``` 20 | 21 | ### Jasmine Node API 22 | ```javascript 23 | var Jasmine = require('jasmine'); 24 | var jasmine = new Jasmine(); 25 | var failFast = require('jasmine-fail-fast'); 26 | jasmine.addReporter(failFast.init()); 27 | ``` 28 | 29 | ## Examples 30 | 31 | ### [karma-jasmine](https://github.com/karma-runner/karma-jasmine) 32 | In the Karma configuration file: 33 | 34 | ```javascript 35 | module.exports = function(config) { 36 | var failFast = require('jasmine-fail-fast'); 37 | window.jasmine.getEnv().addReporter(failFast.init()); 38 | } 39 | ``` 40 | 41 | ### [Protractor](https://github.com/angular/protractor) 42 | In the Protractor configuration file: 43 | 44 | ```javascript 45 | onPrepare: function() { 46 | var failFast = require('jasmine-fail-fast'); 47 | jasmine.getEnv().addReporter(failFast.init()); 48 | } 49 | ``` 50 | 51 | ### As a Jasmine helper 52 | Create a new .js file within the [helpers](http://jasmine.github.io/2.3/node.html#section-9) [folder](http://jasmine.github.io/2.3/node.html#section-Load_configuration_from_a_file_or_from_an_object.): 53 | 54 | ```javascript 55 | ///fail-fast.js 56 | var failFast = require('jasmine-fail-fast'); 57 | jasmine.getEnv().addReporter(failFast.init()); 58 | ``` 59 | ### grunt-contrib-jasmine 60 | Set up as a helper, [optionally overriding the default helpers path](https://github.com/gruntjs/grunt-contrib-jasmine#optionshelpers). 61 | --------------------------------------------------------------------------------