diff --git a/.travis.yml b/.travis.yml
index 8a76015bdd..53f276ae7c 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -11,12 +11,13 @@ env:
# phantomjs hosts binaries @ bitbucket, which has fairly restrictive
# rate-limiting. pull it from this sketchy site in China instead.
- PHANTOMJS_CDNURL='https://cnpmjs.org/downloads'
+ COVERAGE=true
matrix:
fast_finish: true
include:
- node_js: '8'
- env: TARGET=test-node COVERAGE=true
+ env: TARGET=test-node
- node_js: '7'
env: TARGET=test-node
- node_js: '6'
diff --git a/Makefile b/Makefile
index 2fa367e8ff..d6c13165d0 100644
--- a/Makefile
+++ b/Makefile
@@ -7,25 +7,42 @@ ifdef COVERAGE
define test_node
$(NYC) --report-dir coverage/reports/$(1) $(MOCHA)
endef
+ instrument_browser := -t ./instrumentBrowserEntry
else
test_node := $(MOCHA)
endif
-TM_BUNDLE = JavaScript\ mocha.tmbundle
-SRC = $(shell find lib -name "*.js" -type f | LC_ALL=C sort)
-TESTS = $(shell find test -name "*.js" -type f | sort)
-
-all: mocha.js
-
-mocha.js BUILDTMP/mocha.js: $(SRC) browser-entry.js
- @printf "==> [Browser :: build]\n"
- mkdir -p ${@D}
+define bundle_command
$(BROWSERIFY) ./browser-entry \
+ $(1) \
--plugin ./scripts/dedefine \
--ignore 'fs' \
--ignore 'glob' \
--ignore 'path' \
--ignore 'supports-color' > $@
+endef
+
+TM_BUNDLE = JavaScript\ mocha.tmbundle
+SRC = $(shell find lib -name "*.js" -type f | LC_ALL=C sort)
+TESTS = $(shell find test -name "*.js" -type f | sort)
+
+all: mocha.js
+
+mocha.js: $(SRC) browser-entry.js
+ @printf "==> [Browser :: Build]\n"
+ $(call bundle_command)
+
+BUILDTMP/mocha.js: $(SRC) browser-entry.js BUILDTMP BUILDTMP/mocha.css
+ @printf "==> [Browser :: Build :: Test :: Bundle]\n"
+ $(call bundle_command,$(instrument_browser))
+
+BUILDTMP/mocha.css: BUILDTMP
+ @printf "==> [Browser :: Build :: Test :: CSS]\n"
+ cp mocha.css $@
+
+BUILDTMP:
+ @printf "==> [Browser :: Build :: Test :: Temporary Directory]\n"
+ mkdir -p $@
clean:
@printf "==> [Clean]\n"
diff --git a/README.md b/README.md
index 9e4d4dcbea..4db7b3712c 100644
--- a/README.md
+++ b/README.md
@@ -9,13 +9,14 @@
*Thank you* :kissing_heart: to all of you interested in helping. These are Mocha's immediate needs:
1. Increase test coverage on Node.js and browser
- - Increase integration coverage for all reporters
- - `html` reporter must be tested in browser
+ - ~~Increase integration coverage for all reporters~~
+ - ~~`html` reporter must be tested in browser~~
- ~~Basic console reporters (*not* `nyan`, `landing`, etc.) must be tested in **both** browser and Node.js contexts; PhantomJS can consume all console reporters~~
- ~~Filesystem-based reporters must be tested in Node.js context~~
- - **UPDATE - May 24 2017**: Thanks to [community contributions](https://github.com/mochajs/mocha/blob/master/CHANGELOG.md#mag-coverage), the coverage on most reporters has increased dramatically! The `html` reporter is still in [dire need of coverage](https://coveralls.io/builds/11674428/source?filename=lib%2Freporters%2Fhtml.js).
+ - **UPDATE - May 24 2017**: Thanks to [community contributions](https://github.com/mochajs/mocha/blob/master/CHANGELOG.md#mag-coverage), the coverage on most reporters has increased dramatically! ~~The `html` reporter is still in dire need of coverage.~~
- Increase coverage against all interfaces (`exports` in particular). Ideally this becomes a "matrix" where we repeat sets of integration tests across all interfaces.
- Refactor non-Node.js-specific tests to allow them to run in a browser context. Node.js-specific tests include those which *require* the CLI or filesystem. Most everything else is fair game.
+ - In general, anything with relatively low coverage percentage could use a little more attention; but also feel free to look for files with a low but non-zero number of uncovered branches or functions, which may not need much to test the other branch and/or the function in question.
2. Review current open pull requests
- We need individuals familiar with Mocha's codebase. Got questions? Ask them in [our chat room](https://gitter.im/mochajs/mocha).
- Pull requests **must** have supporting tests. The only exceptions are pure cosmetic or non-functional changes.
diff --git a/instrumentBrowserEntry.js b/instrumentBrowserEntry.js
new file mode 100644
index 0000000000..2e53dc08af
--- /dev/null
+++ b/instrumentBrowserEntry.js
@@ -0,0 +1,11 @@
+'use strict';
+
+var browserifyIstanbul = require('browserify-istanbul');
+
+var nyc = require('./nycInstrumenter');
+
+var overrideOptions = { ignore: ['**/lib/**', '**/node_modules/**', '**/test/**'], instrumenter: nyc };
+
+module.exports = function (file, options) {
+ return browserifyIstanbul(file, Object.assign({}, options, overrideOptions));
+};
diff --git a/karma.conf.js b/karma.conf.js
index b8d73fd0e3..c519f8f9f1 100644
--- a/karma.conf.js
+++ b/karma.conf.js
@@ -5,9 +5,16 @@ var path = require('path');
var mkdirp = require('mkdirp');
var baseBundleDirpath = path.join(__dirname, '.karma');
var osName = require('os-name');
+var workaroundMultiplePreprocessorIncompatibility = require('browserify-istanbul');
+var nyc = require('./nycInstrumenter');
module.exports = function (config) {
var bundleDirpath;
+ var filesBase = [
+ // make browserify bundle these properly (if nothing else, this is necessary for coverage transform; unclear whether it makes a difference as to how browserify gets them otherwise, as it doesn't print any debug logs about them without it)
+ { pattern: 'browser-entry.js', included: false, served: false },
+ { pattern: 'lib/**/*.js', included: false, served: false }
+ ];
var cfg = {
frameworks: [
'browserify',
@@ -23,12 +30,14 @@ module.exports = function (config) {
'karma-spec-reporter',
require('@coderbyheart/karma-sauce-launcher')
],
- files: [
+ files: filesBase.concat([
// we use the BDD interface for all of the tests that
// aren't interface-specific.
'test/browser-fixtures/bdd.fixture.js',
- 'test/unit/*.spec.js'
- ],
+ 'test/unit/*.spec.js',
+ 'test/browser-unit/*.spec.js',
+ 'test/browser-reporters/*.spec.js'
+ ]),
preprocessors: {
'test/**/*.js': ['browserify']
},
@@ -128,14 +137,31 @@ module.exports = function (config) {
if (cfg.sauceLabs) {
cfg.sauceLabs.testName = 'Interface "' + ui + '" integration tests';
}
- cfg.files = [
+ cfg.files = filesBase.concat([
'test/browser-fixtures/' + ui + '.fixture.js',
'test/interfaces/' + ui + '.spec.js'
- ];
+ ]);
} else if (cfg.sauceLabs) {
cfg.sauceLabs.testName = 'Unit Tests';
}
+ if (env.COVERAGE) {
+ cfg.plugins.push('karma-coverage');
+ filesBase.forEach(function (file) {
+ cfg.preprocessors[file.pattern] = ['browserify'];
+ });
+ cfg.reporters.push('coverage');
+ cfg.coverageReporter = {
+ instrumenters: { istanbul: nyc },
+ reporters: [ { type: 'json' }, { type: 'text-summary' } ],
+ dir: 'coverage/reports/browser' + (ui ? '-' + ui : ''),
+ subdir: '.',
+ includeAllSources: true
+ };
+ cfg.browserify.transform = [ workaroundMultiplePreprocessorIncompatibility({ ignore: ['**/node_modules/**', '**/test/**'], instrumenter: nyc }) ];
+ console.error('Reporting coverage to ' + cfg.coverageReporter.dir);
+ }
+
config.set(cfg);
};
diff --git a/lib/reporters/html.js b/lib/reporters/html.js
index e29aa36a5a..b1e98e7a9d 100644
--- a/lib/reporters/html.js
+++ b/lib/reporters/html.js
@@ -86,22 +86,22 @@ function HTML (runner) {
// pass toggle
on(passesLink, 'click', function (evt) {
evt.preventDefault();
- unhide();
+ unhide(report);
var name = (/pass/).test(report.className) ? '' : ' pass';
report.className = report.className.replace(/fail|pass/g, '') + name;
if (report.className.trim()) {
- hideSuitesWithout('test pass');
+ hideSuitesWithout(report, 'test pass');
}
});
// failure toggle
on(failuresLink, 'click', function (evt) {
evt.preventDefault();
- unhide();
+ unhide(report);
var name = (/fail/).test(report.className) ? '' : ' fail';
report.className = report.className.replace(/fail|pass/g, '') + name;
if (report.className.trim()) {
- hideSuitesWithout('test fail');
+ hideSuitesWithout(report, 'test fail');
}
});
@@ -302,8 +302,8 @@ function fragment (html) {
*
* @param {text} classname
*/
-function hideSuitesWithout (classname) {
- var suites = document.getElementsByClassName('suite');
+function hideSuitesWithout (root, classname) {
+ var suites = root.getElementsByClassName('suite');
for (var i = 0; i < suites.length; i++) {
var els = suites[i].getElementsByClassName(classname);
if (!els.length) {
@@ -315,9 +315,9 @@ function hideSuitesWithout (classname) {
/**
* Unhide .hidden suites.
*/
-function unhide () {
- var els = document.getElementsByClassName('suite hidden');
- for (var i = 0; i < els.length; ++i) {
+function unhide (root) {
+ var els = root.getElementsByClassName('suite hidden');
+ for (var i = els.length - 1; i >= 0; --i) {
els[i].className = els[i].className.replace('suite hidden', 'suite');
}
}
diff --git a/nycInstrumenter.js b/nycInstrumenter.js
new file mode 100644
index 0000000000..ca3da3952c
--- /dev/null
+++ b/nycInstrumenter.js
@@ -0,0 +1,16 @@
+'use strict';
+
+var defaultOptions = {
+ autoWrap: true,
+ embedSource: true,
+ produceSourceMap: true,
+ noCompact: false
+};
+
+var istanbulLib;
+try {
+ istanbulLib = require('nyc/node_modules/istanbul-lib-instrument');
+} catch (ignore) {
+ istanbulLib = require('istanbul-lib-instrument');
+}
+module.exports = { Instrumenter: function (options) { return istanbulLib.createInstrumenter(Object.assign({}, defaultOptions, options)); } };
diff --git a/package.json b/package.json
index e772d90290..9b1f9a9e6c 100644
--- a/package.json
+++ b/package.json
@@ -323,6 +323,7 @@
"@coderbyheart/karma-sauce-launcher": "coderbyheart/karma-sauce-launcher#5259942cd6d40090eaa13ceeef5b0b8738c7710f",
"assert": "^1.4.1",
"browserify": "^13.0.0",
+ "browserify-istanbul": "^2.0.0",
"coffee-script": "^1.10.0",
"coveralls": "^2.11.15",
"eslint": "^3.11.1",
@@ -335,6 +336,7 @@
"karma": "1.3.0",
"karma-browserify": "^5.0.5",
"karma-chrome-launcher": "^2.0.0",
+ "karma-coverage": "^1.1.1",
"karma-expect": "^1.1.2",
"karma-mocha": "^1.3.0",
"karma-phantomjs-launcher": "0.2.3",
diff --git a/test/browser-fixtures/bdd.fixture.js b/test/browser-fixtures/bdd.fixture.js
index 5fe802f74a..90c8dd72d8 100644
--- a/test/browser-fixtures/bdd.fixture.js
+++ b/test/browser-fixtures/bdd.fixture.js
@@ -4,5 +4,5 @@
process.stdout = require('browser-stdout')();
-window.mocha.timeout(200)
+window.mocha.timeout(500)
.ui('bdd');
diff --git a/test/browser-fixtures/exports.fixture.js b/test/browser-fixtures/exports.fixture.js
index a4c25cff99..1ddabc8620 100644
--- a/test/browser-fixtures/exports.fixture.js
+++ b/test/browser-fixtures/exports.fixture.js
@@ -4,5 +4,5 @@
process.stdout = require('browser-stdout')();
-window.mocha.timeout(200)
+window.mocha.timeout(500)
.ui('exports');
diff --git a/test/browser-fixtures/qunit.fixture.js b/test/browser-fixtures/qunit.fixture.js
index 79b49498d5..2c0b642100 100644
--- a/test/browser-fixtures/qunit.fixture.js
+++ b/test/browser-fixtures/qunit.fixture.js
@@ -4,5 +4,5 @@
process.stdout = require('browser-stdout')();
-window.mocha.timeout(200)
+window.mocha.timeout(500)
.ui('qunit');
diff --git a/test/browser-fixtures/tdd.fixture.js b/test/browser-fixtures/tdd.fixture.js
index 2fdc8f758c..a36040b17f 100644
--- a/test/browser-fixtures/tdd.fixture.js
+++ b/test/browser-fixtures/tdd.fixture.js
@@ -4,5 +4,5 @@
process.stdout = require('browser-stdout')();
-window.mocha.timeout(200)
+window.mocha.timeout(500)
.ui('tdd');
diff --git a/test/browser-reporters/html.spec.js b/test/browser-reporters/html.spec.js
new file mode 100644
index 0000000000..0a66be662a
--- /dev/null
+++ b/test/browser-reporters/html.spec.js
@@ -0,0 +1,1927 @@
+'use strict';
+
+var HTML = require('../../lib/reporters/html');
+
+var Suite = require('../../lib/suite');
+var Context = require('../../lib/context');
+var Test = require('../../lib/test');
+
+describe('HTML reporter', function () {
+ this.slow(250);
+
+ var realOutput;
+ var realOutputStats;
+ var realOutputReport;
+
+ function saveRealOutput () {
+ if (!realOutput) {
+ realOutput = document.getElementById('mocha');
+ realOutputStats = document.getElementById('mocha-stats');
+ realOutputReport = document.getElementById('mocha-report');
+ }
+ }
+
+ function removeRealOutput () {
+ saveRealOutput();
+ if (realOutput) {
+ realOutput.id = null;
+ realOutputStats.id = null;
+ realOutputReport.id = null;
+ }
+ }
+
+ function stubOutput () {
+ removeRealOutput();
+ var tmp = document.createElement('div');
+ tmp.id = 'mocha';
+ document.body.appendChild(tmp);
+ return tmp;
+ }
+
+ function restoreOutput () {
+ var tmp = document.getElementById('mocha');
+ if (tmp && tmp !== realOutput) { tmp.parentNode.removeChild(tmp); }
+ if (realOutput) {
+ realOutput.id = 'mocha';
+ realOutputStats.id = 'mocha-stats';
+ realOutputReport.id = 'mocha-report';
+ }
+ return tmp !== realOutput ? tmp : undefined;
+ }
+
+ before(saveRealOutput); // so that the following afterEach is guaranteed to work
+
+ afterEach(function () { restoreOutput(); }); // WARNING: this is solely a fallback so *further* tests can be guaranteed to report correctly; these tests will not be reported correctly unless `restoreOutput` is called at the end of the test, before throwing any errors
+
+ it('should show an error if the tag is missing', function () {
+ try {
+ // TODO: Figure out why it's ok to add an element to display this error but not ok to just add the missing element in the first place.
+ removeRealOutput();
+ new HTML(new Runner()); // eslint-disable-line no-new
+ var error = document.getElementById('mocha-error');
+ expect(error).not.to.be(null);
+ expect(error).not.to.be(undefined);
+ error.parentNode.removeChild(error);
+ expect(error.outerHTML).to.equal('
#mocha div missing, add it to your document
');
+ restoreOutput();
+ } catch (error) {
+ try {
+ restoreOutput();
+ } catch (ignore) {}
+ throw error;
+ }
+ });
+
+ it('should output to the "mocha" div', function () {
+ try {
+ stubOutput();
+ var runner = new Runner(7);
+ new HTML(runner); // eslint-disable-line no-new
+ var rootSuite = new Suite('', new Context());
+ var mainSuite = Suite.create(rootSuite, 'suite');
+ mainSuite.addTest(new Test('passing', function () { /* content here */; })); // eslint-disable-line no-extra-semi
+ mainSuite.addTest(new Test('pending'));
+ mainSuite.addTest(new Test('skipped at runtime', function () { this.skip(); }));
+ mainSuite.addTest(new Test('slow', function (done) { setTimeout(done, 100); }));
+ mainSuite.addTest(new Test('less slow', function (done) { setTimeout(done, 50); }));
+ var failingTest = function () {
+ var AssertionError = function (message, actual, expected) {
+ this.message = message;
+ this.actual = actual;
+ this.expected = expected;
+ this.showDiff = true;
+ };
+ AssertionError.prototype = Object.create(Error.prototype);
+ AssertionError.prototype.name = 'AssertionError';
+ AssertionError.prototype.constructor = AssertionError;
+ throw new AssertionError('example', 'text with a typo', 'text without a typo');
+ };
+ mainSuite.addTest(new Test('failing', failingTest));
+ mainSuite.addTest(new Test('timeout', function (done) { /* does not complete */; })); // eslint-disable-line no-extra-semi
+ runner.emit('start');
+ runner.emit('suite', rootSuite);
+ runner.emit('suite', mainSuite);
+ runner.emit('test', mainSuite.tests[0]);
+ mainSuite.tests[0].duration = 0;
+ mainSuite.tests[0].state = 'passed';
+ runner.emit('pass', mainSuite.tests[0]);
+ runner.emit('test end', mainSuite.tests[0]);
+ // no 'test' event is emitted for pending tests
+ runner.emit('pending', mainSuite.tests[1]);
+ runner.emit('test end', mainSuite.tests[1]);
+ runner.emit('test', mainSuite.tests[2]);
+ mainSuite.tests[2].pending = true;
+ mainSuite.tests[2].duration = 0;
+ runner.emit('pending', mainSuite.tests[2]);
+ runner.emit('test end', mainSuite.tests[2]);
+ runner.emit('test', mainSuite.tests[3]);
+ mainSuite.tests[3].timer = { '0': null };
+ mainSuite.tests[3].duration = 116;
+ mainSuite.tests[3].state = 'passed';
+ runner.emit('pass', mainSuite.tests[3]);
+ runner.emit('test end', mainSuite.tests[3]);
+ runner.emit('test', mainSuite.tests[4]);
+ mainSuite.tests[4].timer = { '0': null };
+ mainSuite.tests[4].duration = 63;
+ mainSuite.tests[4].state = 'passed';
+ runner.emit('pass', mainSuite.tests[4]);
+ runner.emit('test end', mainSuite.tests[4]);
+ runner.emit('test', mainSuite.tests[5]);
+ mainSuite.tests[5].duration = 0;
+ mainSuite.tests[5].state = 'failed';
+ try {
+ failingTest();
+ throw new Error('Failing test did not throw assertion');
+ } catch (assertion) {
+ runner.emit('fail', mainSuite.tests[5], assertion);
+ }
+ runner.emit('test end', mainSuite.tests[5]);
+ runner.emit('test', mainSuite.tests[6]);
+ mainSuite.tests[6].timer = { '0': null };
+ mainSuite.tests[6].duration = 211;
+ mainSuite.tests[6].state = 'failed';
+ runner.emit('fail', mainSuite.tests[6], new Error('Timeout of 200ms exceeded. For async tests and hooks, ensure "done()" is called; if returning a Promise, ensure it resolves.'));
+ runner.emit('test end', mainSuite.tests[6]);
+ runner.emit('suite end', mainSuite);
+ runner.emit('suite end', rootSuite);
+ runner.emit('end');
+ var output = restoreOutput().outerHTML
+ .replace(/\u2023/g, '‣')
+ .replace(/(duration: )[0-9]+(?:[.][0-9]+)?(<\/em>s<\/li>)/, '$1$2')
+ .replace(/href="[^"?]*[?]/g, 'href="?')
+ .replace(/class="replay" (href="[^"]*")/g, '$1 class="replay"')
+ .replace(/style="display:\s*none;?\s*"/g, 'style="display: none;"')
+ .replace(/\s+style=""/g, '')
+ .replace(/(height="[^"]*")(\s+)(width="[^"]*")/g, '$3$2$1')
+ .replace(/AssertionError: example[^<]*<\/pre>/g, 'AssertionError: example\nat STACKTRACE ')
+ .replace(/Error: Timeout of 200ms exceeded[.] For async tests and hooks, ensure "done[(][)]" is called; if returning a Promise, ensure it resolves[.][^<]*<\/pre>/g, 'Error: Timeout of 200ms exceeded. For async tests and hooks, ensure "done()" is called; if returning a Promise, ensure it resolves.\nat STACKTRACE ')
+ .replace(/\r\n/g, '\n');
+ expect(output).to.equal('passing0ms ‣ /* content here */;
pending skipped at runtime slow116ms ‣ setTimeout(done, 100);
less slow63ms ‣ setTimeout(done, 50);
failing ‣ AssertionError: example\nat STACKTRACE var AssertionError = function (message, actual, expected) {\n this.message = message;\n this.actual = actual;\n this.expected = expected;\n this.showDiff = true;\n};\nAssertionError.prototype = Object.create(Error.prototype);\nAssertionError.prototype.name = \'AssertionError\';\nAssertionError.prototype.constructor = AssertionError;\nthrow new AssertionError(\'example\', \'text with a typo\', \'text without a typo\');
timeout ‣ Error: Timeout of 200ms exceeded. For async tests and hooks, ensure "done()" is called; if returning a Promise, ensure it resolves.\nat STACKTRACE /* does not complete */;
');
+ } catch (error) {
+ try {
+ restoreOutput();
+ } catch (ignore) {}
+ throw error;
+ }
+ });
+
+ it('should correctly output multiple adjacent nested suites', function () {
+ try {
+ stubOutput();
+ var runner = new Runner(4);
+ new HTML(runner); // eslint-disable-line no-new
+ var rootSuite = new Suite('', new Context());
+ Suite.create(rootSuite, 'outer suite 1');
+ Suite.create(rootSuite.suites[0], 'inner suite 1');
+ rootSuite.suites[0].suites[0].addTest(new Test('passing', function () { /* content here */; })); // eslint-disable-line no-extra-semi
+ Suite.create(rootSuite.suites[0], 'inner suite 2');
+ rootSuite.suites[0].suites[1].addTest(new Test('passing', function () { /* content here */; })); // eslint-disable-line no-extra-semi
+ Suite.create(rootSuite, 'outer suite 2');
+ Suite.create(rootSuite.suites[1], 'inner suite 1');
+ rootSuite.suites[1].suites[0].addTest(new Test('passing', function () { /* content here */; })); // eslint-disable-line no-extra-semi
+ Suite.create(rootSuite.suites[1], 'inner suite 2');
+ rootSuite.suites[1].suites[1].addTest(new Test('passing', function () { /* content here */; })); // eslint-disable-line no-extra-semi
+ runner.emit('start');
+ runner.emit('suite', rootSuite);
+ runner.emit('suite', rootSuite.suites[0]);
+ runner.emit('suite', rootSuite.suites[0].suites[0]);
+ runner.emit('test', rootSuite.suites[0].suites[0].tests[0]);
+ rootSuite.suites[0].suites[0].tests[0].duration = 0;
+ rootSuite.suites[0].suites[0].tests[0].state = 'passed';
+ runner.emit('pass', rootSuite.suites[0].suites[0].tests[0]);
+ runner.emit('test end', rootSuite.suites[0].suites[0].tests[0]);
+ runner.emit('suite end', rootSuite.suites[0].suites[0]);
+ runner.emit('suite', rootSuite.suites[0].suites[1]);
+ runner.emit('test', rootSuite.suites[0].suites[1].tests[0]);
+ rootSuite.suites[0].suites[1].tests[0].duration = 0;
+ rootSuite.suites[0].suites[1].tests[0].state = 'passed';
+ runner.emit('pass', rootSuite.suites[0].suites[1].tests[0]);
+ runner.emit('test end', rootSuite.suites[0].suites[1].tests[0]);
+ runner.emit('suite end', rootSuite.suites[0].suites[1]);
+ runner.emit('suite end', rootSuite.suites[0]);
+ runner.emit('suite', rootSuite.suites[1]);
+ runner.emit('suite', rootSuite.suites[1].suites[0]);
+ runner.emit('test', rootSuite.suites[1].suites[0].tests[0]);
+ rootSuite.suites[1].suites[0].tests[0].duration = 0;
+ rootSuite.suites[1].suites[0].tests[0].state = 'passed';
+ runner.emit('pass', rootSuite.suites[1].suites[0].tests[0]);
+ runner.emit('test end', rootSuite.suites[1].suites[0].tests[0]);
+ runner.emit('suite end', rootSuite.suites[1].suites[0]);
+ runner.emit('suite', rootSuite.suites[1].suites[1]);
+ runner.emit('test', rootSuite.suites[1].suites[1].tests[0]);
+ rootSuite.suites[1].suites[1].tests[0].duration = 0;
+ rootSuite.suites[1].suites[1].tests[0].state = 'passed';
+ runner.emit('pass', rootSuite.suites[1].suites[1].tests[0]);
+ runner.emit('test end', rootSuite.suites[1].suites[1].tests[0]);
+ runner.emit('suite end', rootSuite.suites[1].suites[1]);
+ runner.emit('suite end', rootSuite.suites[1]);
+ runner.emit('suite end', rootSuite);
+ runner.emit('end');
+ var output = restoreOutput().outerHTML
+ .replace(/\u2023/g, '‣')
+ .replace(/( duration: )[0-9]+(?:[.][0-9]+)?(<\/em>s<\/li>)/, '$1$2')
+ .replace(/href="[^"?]*[?]/g, 'href="?')
+ .replace(/class="replay" (href="[^"]*")/g, '$1 class="replay"')
+ .replace(/style="display:\s*none;?\s*"/g, 'style="display: none;"')
+ .replace(/\s+style=""/g, '')
+ .replace(/(height="[^"]*")(\s+)(width="[^"]*")/g, '$3$2$1')
+ .replace(/AssertionError: example[^<]*<\/pre>/g, 'AssertionError: example\nat STACKTRACE ')
+ .replace(/Error: Timeout of 200ms exceeded[.] For async tests and hooks, ensure "done[(][)]" is called; if returning a Promise, ensure it resolves[.][^<]*<\/pre>/g, 'Error: Timeout of 200ms exceeded. For async tests and hooks, ensure "done()" is called; if returning a Promise, ensure it resolves.\nat STACKTRACE ')
+ .replace(/\r\n/g, '\n');
+ expect(output).to.equal('passing0ms ‣ /* content here */;
passing0ms ‣ /* content here */;
passing0ms ‣ /* content here */;
passing0ms ‣ /* content here */;
');
+ } catch (error) {
+ try {
+ restoreOutput();
+ } catch (ignore) {}
+ throw error;
+ }
+ });
+
+ it('should output sanely when there are no tests', function () {
+ try {
+ stubOutput();
+ var runner = new Runner(0);
+ new HTML(runner); // eslint-disable-line no-new
+ var rootSuite = new Suite('', new Context());
+ runner.emit('start');
+ runner.emit('suite', rootSuite);
+ runner.emit('suite end', rootSuite);
+ runner.emit('end');
+ var output = restoreOutput().outerHTML
+ .replace(/\u2023/g, '‣')
+ .replace(/( duration: )[0-9]+(?:[.][0-9]+)?(<\/em>s<\/li>)/, '$1$2')
+ .replace(/href="[^"?]*[?]/g, 'href="?')
+ .replace(/class="replay" (href="[^"]*")/g, '$1 class="replay"')
+ .replace(/style="display:\s*none;?\s*"/g, 'style="display: none;"')
+ .replace(/\s+style=""/g, '')
+ .replace(/(height="[^"]*")(\s+)(width="[^"]*")/g, '$3$2$1')
+ .replace(/AssertionError: example[^<]*<\/pre>/g, 'AssertionError: example\nat STACKTRACE ')
+ .replace(/Error: Timeout of 200ms exceeded[.] For async tests and hooks, ensure "done[(][)]" is called; if returning a Promise, ensure it resolves[.][^<]*<\/pre>/g, 'Error: Timeout of 200ms exceeded. For async tests and hooks, ensure "done()" is called; if returning a Promise, ensure it resolves.\nat STACKTRACE ')
+ .replace(/\r\n/g, '\n');
+ expect(output).to.equal('');
+ } catch (error) {
+ try {
+ restoreOutput();
+ } catch (ignore) {}
+ throw error;
+ }
+ });
+
+ // this is mostly to validate the reliability of the other tests, rather than because the reporter is actually meant to run multiple instances; after all, it depends on the current global document.getElementById('mocha')
+ describe('multiple instances', function () {
+ it('should print only to the current instance', function () {
+ try {
+ var output = stubOutput();
+ var runner = new Runner(4);
+ new HTML(runner); // eslint-disable-line no-new
+ var rootSuite = new Suite('', new Context());
+ rootSuite.addTest(new Test('passing', function () { /* content here */; })); // eslint-disable-line no-extra-semi
+ rootSuite.addTest(new Test('pending'));
+ rootSuite.addTest(new Test('skipped at runtime', function () { this.skip(); }));
+ var failingTest = function () { throw new Error('fail test'); };
+ rootSuite.addTest(new Test('failing', failingTest));
+ var initialStates = [
+ rootSuite.tests[0].state,
+ rootSuite.tests[1].pending,
+ rootSuite.tests[2].pending,
+ rootSuite.tests[3].state
+ ];
+ runner.emit('start');
+ runner.emit('suite', rootSuite);
+ runner.emit('test', rootSuite.tests[0]);
+ rootSuite.tests[0].duration = 0;
+ rootSuite.tests[0].state = 'passed';
+ runner.emit('pass', rootSuite.tests[0]);
+ runner.emit('test end', rootSuite.tests[0]);
+ // no 'test' event is emitted for pending tests
+ runner.emit('pending', rootSuite.tests[1]);
+ runner.emit('test end', rootSuite.tests[1]);
+ runner.emit('test', rootSuite.tests[2]);
+ rootSuite.tests[2].pending = true;
+ rootSuite.tests[2].duration = 0;
+ runner.emit('pending', rootSuite.tests[2]);
+ runner.emit('test end', rootSuite.tests[2]);
+ runner.emit('test', rootSuite.tests[3]);
+ rootSuite.tests[3].duration = 0;
+ rootSuite.tests[3].state = 'failed';
+ var assertion;
+ try {
+ failingTest();
+ throw new Error('Failing test did not throw assertion');
+ } catch (caughtAssertion) {
+ assertion = caughtAssertion;
+ runner.emit('fail', rootSuite.tests[3], assertion);
+ }
+ runner.emit('test end', rootSuite.tests[3]);
+ runner.emit('suite end', rootSuite);
+ runner.emit('end');
+ var originalHTML = output.outerHTML;
+ restoreOutput();
+ var other = stubOutput();
+ runner = new Runner(0);
+ new HTML(runner); // eslint-disable-line no-new
+ rootSuite.tests[0].state = initialStates[0];
+ rootSuite.tests[1].pending = initialStates[1];
+ rootSuite.tests[2].pending = initialStates[2];
+ rootSuite.tests[3].state = initialStates[3];
+ runner.emit('start');
+ runner.emit('suite', rootSuite);
+ runner.emit('test', rootSuite.tests[0]);
+ rootSuite.tests[0].duration = 1;
+ rootSuite.tests[0].state = 'passed';
+ runner.emit('pass', rootSuite.tests[0]);
+ runner.emit('test end', rootSuite.tests[0]);
+ // no 'test' event is emitted for pending tests
+ runner.emit('pending', rootSuite.tests[1]);
+ runner.emit('test end', rootSuite.tests[1]);
+ runner.emit('test', rootSuite.tests[2]);
+ rootSuite.tests[2].pending = true;
+ rootSuite.tests[2].duration = 1;
+ runner.emit('pending', rootSuite.tests[2]);
+ runner.emit('test end', rootSuite.tests[2]);
+ runner.emit('test', rootSuite.tests[3]);
+ rootSuite.tests[3].duration = 1;
+ rootSuite.tests[3].state = 'failed';
+ runner.emit('fail', rootSuite.tests[3], assertion);
+ runner.emit('test end', rootSuite.tests[3]);
+ runner.emit('suite end', rootSuite);
+ runner.emit('end');
+ expect(output.outerHTML).to.be(originalHTML);
+ expect(output.outerHTML).not.to.equal(other.outerHTML);
+ expect(output.outerHTML
+ .replace(/( duration: )[0-9]+(?:[.][0-9]+)?(<\/em>s<\/li>)/, '$1$2'))
+ .to.equal(other.outerHTML.replace(/1ms/g, '0ms')
+ .replace(/(duration: )[0-9]+(?:[.][0-9]+)?(<\/em>s<\/li>)/, '$1$2'));
+ restoreOutput();
+ } catch (error) {
+ try {
+ restoreOutput();
+ } catch (ignore) {}
+ throw error;
+ }
+ });
+
+ it('should not affect other instances when the passes filter is clicked', function () {
+ try {
+ var output = stubOutput();
+ var runner = new Runner(4);
+ new HTML(runner); // eslint-disable-line no-new
+ var rootSuite = new Suite('', new Context());
+ rootSuite.addTest(new Test('passing', function () { /* content here */; })); // eslint-disable-line no-extra-semi
+ rootSuite.addTest(new Test('pending'));
+ rootSuite.addTest(new Test('skipped at runtime', function () { this.skip(); }));
+ var failingTest = function () { throw new Error('fail test'); };
+ rootSuite.addTest(new Test('failing', failingTest));
+ runner.emit('start');
+ runner.emit('suite', rootSuite);
+ runner.emit('test', rootSuite.tests[0]);
+ rootSuite.tests[0].duration = 0;
+ rootSuite.tests[0].state = 'passed';
+ runner.emit('pass', rootSuite.tests[0]);
+ runner.emit('test end', rootSuite.tests[0]);
+ // no 'test' event is emitted for pending tests
+ runner.emit('pending', rootSuite.tests[1]);
+ runner.emit('test end', rootSuite.tests[1]);
+ runner.emit('test', rootSuite.tests[2]);
+ rootSuite.tests[2].pending = true;
+ rootSuite.tests[2].duration = 0;
+ runner.emit('pending', rootSuite.tests[2]);
+ runner.emit('test end', rootSuite.tests[2]);
+ runner.emit('test', rootSuite.tests[3]);
+ rootSuite.tests[3].duration = 0;
+ rootSuite.tests[3].state = 'failed';
+ try {
+ failingTest();
+ throw new Error('Failing test did not throw assertion');
+ } catch (assertion) {
+ runner.emit('fail', rootSuite.tests[3], assertion);
+ }
+ runner.emit('test end', rootSuite.tests[3]);
+ runner.emit('suite end', rootSuite);
+ runner.emit('end');
+ var originalHTML = output.outerHTML;
+ restoreOutput();
+ var other = stubOutput();
+ runner = new Runner(0);
+ new HTML(runner); // eslint-disable-line no-new
+ rootSuite = new Suite('', new Context());
+ runner.emit('start');
+ runner.emit('suite', rootSuite);
+ runner.emit('suite end', rootSuite);
+ runner.emit('end');
+ click(other.getElementsByClassName('passes').item(0).getElementsByTagName('a').item(0));
+ expect(output.outerHTML).to.be(originalHTML);
+ restoreOutput();
+ } catch (error) {
+ try {
+ restoreOutput();
+ } catch (ignore) {}
+ throw error;
+ }
+ });
+
+ it('should not affect other instances when the failures filter is clicked', function () {
+ try {
+ var output = stubOutput();
+ var runner = new Runner(4);
+ new HTML(runner); // eslint-disable-line no-new
+ var rootSuite = new Suite('', new Context());
+ rootSuite.addTest(new Test('passing', function () { /* content here */; })); // eslint-disable-line no-extra-semi
+ rootSuite.addTest(new Test('pending'));
+ rootSuite.addTest(new Test('skipped at runtime', function () { this.skip(); }));
+ var failingTest = function () { throw new Error('fail test'); };
+ rootSuite.addTest(new Test('failing', failingTest));
+ runner.emit('start');
+ runner.emit('suite', rootSuite);
+ runner.emit('test', rootSuite.tests[0]);
+ rootSuite.tests[0].duration = 0;
+ rootSuite.tests[0].state = 'passed';
+ runner.emit('pass', rootSuite.tests[0]);
+ runner.emit('test end', rootSuite.tests[0]);
+ // no 'test' event is emitted for pending tests
+ runner.emit('pending', rootSuite.tests[1]);
+ runner.emit('test end', rootSuite.tests[1]);
+ runner.emit('test', rootSuite.tests[2]);
+ rootSuite.tests[2].pending = true;
+ rootSuite.tests[2].duration = 0;
+ runner.emit('pending', rootSuite.tests[2]);
+ runner.emit('test end', rootSuite.tests[2]);
+ runner.emit('test', rootSuite.tests[3]);
+ rootSuite.tests[3].duration = 0;
+ rootSuite.tests[3].state = 'failed';
+ try {
+ failingTest();
+ throw new Error('Failing test did not throw assertion');
+ } catch (assertion) {
+ runner.emit('fail', rootSuite.tests[3], assertion);
+ }
+ runner.emit('test end', rootSuite.tests[3]);
+ runner.emit('suite end', rootSuite);
+ runner.emit('end');
+ var originalHTML = output.outerHTML;
+ restoreOutput();
+ var other = stubOutput();
+ runner = new Runner(0);
+ new HTML(runner); // eslint-disable-line no-new
+ rootSuite = new Suite('', new Context());
+ runner.emit('start');
+ runner.emit('suite', rootSuite);
+ runner.emit('suite end', rootSuite);
+ runner.emit('end');
+ click(other.getElementsByClassName('failures').item(0).getElementsByTagName('a').item(0));
+ expect(output.outerHTML).to.be(originalHTML);
+ restoreOutput();
+ } catch (error) {
+ try {
+ restoreOutput();
+ } catch (ignore) {}
+ throw error;
+ }
+ });
+ });
+
+ describe('passes filter', function () {
+ it('should still show passed tests', function () {
+ try {
+ var output = stubOutput();
+ var runner = new Runner(4);
+ new HTML(runner); // eslint-disable-line no-new
+ var rootSuite = new Suite('', new Context());
+ rootSuite.addTest(new Test('passing', function () { /* content here */; })); // eslint-disable-line no-extra-semi
+ rootSuite.addTest(new Test('pending'));
+ rootSuite.addTest(new Test('skipped at runtime', function () { this.skip(); }));
+ var failingTest = function () { throw new Error('fail test'); };
+ rootSuite.addTest(new Test('failing', failingTest));
+ runner.emit('start');
+ runner.emit('suite', rootSuite);
+ runner.emit('test', rootSuite.tests[0]);
+ rootSuite.tests[0].duration = 0;
+ rootSuite.tests[0].state = 'passed';
+ runner.emit('pass', rootSuite.tests[0]);
+ runner.emit('test end', rootSuite.tests[0]);
+ // no 'test' event is emitted for pending tests
+ runner.emit('pending', rootSuite.tests[1]);
+ runner.emit('test end', rootSuite.tests[1]);
+ runner.emit('test', rootSuite.tests[2]);
+ rootSuite.tests[2].pending = true;
+ rootSuite.tests[2].duration = 0;
+ runner.emit('pending', rootSuite.tests[2]);
+ runner.emit('test end', rootSuite.tests[2]);
+ runner.emit('test', rootSuite.tests[3]);
+ rootSuite.tests[3].duration = 0;
+ rootSuite.tests[3].state = 'failed';
+ try {
+ failingTest();
+ throw new Error('Failing test did not throw assertion');
+ } catch (assertion) {
+ runner.emit('fail', rootSuite.tests[3], assertion);
+ }
+ runner.emit('test end', rootSuite.tests[3]);
+ runner.emit('suite end', rootSuite);
+ runner.emit('end');
+ click(output.getElementsByClassName('passes').item(0).getElementsByTagName('a').item(0));
+ var tests = output.getElementsByClassName('test');
+ for (var index = 0; index < tests.length; index += 1) {
+ if (/\bpass\b/.test(tests[index].className)) {
+ assertDisplayed(tests[index]);
+ }
+ }
+ restoreOutput();
+ } catch (error) {
+ try {
+ restoreOutput();
+ } catch (ignore) {}
+ throw error;
+ }
+ });
+
+ it('should hide all non-passed tests', function () {
+ try {
+ var output = stubOutput();
+ var runner = new Runner(4);
+ new HTML(runner); // eslint-disable-line no-new
+ var rootSuite = new Suite('', new Context());
+ rootSuite.addTest(new Test('passing', function () { /* content here */; })); // eslint-disable-line no-extra-semi
+ rootSuite.addTest(new Test('pending'));
+ rootSuite.addTest(new Test('skipped at runtime', function () { this.skip(); }));
+ var failingTest = function () { throw new Error('fail test'); };
+ rootSuite.addTest(new Test('failing', failingTest));
+ runner.emit('start');
+ runner.emit('suite', rootSuite);
+ runner.emit('test', rootSuite.tests[0]);
+ rootSuite.tests[0].duration = 0;
+ rootSuite.tests[0].state = 'passed';
+ runner.emit('pass', rootSuite.tests[0]);
+ runner.emit('test end', rootSuite.tests[0]);
+ // no 'test' event is emitted for pending tests
+ runner.emit('pending', rootSuite.tests[1]);
+ runner.emit('test end', rootSuite.tests[1]);
+ runner.emit('test', rootSuite.tests[2]);
+ rootSuite.tests[2].pending = true;
+ rootSuite.tests[2].duration = 0;
+ runner.emit('pending', rootSuite.tests[2]);
+ runner.emit('test end', rootSuite.tests[2]);
+ runner.emit('test', rootSuite.tests[3]);
+ rootSuite.tests[3].duration = 0;
+ rootSuite.tests[3].state = 'failed';
+ try {
+ failingTest();
+ throw new Error('Failing test did not throw assertion');
+ } catch (assertion) {
+ runner.emit('fail', rootSuite.tests[3], assertion);
+ }
+ runner.emit('test end', rootSuite.tests[3]);
+ runner.emit('suite end', rootSuite);
+ runner.emit('end');
+ click(output.getElementsByClassName('passes').item(0).getElementsByTagName('a').item(0));
+ var tests = output.getElementsByClassName('test');
+ for (var index = 0; index < tests.length; index += 1) {
+ if (!/\bpass\b/.test(tests[index].className)) {
+ assertDisplayed(tests[index], false);
+ }
+ }
+ restoreOutput();
+ } catch (error) {
+ try {
+ restoreOutput();
+ } catch (ignore) {}
+ throw error;
+ }
+ });
+
+ it('should hide suites with only non-passed tests', function () {
+ try {
+ var output = stubOutput();
+ var runner = new Runner(4);
+ new HTML(runner); // eslint-disable-line no-new
+ var rootSuite = new Suite('', new Context());
+ Suite.create(rootSuite, 'passing');
+ rootSuite.suites[0].addTest(new Test('passing', function () { /* content here */; })); // eslint-disable-line no-extra-semi
+ Suite.create(rootSuite, 'pending');
+ rootSuite.suites[1].addTest(new Test('pending'));
+ rootSuite.suites[1].addTest(new Test('skipped at runtime', function () { this.skip(); }));
+ Suite.create(rootSuite, 'failing');
+ var failingTest = function () { throw new Error('fail test'); };
+ rootSuite.suites[2].addTest(new Test('failing', failingTest));
+ runner.emit('start');
+ runner.emit('suite', rootSuite);
+ runner.emit('suite', rootSuite.suites[0]);
+ runner.emit('test', rootSuite.suites[0].tests[0]);
+ rootSuite.suites[0].tests[0].duration = 0;
+ rootSuite.suites[0].tests[0].state = 'passed';
+ runner.emit('pass', rootSuite.suites[0].tests[0]);
+ runner.emit('test end', rootSuite.suites[0].tests[0]);
+ runner.emit('suite end', rootSuite.suites[0]);
+ runner.emit('suite', rootSuite.suites[1]);
+ // no 'test' event is emitted for pending tests
+ runner.emit('pending', rootSuite.suites[1].tests[0]);
+ runner.emit('test end', rootSuite.suites[1].tests[0]);
+ runner.emit('test', rootSuite.suites[1].tests[1]);
+ rootSuite.suites[1].tests[1].pending = true;
+ rootSuite.suites[1].tests[1].duration = 0;
+ runner.emit('pending', rootSuite.suites[1].tests[1]);
+ runner.emit('test end', rootSuite.suites[1].tests[1]);
+ runner.emit('suite end', rootSuite.suites[1]);
+ runner.emit('suite', rootSuite.suites[2]);
+ runner.emit('test', rootSuite.suites[2].tests[0]);
+ rootSuite.suites[2].tests[0].duration = 0;
+ rootSuite.suites[2].tests[0].state = 'failed';
+ try {
+ failingTest();
+ throw new Error('Failing test did not throw assertion');
+ } catch (assertion) {
+ runner.emit('fail', rootSuite.suites[2].tests[0], assertion);
+ }
+ runner.emit('test end', rootSuite.suites[2].tests[0]);
+ runner.emit('suite end', rootSuite.suites[2]);
+ runner.emit('suite end', rootSuite);
+ runner.emit('end');
+ click(output.getElementsByClassName('passes').item(0).getElementsByTagName('a').item(0));
+ var suites = output.getElementsByClassName('suite');
+ for (var index = 0; index < suites.length; index += 1) {
+ if (!suites[index].getElementsByClassName('test pass').length) {
+ assertDisplayed(suites[index], false);
+ }
+ }
+ restoreOutput();
+ } catch (error) {
+ try {
+ restoreOutput();
+ } catch (ignore) {}
+ throw error;
+ }
+ });
+
+ it('should not hide suites with passed tests', function () {
+ try {
+ var output = stubOutput();
+ var runner = new Runner(4);
+ new HTML(runner); // eslint-disable-line no-new
+ var rootSuite = new Suite('', new Context());
+ Suite.create(rootSuite, 'passing');
+ rootSuite.suites[0].addTest(new Test('passing', function () { /* content here */; })); // eslint-disable-line no-extra-semi
+ Suite.create(rootSuite, 'pending');
+ rootSuite.suites[1].addTest(new Test('pending'));
+ rootSuite.suites[1].addTest(new Test('skipped at runtime', function () { this.skip(); }));
+ Suite.create(rootSuite, 'failing');
+ var failingTest = function () { throw new Error('fail test'); };
+ rootSuite.suites[2].addTest(new Test('failing', failingTest));
+ runner.emit('start');
+ runner.emit('suite', rootSuite);
+ runner.emit('suite', rootSuite.suites[0]);
+ runner.emit('test', rootSuite.suites[0].tests[0]);
+ rootSuite.suites[0].tests[0].duration = 0;
+ rootSuite.suites[0].tests[0].state = 'passed';
+ runner.emit('pass', rootSuite.suites[0].tests[0]);
+ runner.emit('test end', rootSuite.suites[0].tests[0]);
+ runner.emit('suite end', rootSuite.suites[0]);
+ runner.emit('suite', rootSuite.suites[1]);
+ // no 'test' event is emitted for pending tests
+ runner.emit('pending', rootSuite.suites[1].tests[0]);
+ runner.emit('test end', rootSuite.suites[1].tests[0]);
+ runner.emit('test', rootSuite.suites[1].tests[1]);
+ rootSuite.suites[1].tests[1].pending = true;
+ rootSuite.suites[1].tests[1].duration = 0;
+ runner.emit('pending', rootSuite.suites[1].tests[1]);
+ runner.emit('test end', rootSuite.suites[1].tests[1]);
+ runner.emit('suite end', rootSuite.suites[1]);
+ runner.emit('suite', rootSuite.suites[2]);
+ runner.emit('test', rootSuite.suites[2].tests[0]);
+ rootSuite.suites[2].tests[0].duration = 0;
+ rootSuite.suites[2].tests[0].state = 'failed';
+ try {
+ failingTest();
+ throw new Error('Failing test did not throw assertion');
+ } catch (assertion) {
+ runner.emit('fail', rootSuite.suites[2].tests[0], assertion);
+ }
+ runner.emit('test end', rootSuite.suites[2].tests[0]);
+ runner.emit('suite end', rootSuite.suites[2]);
+ runner.emit('suite end', rootSuite);
+ runner.emit('end');
+ click(output.getElementsByClassName('passes').item(0).getElementsByTagName('a').item(0));
+ var suites = output.getElementsByClassName('suite');
+ for (var index = 0; index < suites.length; index += 1) {
+ if (suites[index].getElementsByClassName('test pass').length > 0) {
+ assertDisplayed(suites[index]);
+ }
+ }
+ restoreOutput();
+ } catch (error) {
+ try {
+ restoreOutput();
+ } catch (ignore) {}
+ throw error;
+ }
+ });
+
+ it('should unhide all tests and suites when clicked again', function () {
+ try {
+ var output = stubOutput();
+ var runner = new Runner(4);
+ new HTML(runner); // eslint-disable-line no-new
+ var rootSuite = new Suite('', new Context());
+ Suite.create(rootSuite, 'passing');
+ rootSuite.suites[0].addTest(new Test('passing', function () { /* content here */; })); // eslint-disable-line no-extra-semi
+ Suite.create(rootSuite, 'pending');
+ rootSuite.suites[1].addTest(new Test('pending'));
+ rootSuite.suites[1].addTest(new Test('skipped at runtime', function () { this.skip(); }));
+ Suite.create(rootSuite, 'failing');
+ var failingTest = function () { throw new Error('fail test'); };
+ rootSuite.suites[2].addTest(new Test('failing', failingTest));
+ runner.emit('start');
+ runner.emit('suite', rootSuite);
+ runner.emit('suite', rootSuite.suites[0]);
+ runner.emit('test', rootSuite.suites[0].tests[0]);
+ rootSuite.suites[0].tests[0].duration = 0;
+ rootSuite.suites[0].tests[0].state = 'passed';
+ runner.emit('pass', rootSuite.suites[0].tests[0]);
+ runner.emit('test end', rootSuite.suites[0].tests[0]);
+ runner.emit('suite end', rootSuite.suites[0]);
+ runner.emit('suite', rootSuite.suites[1]);
+ // no 'test' event is emitted for pending tests
+ runner.emit('pending', rootSuite.suites[1].tests[0]);
+ runner.emit('test end', rootSuite.suites[1].tests[0]);
+ runner.emit('test', rootSuite.suites[1].tests[1]);
+ rootSuite.suites[1].tests[1].pending = true;
+ rootSuite.suites[1].tests[1].duration = 0;
+ runner.emit('pending', rootSuite.suites[1].tests[1]);
+ runner.emit('test end', rootSuite.suites[1].tests[1]);
+ runner.emit('suite end', rootSuite.suites[1]);
+ runner.emit('suite', rootSuite.suites[2]);
+ runner.emit('test', rootSuite.suites[2].tests[0]);
+ rootSuite.suites[2].tests[0].duration = 0;
+ rootSuite.suites[2].tests[0].state = 'failed';
+ try {
+ failingTest();
+ throw new Error('Failing test did not throw assertion');
+ } catch (assertion) {
+ runner.emit('fail', rootSuite.suites[2].tests[0], assertion);
+ }
+ runner.emit('test end', rootSuite.suites[2].tests[0]);
+ runner.emit('suite end', rootSuite.suites[2]);
+ runner.emit('suite end', rootSuite);
+ runner.emit('end');
+ click(output.getElementsByClassName('passes').item(0).getElementsByTagName('a').item(0));
+ click(output.getElementsByClassName('passes').item(0).getElementsByTagName('a').item(0));
+ var suites = output.getElementsByClassName('suite');
+ for (var suiteIndex = 0; suiteIndex < suites.length; suiteIndex += 1) {
+ assertDisplayed(suites[suiteIndex]);
+ }
+ var tests = output.getElementsByClassName('test');
+ for (var testIndex = 0; testIndex < tests.length; testIndex += 1) {
+ assertDisplayed(tests[testIndex]);
+ }
+ restoreOutput();
+ } catch (error) {
+ try {
+ restoreOutput();
+ } catch (ignore) {}
+ throw error;
+ }
+ });
+
+ describe('after failures filter was clicked', function () {
+ it('should show passed tests', function () {
+ try {
+ var output = stubOutput();
+ var runner = new Runner(4);
+ new HTML(runner); // eslint-disable-line no-new
+ var rootSuite = new Suite('', new Context());
+ rootSuite.addTest(new Test('passing', function () { /* content here */; })); // eslint-disable-line no-extra-semi
+ rootSuite.addTest(new Test('pending'));
+ rootSuite.addTest(new Test('skipped at runtime', function () { this.skip(); }));
+ var failingTest = function () { throw new Error('fail test'); };
+ rootSuite.addTest(new Test('failing', failingTest));
+ runner.emit('start');
+ runner.emit('suite', rootSuite);
+ runner.emit('test', rootSuite.tests[0]);
+ rootSuite.tests[0].duration = 0;
+ rootSuite.tests[0].state = 'passed';
+ runner.emit('pass', rootSuite.tests[0]);
+ runner.emit('test end', rootSuite.tests[0]);
+ // no 'test' event is emitted for pending tests
+ runner.emit('pending', rootSuite.tests[1]);
+ runner.emit('test end', rootSuite.tests[1]);
+ runner.emit('test', rootSuite.tests[2]);
+ rootSuite.tests[2].pending = true;
+ rootSuite.tests[2].duration = 0;
+ runner.emit('pending', rootSuite.tests[2]);
+ runner.emit('test end', rootSuite.tests[2]);
+ runner.emit('test', rootSuite.tests[3]);
+ rootSuite.tests[3].duration = 0;
+ rootSuite.tests[3].state = 'failed';
+ try {
+ failingTest();
+ throw new Error('Failing test did not throw assertion');
+ } catch (assertion) {
+ runner.emit('fail', rootSuite.tests[3], assertion);
+ }
+ runner.emit('test end', rootSuite.tests[3]);
+ runner.emit('suite end', rootSuite);
+ runner.emit('end');
+ click(output.getElementsByClassName('failures').item(0).getElementsByTagName('a').item(0));
+ click(output.getElementsByClassName('passes').item(0).getElementsByTagName('a').item(0));
+ var tests = output.getElementsByClassName('test');
+ for (var index = 0; index < tests.length; index += 1) {
+ if (/\bpass\b/.test(tests[index].className)) {
+ assertDisplayed(tests[index]);
+ }
+ }
+ restoreOutput();
+ } catch (error) {
+ try {
+ restoreOutput();
+ } catch (ignore) {}
+ throw error;
+ }
+ });
+
+ it('should hide all non-passed tests', function () {
+ try {
+ var output = stubOutput();
+ var runner = new Runner(4);
+ new HTML(runner); // eslint-disable-line no-new
+ var rootSuite = new Suite('', new Context());
+ rootSuite.addTest(new Test('passing', function () { /* content here */; })); // eslint-disable-line no-extra-semi
+ rootSuite.addTest(new Test('pending'));
+ rootSuite.addTest(new Test('skipped at runtime', function () { this.skip(); }));
+ var failingTest = function () { throw new Error('fail test'); };
+ rootSuite.addTest(new Test('failing', failingTest));
+ runner.emit('start');
+ runner.emit('suite', rootSuite);
+ runner.emit('test', rootSuite.tests[0]);
+ rootSuite.tests[0].duration = 0;
+ rootSuite.tests[0].state = 'passed';
+ runner.emit('pass', rootSuite.tests[0]);
+ runner.emit('test end', rootSuite.tests[0]);
+ // no 'test' event is emitted for pending tests
+ runner.emit('pending', rootSuite.tests[1]);
+ runner.emit('test end', rootSuite.tests[1]);
+ runner.emit('test', rootSuite.tests[2]);
+ rootSuite.tests[2].pending = true;
+ rootSuite.tests[2].duration = 0;
+ runner.emit('pending', rootSuite.tests[2]);
+ runner.emit('test end', rootSuite.tests[2]);
+ runner.emit('test', rootSuite.tests[3]);
+ rootSuite.tests[3].duration = 0;
+ rootSuite.tests[3].state = 'failed';
+ try {
+ failingTest();
+ throw new Error('Failing test did not throw assertion');
+ } catch (assertion) {
+ runner.emit('fail', rootSuite.tests[3], assertion);
+ }
+ runner.emit('test end', rootSuite.tests[3]);
+ runner.emit('suite end', rootSuite);
+ runner.emit('end');
+ click(output.getElementsByClassName('failures').item(0).getElementsByTagName('a').item(0));
+ click(output.getElementsByClassName('passes').item(0).getElementsByTagName('a').item(0));
+ var tests = output.getElementsByClassName('test');
+ for (var index = 0; index < tests.length; index += 1) {
+ if (!/\bpass\b/.test(tests[index].className)) {
+ assertDisplayed(tests[index], false);
+ }
+ }
+ restoreOutput();
+ } catch (error) {
+ try {
+ restoreOutput();
+ } catch (ignore) {}
+ throw error;
+ }
+ });
+
+ it('should hide suites with only non-passed tests', function () {
+ try {
+ var output = stubOutput();
+ var runner = new Runner(4);
+ new HTML(runner); // eslint-disable-line no-new
+ var rootSuite = new Suite('', new Context());
+ Suite.create(rootSuite, 'passing');
+ rootSuite.suites[0].addTest(new Test('passing', function () { /* content here */; })); // eslint-disable-line no-extra-semi
+ Suite.create(rootSuite, 'pending');
+ rootSuite.suites[1].addTest(new Test('pending'));
+ rootSuite.suites[1].addTest(new Test('skipped at runtime', function () { this.skip(); }));
+ Suite.create(rootSuite, 'failing');
+ var failingTest = function () { throw new Error('fail test'); };
+ rootSuite.suites[2].addTest(new Test('failing', failingTest));
+ runner.emit('start');
+ runner.emit('suite', rootSuite);
+ runner.emit('suite', rootSuite.suites[0]);
+ runner.emit('test', rootSuite.suites[0].tests[0]);
+ rootSuite.suites[0].tests[0].duration = 0;
+ rootSuite.suites[0].tests[0].state = 'passed';
+ runner.emit('pass', rootSuite.suites[0].tests[0]);
+ runner.emit('test end', rootSuite.suites[0].tests[0]);
+ runner.emit('suite end', rootSuite.suites[0]);
+ runner.emit('suite', rootSuite.suites[1]);
+ // no 'test' event is emitted for pending tests
+ runner.emit('pending', rootSuite.suites[1].tests[0]);
+ runner.emit('test end', rootSuite.suites[1].tests[0]);
+ runner.emit('test', rootSuite.suites[1].tests[1]);
+ rootSuite.suites[1].tests[1].pending = true;
+ rootSuite.suites[1].tests[1].duration = 0;
+ runner.emit('pending', rootSuite.suites[1].tests[1]);
+ runner.emit('test end', rootSuite.suites[1].tests[1]);
+ runner.emit('suite end', rootSuite.suites[1]);
+ runner.emit('suite', rootSuite.suites[2]);
+ runner.emit('test', rootSuite.suites[2].tests[0]);
+ rootSuite.suites[2].tests[0].duration = 0;
+ rootSuite.suites[2].tests[0].state = 'failed';
+ try {
+ failingTest();
+ throw new Error('Failing test did not throw assertion');
+ } catch (assertion) {
+ runner.emit('fail', rootSuite.suites[2].tests[0], assertion);
+ }
+ runner.emit('test end', rootSuite.suites[2].tests[0]);
+ runner.emit('suite end', rootSuite.suites[2]);
+ runner.emit('suite end', rootSuite);
+ runner.emit('end');
+ click(output.getElementsByClassName('failures').item(0).getElementsByTagName('a').item(0));
+ click(output.getElementsByClassName('passes').item(0).getElementsByTagName('a').item(0));
+ var suites = output.getElementsByClassName('suite');
+ for (var index = 0; index < suites.length; index += 1) {
+ if (!suites[index].getElementsByClassName('test pass').length) {
+ assertDisplayed(suites[index], false);
+ }
+ }
+ restoreOutput();
+ } catch (error) {
+ try {
+ restoreOutput();
+ } catch (ignore) {}
+ throw error;
+ }
+ });
+
+ it('should not hide suites with passed tests', function () {
+ try {
+ var output = stubOutput();
+ var runner = new Runner(4);
+ new HTML(runner); // eslint-disable-line no-new
+ var rootSuite = new Suite('', new Context());
+ Suite.create(rootSuite, 'passing');
+ rootSuite.suites[0].addTest(new Test('passing', function () { /* content here */; })); // eslint-disable-line no-extra-semi
+ Suite.create(rootSuite, 'pending');
+ rootSuite.suites[1].addTest(new Test('pending'));
+ rootSuite.suites[1].addTest(new Test('skipped at runtime', function () { this.skip(); }));
+ Suite.create(rootSuite, 'failing');
+ var failingTest = function () { throw new Error('fail test'); };
+ rootSuite.suites[2].addTest(new Test('failing', failingTest));
+ runner.emit('start');
+ runner.emit('suite', rootSuite);
+ runner.emit('suite', rootSuite.suites[0]);
+ runner.emit('test', rootSuite.suites[0].tests[0]);
+ rootSuite.suites[0].tests[0].duration = 0;
+ rootSuite.suites[0].tests[0].state = 'passed';
+ runner.emit('pass', rootSuite.suites[0].tests[0]);
+ runner.emit('test end', rootSuite.suites[0].tests[0]);
+ runner.emit('suite end', rootSuite.suites[0]);
+ runner.emit('suite', rootSuite.suites[1]);
+ // no 'test' event is emitted for pending tests
+ runner.emit('pending', rootSuite.suites[1].tests[0]);
+ runner.emit('test end', rootSuite.suites[1].tests[0]);
+ runner.emit('test', rootSuite.suites[1].tests[1]);
+ rootSuite.suites[1].tests[1].pending = true;
+ rootSuite.suites[1].tests[1].duration = 0;
+ runner.emit('pending', rootSuite.suites[1].tests[1]);
+ runner.emit('test end', rootSuite.suites[1].tests[1]);
+ runner.emit('suite end', rootSuite.suites[1]);
+ runner.emit('suite', rootSuite.suites[2]);
+ runner.emit('test', rootSuite.suites[2].tests[0]);
+ rootSuite.suites[2].tests[0].duration = 0;
+ rootSuite.suites[2].tests[0].state = 'failed';
+ try {
+ failingTest();
+ throw new Error('Failing test did not throw assertion');
+ } catch (assertion) {
+ runner.emit('fail', rootSuite.suites[2].tests[0], assertion);
+ }
+ runner.emit('test end', rootSuite.suites[2].tests[0]);
+ runner.emit('suite end', rootSuite.suites[2]);
+ runner.emit('suite end', rootSuite);
+ runner.emit('end');
+ click(output.getElementsByClassName('failures').item(0).getElementsByTagName('a').item(0));
+ click(output.getElementsByClassName('passes').item(0).getElementsByTagName('a').item(0));
+ var suites = output.getElementsByClassName('suite');
+ for (var index = 0; index < suites.length; index += 1) {
+ if (suites[index].getElementsByClassName('test pass').length > 0) {
+ assertDisplayed(suites[index]);
+ }
+ }
+ restoreOutput();
+ } catch (error) {
+ try {
+ restoreOutput();
+ } catch (ignore) {}
+ throw error;
+ }
+ });
+
+ it('should unhide all tests and suites when clicked again', function () {
+ try {
+ var output = stubOutput();
+ var runner = new Runner(4);
+ new HTML(runner); // eslint-disable-line no-new
+ var rootSuite = new Suite('', new Context());
+ Suite.create(rootSuite, 'passing');
+ rootSuite.suites[0].addTest(new Test('passing', function () { /* content here */; })); // eslint-disable-line no-extra-semi
+ Suite.create(rootSuite, 'pending');
+ rootSuite.suites[1].addTest(new Test('pending'));
+ rootSuite.suites[1].addTest(new Test('skipped at runtime', function () { this.skip(); }));
+ Suite.create(rootSuite, 'failing');
+ var failingTest = function () { throw new Error('fail test'); };
+ rootSuite.suites[2].addTest(new Test('failing', failingTest));
+ runner.emit('start');
+ runner.emit('suite', rootSuite);
+ runner.emit('suite', rootSuite.suites[0]);
+ runner.emit('test', rootSuite.suites[0].tests[0]);
+ rootSuite.suites[0].tests[0].duration = 0;
+ rootSuite.suites[0].tests[0].state = 'passed';
+ runner.emit('pass', rootSuite.suites[0].tests[0]);
+ runner.emit('test end', rootSuite.suites[0].tests[0]);
+ runner.emit('suite end', rootSuite.suites[0]);
+ runner.emit('suite', rootSuite.suites[1]);
+ // no 'test' event is emitted for pending tests
+ runner.emit('pending', rootSuite.suites[1].tests[0]);
+ runner.emit('test end', rootSuite.suites[1].tests[0]);
+ runner.emit('test', rootSuite.suites[1].tests[1]);
+ rootSuite.suites[1].tests[1].pending = true;
+ rootSuite.suites[1].tests[1].duration = 0;
+ runner.emit('pending', rootSuite.suites[1].tests[1]);
+ runner.emit('test end', rootSuite.suites[1].tests[1]);
+ runner.emit('suite end', rootSuite.suites[1]);
+ runner.emit('suite', rootSuite.suites[2]);
+ runner.emit('test', rootSuite.suites[2].tests[0]);
+ rootSuite.suites[2].tests[0].duration = 0;
+ rootSuite.suites[2].tests[0].state = 'failed';
+ try {
+ failingTest();
+ throw new Error('Failing test did not throw assertion');
+ } catch (assertion) {
+ runner.emit('fail', rootSuite.suites[2].tests[0], assertion);
+ }
+ runner.emit('test end', rootSuite.suites[2].tests[0]);
+ runner.emit('suite end', rootSuite.suites[2]);
+ runner.emit('suite end', rootSuite);
+ runner.emit('end');
+ click(output.getElementsByClassName('failures').item(0).getElementsByTagName('a').item(0));
+ click(output.getElementsByClassName('passes').item(0).getElementsByTagName('a').item(0));
+ click(output.getElementsByClassName('passes').item(0).getElementsByTagName('a').item(0));
+ var suites = output.getElementsByClassName('suite');
+ for (var suiteIndex = 0; suiteIndex < suites.length; suiteIndex += 1) {
+ assertDisplayed(suites[suiteIndex]);
+ }
+ var tests = output.getElementsByClassName('test');
+ for (var testIndex = 0; testIndex < tests.length; testIndex += 1) {
+ assertDisplayed(tests[testIndex]);
+ }
+ restoreOutput();
+ } catch (error) {
+ try {
+ restoreOutput();
+ } catch (ignore) {}
+ throw error;
+ }
+ });
+ });
+ });
+
+ describe('failures filter', function () {
+ it('should still show failed tests', function () {
+ try {
+ var output = stubOutput();
+ var runner = new Runner(4);
+ new HTML(runner); // eslint-disable-line no-new
+ var rootSuite = new Suite('', new Context());
+ rootSuite.addTest(new Test('passing', function () { /* content here */; })); // eslint-disable-line no-extra-semi
+ rootSuite.addTest(new Test('pending'));
+ rootSuite.addTest(new Test('skipped at runtime', function () { this.skip(); }));
+ var failingTest = function () { throw new Error('fail test'); };
+ rootSuite.addTest(new Test('failing', failingTest));
+ runner.emit('start');
+ runner.emit('suite', rootSuite);
+ runner.emit('test', rootSuite.tests[0]);
+ rootSuite.tests[0].duration = 0;
+ rootSuite.tests[0].state = 'passed';
+ runner.emit('pass', rootSuite.tests[0]);
+ runner.emit('test end', rootSuite.tests[0]);
+ // no 'test' event is emitted for pending tests
+ runner.emit('pending', rootSuite.tests[1]);
+ runner.emit('test end', rootSuite.tests[1]);
+ runner.emit('test', rootSuite.tests[2]);
+ rootSuite.tests[2].pending = true;
+ rootSuite.tests[2].duration = 0;
+ runner.emit('pending', rootSuite.tests[2]);
+ runner.emit('test end', rootSuite.tests[2]);
+ runner.emit('test', rootSuite.tests[3]);
+ rootSuite.tests[3].duration = 0;
+ rootSuite.tests[3].state = 'failed';
+ try {
+ failingTest();
+ throw new Error('Failing test did not throw assertion');
+ } catch (assertion) {
+ runner.emit('fail', rootSuite.tests[3], assertion);
+ }
+ runner.emit('test end', rootSuite.tests[3]);
+ runner.emit('suite end', rootSuite);
+ runner.emit('end');
+ click(output.getElementsByClassName('failures').item(0).getElementsByTagName('a').item(0));
+ var tests = output.getElementsByClassName('test');
+ for (var index = 0; index < tests.length; index += 1) {
+ if (/\bfail\b/.test(tests[index].className)) {
+ assertDisplayed(tests[index]);
+ }
+ }
+ restoreOutput();
+ } catch (error) {
+ try {
+ restoreOutput();
+ } catch (ignore) {}
+ throw error;
+ }
+ });
+
+ it('should hide all non-failed tests', function () {
+ try {
+ var output = stubOutput();
+ var runner = new Runner(4);
+ new HTML(runner); // eslint-disable-line no-new
+ var rootSuite = new Suite('', new Context());
+ rootSuite.addTest(new Test('passing', function () { /* content here */; })); // eslint-disable-line no-extra-semi
+ rootSuite.addTest(new Test('pending'));
+ rootSuite.addTest(new Test('skipped at runtime', function () { this.skip(); }));
+ var failingTest = function () { throw new Error('fail test'); };
+ rootSuite.addTest(new Test('failing', failingTest));
+ runner.emit('start');
+ runner.emit('suite', rootSuite);
+ runner.emit('test', rootSuite.tests[0]);
+ rootSuite.tests[0].duration = 0;
+ rootSuite.tests[0].state = 'passed';
+ runner.emit('pass', rootSuite.tests[0]);
+ runner.emit('test end', rootSuite.tests[0]);
+ // no 'test' event is emitted for pending tests
+ runner.emit('pending', rootSuite.tests[1]);
+ runner.emit('test end', rootSuite.tests[1]);
+ runner.emit('test', rootSuite.tests[2]);
+ rootSuite.tests[2].pending = true;
+ rootSuite.tests[2].duration = 0;
+ runner.emit('pending', rootSuite.tests[2]);
+ runner.emit('test end', rootSuite.tests[2]);
+ runner.emit('test', rootSuite.tests[3]);
+ rootSuite.tests[3].duration = 0;
+ rootSuite.tests[3].state = 'failed';
+ try {
+ failingTest();
+ throw new Error('Failing test did not throw assertion');
+ } catch (assertion) {
+ runner.emit('fail', rootSuite.tests[3], assertion);
+ }
+ runner.emit('test end', rootSuite.tests[3]);
+ runner.emit('suite end', rootSuite);
+ runner.emit('end');
+ click(output.getElementsByClassName('failures').item(0).getElementsByTagName('a').item(0));
+ var tests = output.getElementsByClassName('test');
+ for (var index = 0; index < tests.length; index += 1) {
+ if (!/\bfail\b/.test(tests[index].className)) {
+ assertDisplayed(tests[index], false);
+ }
+ }
+ restoreOutput();
+ } catch (error) {
+ try {
+ restoreOutput();
+ } catch (ignore) {}
+ throw error;
+ }
+ });
+
+ it('should hide suites with only non-failed tests', function () {
+ try {
+ var output = stubOutput();
+ var runner = new Runner(4);
+ new HTML(runner); // eslint-disable-line no-new
+ var rootSuite = new Suite('', new Context());
+ Suite.create(rootSuite, 'passing');
+ rootSuite.suites[0].addTest(new Test('passing', function () { /* content here */; })); // eslint-disable-line no-extra-semi
+ Suite.create(rootSuite, 'pending');
+ rootSuite.suites[1].addTest(new Test('pending'));
+ rootSuite.suites[1].addTest(new Test('skipped at runtime', function () { this.skip(); }));
+ Suite.create(rootSuite, 'failing');
+ var failingTest = function () { throw new Error('fail test'); };
+ rootSuite.suites[2].addTest(new Test('failing', failingTest));
+ runner.emit('start');
+ runner.emit('suite', rootSuite);
+ runner.emit('suite', rootSuite.suites[0]);
+ runner.emit('test', rootSuite.suites[0].tests[0]);
+ rootSuite.suites[0].tests[0].duration = 0;
+ rootSuite.suites[0].tests[0].state = 'passed';
+ runner.emit('pass', rootSuite.suites[0].tests[0]);
+ runner.emit('test end', rootSuite.suites[0].tests[0]);
+ runner.emit('suite end', rootSuite.suites[0]);
+ runner.emit('suite', rootSuite.suites[1]);
+ // no 'test' event is emitted for pending tests
+ runner.emit('pending', rootSuite.suites[1].tests[0]);
+ runner.emit('test end', rootSuite.suites[1].tests[0]);
+ runner.emit('test', rootSuite.suites[1].tests[1]);
+ rootSuite.suites[1].tests[1].pending = true;
+ rootSuite.suites[1].tests[1].duration = 0;
+ runner.emit('pending', rootSuite.suites[1].tests[1]);
+ runner.emit('test end', rootSuite.suites[1].tests[1]);
+ runner.emit('suite end', rootSuite.suites[1]);
+ runner.emit('suite', rootSuite.suites[2]);
+ runner.emit('test', rootSuite.suites[2].tests[0]);
+ rootSuite.suites[2].tests[0].duration = 0;
+ rootSuite.suites[2].tests[0].state = 'failed';
+ try {
+ failingTest();
+ throw new Error('Failing test did not throw assertion');
+ } catch (assertion) {
+ runner.emit('fail', rootSuite.suites[2].tests[0], assertion);
+ }
+ runner.emit('test end', rootSuite.suites[2].tests[0]);
+ runner.emit('suite end', rootSuite.suites[2]);
+ runner.emit('suite end', rootSuite);
+ runner.emit('end');
+ click(output.getElementsByClassName('failures').item(0).getElementsByTagName('a').item(0));
+ var suites = output.getElementsByClassName('suite');
+ for (var index = 0; index < suites.length; index += 1) {
+ if (!suites[index].getElementsByClassName('test fail').length) {
+ assertDisplayed(suites[index], false);
+ }
+ }
+ restoreOutput();
+ } catch (error) {
+ try {
+ restoreOutput();
+ } catch (ignore) {}
+ throw error;
+ }
+ });
+
+ it('should not hide suites with failed tests', function () {
+ try {
+ var output = stubOutput();
+ var runner = new Runner(4);
+ new HTML(runner); // eslint-disable-line no-new
+ var rootSuite = new Suite('', new Context());
+ Suite.create(rootSuite, 'passing');
+ rootSuite.suites[0].addTest(new Test('passing', function () { /* content here */; })); // eslint-disable-line no-extra-semi
+ Suite.create(rootSuite, 'pending');
+ rootSuite.suites[1].addTest(new Test('pending'));
+ rootSuite.suites[1].addTest(new Test('skipped at runtime', function () { this.skip(); }));
+ Suite.create(rootSuite, 'failing');
+ var failingTest = function () { throw new Error('fail test'); };
+ rootSuite.suites[2].addTest(new Test('failing', failingTest));
+ runner.emit('start');
+ runner.emit('suite', rootSuite);
+ runner.emit('suite', rootSuite.suites[0]);
+ runner.emit('test', rootSuite.suites[0].tests[0]);
+ rootSuite.suites[0].tests[0].duration = 0;
+ rootSuite.suites[0].tests[0].state = 'passed';
+ runner.emit('pass', rootSuite.suites[0].tests[0]);
+ runner.emit('test end', rootSuite.suites[0].tests[0]);
+ runner.emit('suite end', rootSuite.suites[0]);
+ runner.emit('suite', rootSuite.suites[1]);
+ // no 'test' event is emitted for pending tests
+ runner.emit('pending', rootSuite.suites[1].tests[0]);
+ runner.emit('test end', rootSuite.suites[1].tests[0]);
+ runner.emit('test', rootSuite.suites[1].tests[1]);
+ rootSuite.suites[1].tests[1].pending = true;
+ rootSuite.suites[1].tests[1].duration = 0;
+ runner.emit('pending', rootSuite.suites[1].tests[1]);
+ runner.emit('test end', rootSuite.suites[1].tests[1]);
+ runner.emit('suite end', rootSuite.suites[1]);
+ runner.emit('suite', rootSuite.suites[2]);
+ runner.emit('test', rootSuite.suites[2].tests[0]);
+ rootSuite.suites[2].tests[0].duration = 0;
+ rootSuite.suites[2].tests[0].state = 'failed';
+ try {
+ failingTest();
+ throw new Error('Failing test did not throw assertion');
+ } catch (assertion) {
+ runner.emit('fail', rootSuite.suites[2].tests[0], assertion);
+ }
+ runner.emit('test end', rootSuite.suites[2].tests[0]);
+ runner.emit('suite end', rootSuite.suites[2]);
+ runner.emit('suite end', rootSuite);
+ runner.emit('end');
+ click(output.getElementsByClassName('failures').item(0).getElementsByTagName('a').item(0));
+ var suites = output.getElementsByClassName('suite');
+ for (var index = 0; index < suites.length; index += 1) {
+ if (suites[index].getElementsByClassName('test fail').length > 0) {
+ assertDisplayed(suites[index]);
+ }
+ }
+ restoreOutput();
+ } catch (error) {
+ try {
+ restoreOutput();
+ } catch (ignore) {}
+ throw error;
+ }
+ });
+
+ it('should unhide all tests and suites when clicked again', function () {
+ try {
+ var output = stubOutput();
+ var runner = new Runner(4);
+ new HTML(runner); // eslint-disable-line no-new
+ var rootSuite = new Suite('', new Context());
+ Suite.create(rootSuite, 'passing');
+ rootSuite.suites[0].addTest(new Test('passing', function () { /* content here */; })); // eslint-disable-line no-extra-semi
+ Suite.create(rootSuite, 'pending');
+ rootSuite.suites[1].addTest(new Test('pending'));
+ rootSuite.suites[1].addTest(new Test('skipped at runtime', function () { this.skip(); }));
+ Suite.create(rootSuite, 'failing');
+ var failingTest = function () { throw new Error('fail test'); };
+ rootSuite.suites[2].addTest(new Test('failing', failingTest));
+ runner.emit('start');
+ runner.emit('suite', rootSuite);
+ runner.emit('suite', rootSuite.suites[0]);
+ runner.emit('test', rootSuite.suites[0].tests[0]);
+ rootSuite.suites[0].tests[0].duration = 0;
+ rootSuite.suites[0].tests[0].state = 'passed';
+ runner.emit('pass', rootSuite.suites[0].tests[0]);
+ runner.emit('test end', rootSuite.suites[0].tests[0]);
+ runner.emit('suite end', rootSuite.suites[0]);
+ runner.emit('suite', rootSuite.suites[1]);
+ // no 'test' event is emitted for pending tests
+ runner.emit('pending', rootSuite.suites[1].tests[0]);
+ runner.emit('test end', rootSuite.suites[1].tests[0]);
+ runner.emit('test', rootSuite.suites[1].tests[1]);
+ rootSuite.suites[1].tests[1].pending = true;
+ rootSuite.suites[1].tests[1].duration = 0;
+ runner.emit('pending', rootSuite.suites[1].tests[1]);
+ runner.emit('test end', rootSuite.suites[1].tests[1]);
+ runner.emit('suite end', rootSuite.suites[1]);
+ runner.emit('suite', rootSuite.suites[2]);
+ runner.emit('test', rootSuite.suites[2].tests[0]);
+ rootSuite.suites[2].tests[0].duration = 0;
+ rootSuite.suites[2].tests[0].state = 'failed';
+ try {
+ failingTest();
+ throw new Error('Failing test did not throw assertion');
+ } catch (assertion) {
+ runner.emit('fail', rootSuite.suites[2].tests[0], assertion);
+ }
+ runner.emit('test end', rootSuite.suites[2].tests[0]);
+ runner.emit('suite end', rootSuite.suites[2]);
+ runner.emit('suite end', rootSuite);
+ runner.emit('end');
+ click(output.getElementsByClassName('failures').item(0).getElementsByTagName('a').item(0));
+ click(output.getElementsByClassName('failures').item(0).getElementsByTagName('a').item(0));
+ var suites = output.getElementsByClassName('suite');
+ for (var suiteIndex = 0; suiteIndex < suites.length; suiteIndex += 1) {
+ assertDisplayed(suites[suiteIndex]);
+ }
+ var tests = output.getElementsByClassName('test');
+ for (var testIndex = 0; testIndex < tests.length; testIndex += 1) {
+ assertDisplayed(tests[testIndex]);
+ }
+ restoreOutput();
+ } catch (error) {
+ try {
+ restoreOutput();
+ } catch (ignore) {}
+ throw error;
+ }
+ });
+
+ describe('after passes filter was clicked', function () {
+ it('should show failed tests', function () {
+ try {
+ var output = stubOutput();
+ var runner = new Runner(4);
+ new HTML(runner); // eslint-disable-line no-new
+ var rootSuite = new Suite('', new Context());
+ rootSuite.addTest(new Test('passing', function () { /* content here */; })); // eslint-disable-line no-extra-semi
+ rootSuite.addTest(new Test('pending'));
+ rootSuite.addTest(new Test('skipped at runtime', function () { this.skip(); }));
+ var failingTest = function () { throw new Error('fail test'); };
+ rootSuite.addTest(new Test('failing', failingTest));
+ runner.emit('start');
+ runner.emit('suite', rootSuite);
+ runner.emit('test', rootSuite.tests[0]);
+ rootSuite.tests[0].duration = 0;
+ rootSuite.tests[0].state = 'passed';
+ runner.emit('pass', rootSuite.tests[0]);
+ runner.emit('test end', rootSuite.tests[0]);
+ // no 'test' event is emitted for pending tests
+ runner.emit('pending', rootSuite.tests[1]);
+ runner.emit('test end', rootSuite.tests[1]);
+ runner.emit('test', rootSuite.tests[2]);
+ rootSuite.tests[2].pending = true;
+ rootSuite.tests[2].duration = 0;
+ runner.emit('pending', rootSuite.tests[2]);
+ runner.emit('test end', rootSuite.tests[2]);
+ runner.emit('test', rootSuite.tests[3]);
+ rootSuite.tests[3].duration = 0;
+ rootSuite.tests[3].state = 'failed';
+ try {
+ failingTest();
+ throw new Error('Failing test did not throw assertion');
+ } catch (assertion) {
+ runner.emit('fail', rootSuite.tests[3], assertion);
+ }
+ runner.emit('test end', rootSuite.tests[3]);
+ runner.emit('suite end', rootSuite);
+ runner.emit('end');
+ click(output.getElementsByClassName('passes').item(0).getElementsByTagName('a').item(0));
+ click(output.getElementsByClassName('failures').item(0).getElementsByTagName('a').item(0));
+ var tests = output.getElementsByClassName('test');
+ for (var index = 0; index < tests.length; index += 1) {
+ if (/\bfail\b/.test(tests[index].className)) {
+ assertDisplayed(tests[index]);
+ }
+ }
+ restoreOutput();
+ } catch (error) {
+ try {
+ restoreOutput();
+ } catch (ignore) {}
+ throw error;
+ }
+ });
+
+ it('should hide all non-failed tests', function () {
+ try {
+ var output = stubOutput();
+ var runner = new Runner(4);
+ new HTML(runner); // eslint-disable-line no-new
+ var rootSuite = new Suite('', new Context());
+ rootSuite.addTest(new Test('passing', function () { /* content here */; })); // eslint-disable-line no-extra-semi
+ rootSuite.addTest(new Test('pending'));
+ rootSuite.addTest(new Test('skipped at runtime', function () { this.skip(); }));
+ var failingTest = function () { throw new Error('fail test'); };
+ rootSuite.addTest(new Test('failing', failingTest));
+ runner.emit('start');
+ runner.emit('suite', rootSuite);
+ runner.emit('test', rootSuite.tests[0]);
+ rootSuite.tests[0].duration = 0;
+ rootSuite.tests[0].state = 'passed';
+ runner.emit('pass', rootSuite.tests[0]);
+ runner.emit('test end', rootSuite.tests[0]);
+ // no 'test' event is emitted for pending tests
+ runner.emit('pending', rootSuite.tests[1]);
+ runner.emit('test end', rootSuite.tests[1]);
+ runner.emit('test', rootSuite.tests[2]);
+ rootSuite.tests[2].pending = true;
+ rootSuite.tests[2].duration = 0;
+ runner.emit('pending', rootSuite.tests[2]);
+ runner.emit('test end', rootSuite.tests[2]);
+ runner.emit('test', rootSuite.tests[3]);
+ rootSuite.tests[3].duration = 0;
+ rootSuite.tests[3].state = 'failed';
+ try {
+ failingTest();
+ throw new Error('Failing test did not throw assertion');
+ } catch (assertion) {
+ runner.emit('fail', rootSuite.tests[3], assertion);
+ }
+ runner.emit('test end', rootSuite.tests[3]);
+ runner.emit('suite end', rootSuite);
+ runner.emit('end');
+ click(output.getElementsByClassName('passes').item(0).getElementsByTagName('a').item(0));
+ click(output.getElementsByClassName('failures').item(0).getElementsByTagName('a').item(0));
+ var tests = output.getElementsByClassName('test');
+ for (var index = 0; index < tests.length; index += 1) {
+ if (!/\bfail\b/.test(tests[index].className)) {
+ assertDisplayed(tests[index], false);
+ }
+ }
+ restoreOutput();
+ } catch (error) {
+ try {
+ restoreOutput();
+ } catch (ignore) {}
+ throw error;
+ }
+ });
+
+ it('should hide suites with only non-failed tests', function () {
+ try {
+ var output = stubOutput();
+ var runner = new Runner(4);
+ new HTML(runner); // eslint-disable-line no-new
+ var rootSuite = new Suite('', new Context());
+ Suite.create(rootSuite, 'passing');
+ rootSuite.suites[0].addTest(new Test('passing', function () { /* content here */; })); // eslint-disable-line no-extra-semi
+ Suite.create(rootSuite, 'pending');
+ rootSuite.suites[1].addTest(new Test('pending'));
+ rootSuite.suites[1].addTest(new Test('skipped at runtime', function () { this.skip(); }));
+ Suite.create(rootSuite, 'failing');
+ var failingTest = function () { throw new Error('fail test'); };
+ rootSuite.suites[2].addTest(new Test('failing', failingTest));
+ runner.emit('start');
+ runner.emit('suite', rootSuite);
+ runner.emit('suite', rootSuite.suites[0]);
+ runner.emit('test', rootSuite.suites[0].tests[0]);
+ rootSuite.suites[0].tests[0].duration = 0;
+ rootSuite.suites[0].tests[0].state = 'passed';
+ runner.emit('pass', rootSuite.suites[0].tests[0]);
+ runner.emit('test end', rootSuite.suites[0].tests[0]);
+ runner.emit('suite end', rootSuite.suites[0]);
+ runner.emit('suite', rootSuite.suites[1]);
+ // no 'test' event is emitted for pending tests
+ runner.emit('pending', rootSuite.suites[1].tests[0]);
+ runner.emit('test end', rootSuite.suites[1].tests[0]);
+ runner.emit('test', rootSuite.suites[1].tests[1]);
+ rootSuite.suites[1].tests[1].pending = true;
+ rootSuite.suites[1].tests[1].duration = 0;
+ runner.emit('pending', rootSuite.suites[1].tests[1]);
+ runner.emit('test end', rootSuite.suites[1].tests[1]);
+ runner.emit('suite end', rootSuite.suites[1]);
+ runner.emit('suite', rootSuite.suites[2]);
+ runner.emit('test', rootSuite.suites[2].tests[0]);
+ rootSuite.suites[2].tests[0].duration = 0;
+ rootSuite.suites[2].tests[0].state = 'failed';
+ try {
+ failingTest();
+ throw new Error('Failing test did not throw assertion');
+ } catch (assertion) {
+ runner.emit('fail', rootSuite.suites[2].tests[0], assertion);
+ }
+ runner.emit('test end', rootSuite.suites[2].tests[0]);
+ runner.emit('suite end', rootSuite.suites[2]);
+ runner.emit('suite end', rootSuite);
+ runner.emit('end');
+ click(output.getElementsByClassName('passes').item(0).getElementsByTagName('a').item(0));
+ click(output.getElementsByClassName('failures').item(0).getElementsByTagName('a').item(0));
+ var suites = output.getElementsByClassName('suite');
+ for (var index = 0; index < suites.length; index += 1) {
+ if (!suites[index].getElementsByClassName('test fail').length) {
+ assertDisplayed(suites[index], false);
+ }
+ }
+ restoreOutput();
+ } catch (error) {
+ try {
+ restoreOutput();
+ } catch (ignore) {}
+ throw error;
+ }
+ });
+
+ it('should not hide suites with failed tests', function () {
+ try {
+ var output = stubOutput();
+ var runner = new Runner(4);
+ new HTML(runner); // eslint-disable-line no-new
+ var rootSuite = new Suite('', new Context());
+ Suite.create(rootSuite, 'passing');
+ rootSuite.suites[0].addTest(new Test('passing', function () { /* content here */; })); // eslint-disable-line no-extra-semi
+ Suite.create(rootSuite, 'pending');
+ rootSuite.suites[1].addTest(new Test('pending'));
+ rootSuite.suites[1].addTest(new Test('skipped at runtime', function () { this.skip(); }));
+ Suite.create(rootSuite, 'failing');
+ var failingTest = function () { throw new Error('fail test'); };
+ rootSuite.suites[2].addTest(new Test('failing', failingTest));
+ runner.emit('start');
+ runner.emit('suite', rootSuite);
+ runner.emit('suite', rootSuite.suites[0]);
+ runner.emit('test', rootSuite.suites[0].tests[0]);
+ rootSuite.suites[0].tests[0].duration = 0;
+ rootSuite.suites[0].tests[0].state = 'passed';
+ runner.emit('pass', rootSuite.suites[0].tests[0]);
+ runner.emit('test end', rootSuite.suites[0].tests[0]);
+ runner.emit('suite end', rootSuite.suites[0]);
+ runner.emit('suite', rootSuite.suites[1]);
+ // no 'test' event is emitted for pending tests
+ runner.emit('pending', rootSuite.suites[1].tests[0]);
+ runner.emit('test end', rootSuite.suites[1].tests[0]);
+ runner.emit('test', rootSuite.suites[1].tests[1]);
+ rootSuite.suites[1].tests[1].pending = true;
+ rootSuite.suites[1].tests[1].duration = 0;
+ runner.emit('pending', rootSuite.suites[1].tests[1]);
+ runner.emit('test end', rootSuite.suites[1].tests[1]);
+ runner.emit('suite end', rootSuite.suites[1]);
+ runner.emit('suite', rootSuite.suites[2]);
+ runner.emit('test', rootSuite.suites[2].tests[0]);
+ rootSuite.suites[2].tests[0].duration = 0;
+ rootSuite.suites[2].tests[0].state = 'failed';
+ try {
+ failingTest();
+ throw new Error('Failing test did not throw assertion');
+ } catch (assertion) {
+ runner.emit('fail', rootSuite.suites[2].tests[0], assertion);
+ }
+ runner.emit('test end', rootSuite.suites[2].tests[0]);
+ runner.emit('suite end', rootSuite.suites[2]);
+ runner.emit('suite end', rootSuite);
+ runner.emit('end');
+ click(output.getElementsByClassName('passes').item(0).getElementsByTagName('a').item(0));
+ click(output.getElementsByClassName('failures').item(0).getElementsByTagName('a').item(0));
+ var suites = output.getElementsByClassName('suite');
+ for (var index = 0; index < suites.length; index += 1) {
+ if (suites[index].getElementsByClassName('test fail').length > 0) {
+ assertDisplayed(suites[index]);
+ }
+ }
+ restoreOutput();
+ } catch (error) {
+ try {
+ restoreOutput();
+ } catch (ignore) {}
+ throw error;
+ }
+ });
+
+ it('should unhide all tests and suites when clicked again', function () {
+ try {
+ var output = stubOutput();
+ var runner = new Runner(4);
+ new HTML(runner); // eslint-disable-line no-new
+ var rootSuite = new Suite('', new Context());
+ Suite.create(rootSuite, 'passing');
+ rootSuite.suites[0].addTest(new Test('passing', function () { /* content here */; })); // eslint-disable-line no-extra-semi
+ Suite.create(rootSuite, 'pending');
+ rootSuite.suites[1].addTest(new Test('pending'));
+ rootSuite.suites[1].addTest(new Test('skipped at runtime', function () { this.skip(); }));
+ Suite.create(rootSuite, 'failing');
+ var failingTest = function () { throw new Error('fail test'); };
+ rootSuite.suites[2].addTest(new Test('failing', failingTest));
+ runner.emit('start');
+ runner.emit('suite', rootSuite);
+ runner.emit('suite', rootSuite.suites[0]);
+ runner.emit('test', rootSuite.suites[0].tests[0]);
+ rootSuite.suites[0].tests[0].duration = 0;
+ rootSuite.suites[0].tests[0].state = 'passed';
+ runner.emit('pass', rootSuite.suites[0].tests[0]);
+ runner.emit('test end', rootSuite.suites[0].tests[0]);
+ runner.emit('suite end', rootSuite.suites[0]);
+ runner.emit('suite', rootSuite.suites[1]);
+ // no 'test' event is emitted for pending tests
+ runner.emit('pending', rootSuite.suites[1].tests[0]);
+ runner.emit('test end', rootSuite.suites[1].tests[0]);
+ runner.emit('test', rootSuite.suites[1].tests[1]);
+ rootSuite.suites[1].tests[1].pending = true;
+ rootSuite.suites[1].tests[1].duration = 0;
+ runner.emit('pending', rootSuite.suites[1].tests[1]);
+ runner.emit('test end', rootSuite.suites[1].tests[1]);
+ runner.emit('suite end', rootSuite.suites[1]);
+ runner.emit('suite', rootSuite.suites[2]);
+ runner.emit('test', rootSuite.suites[2].tests[0]);
+ rootSuite.suites[2].tests[0].duration = 0;
+ rootSuite.suites[2].tests[0].state = 'failed';
+ try {
+ failingTest();
+ throw new Error('Failing test did not throw assertion');
+ } catch (assertion) {
+ runner.emit('fail', rootSuite.suites[2].tests[0], assertion);
+ }
+ runner.emit('test end', rootSuite.suites[2].tests[0]);
+ runner.emit('suite end', rootSuite.suites[2]);
+ runner.emit('suite end', rootSuite);
+ runner.emit('end');
+ click(output.getElementsByClassName('passes').item(0).getElementsByTagName('a').item(0));
+ click(output.getElementsByClassName('failures').item(0).getElementsByTagName('a').item(0));
+ click(output.getElementsByClassName('failures').item(0).getElementsByTagName('a').item(0));
+ var suites = output.getElementsByClassName('suite');
+ for (var suiteIndex = 0; suiteIndex < suites.length; suiteIndex += 1) {
+ assertDisplayed(suites[suiteIndex]);
+ }
+ var tests = output.getElementsByClassName('test');
+ for (var testIndex = 0; testIndex < tests.length; testIndex += 1) {
+ assertDisplayed(tests[testIndex]);
+ }
+ restoreOutput();
+ } catch (error) {
+ try {
+ restoreOutput();
+ } catch (ignore) {}
+ throw error;
+ }
+ });
+ });
+ });
+
+ describe('test source', function () {
+ it('should not be displayed initially', function () {
+ try {
+ var output = stubOutput();
+ var runner = new Runner(1);
+ new HTML(runner); // eslint-disable-line no-new
+ var rootSuite = new Suite('', new Context());
+ rootSuite.addTest(new Test('passing', function () { }));
+ runner.emit('start');
+ runner.emit('suite', rootSuite);
+ runner.emit('test', rootSuite.tests[0]);
+ rootSuite.tests[0].duration = 0;
+ rootSuite.tests[0].state = 'passed';
+ runner.emit('pass', rootSuite.tests[0]);
+ runner.emit('test end', rootSuite.tests[0]);
+ runner.emit('suite end', rootSuite);
+ runner.emit('end');
+ var testCodeElement = output.getElementsByClassName('test').item(0).getElementsByTagName('pre').item(0);
+ assertDisplayed(testCodeElement, false);
+ restoreOutput();
+ } catch (error) {
+ try {
+ restoreOutput();
+ } catch (ignore) {}
+ throw error;
+ }
+ });
+
+ it('should be displayed when the test is clicked upon', function () {
+ try {
+ var output = stubOutput();
+ var runner = new Runner(1);
+ new HTML(runner); // eslint-disable-line no-new
+ var rootSuite = new Suite('', new Context());
+ rootSuite.addTest(new Test('passing', function () { }));
+ runner.emit('start');
+ runner.emit('suite', rootSuite);
+ runner.emit('test', rootSuite.tests[0]);
+ rootSuite.tests[0].duration = 0;
+ rootSuite.tests[0].state = 'passed';
+ runner.emit('pass', rootSuite.tests[0]);
+ runner.emit('test end', rootSuite.tests[0]);
+ runner.emit('suite end', rootSuite);
+ runner.emit('end');
+ var testCodeElement = output.getElementsByClassName('test').item(0).getElementsByTagName('pre').item(0);
+ click(testCodeElement.parentNode.getElementsByTagName('h2').item(0));
+ assertDisplayed(testCodeElement);
+ restoreOutput();
+ } catch (error) {
+ try {
+ restoreOutput();
+ } catch (ignore) {}
+ throw error;
+ }
+ });
+
+ it('should be hidden again when clicked twice', function () {
+ try {
+ var output = stubOutput();
+ var runner = new Runner(1);
+ new HTML(runner); // eslint-disable-line no-new
+ var rootSuite = new Suite('', new Context());
+ rootSuite.addTest(new Test('passing', function () { }));
+ runner.emit('start');
+ runner.emit('suite', rootSuite);
+ runner.emit('test', rootSuite.tests[0]);
+ rootSuite.tests[0].duration = 0;
+ rootSuite.tests[0].state = 'passed';
+ runner.emit('pass', rootSuite.tests[0]);
+ runner.emit('test end', rootSuite.tests[0]);
+ runner.emit('suite end', rootSuite);
+ runner.emit('end');
+ var testCodeElement = output.getElementsByClassName('test').item(0).getElementsByTagName('pre').item(0);
+ click(testCodeElement.parentNode.getElementsByTagName('h2').item(0));
+ click(testCodeElement.parentNode.getElementsByTagName('h2').item(0));
+ assertDisplayed(testCodeElement, false);
+ restoreOutput();
+ } catch (error) {
+ try {
+ restoreOutput();
+ } catch (ignore) {}
+ throw error;
+ }
+ });
+
+ it('should not affect other tests than the one clicked', function () {
+ try {
+ var output = stubOutput();
+ var runner = new Runner(1);
+ new HTML(runner); // eslint-disable-line no-new
+ var rootSuite = new Suite('', new Context());
+ rootSuite.addTest(new Test('passing', function () { }));
+ rootSuite.addTest(new Test('passing', function () { }));
+ runner.emit('start');
+ runner.emit('suite', rootSuite);
+ runner.emit('test', rootSuite.tests[0]);
+ rootSuite.tests[0].duration = 0;
+ rootSuite.tests[0].state = 'passed';
+ runner.emit('pass', rootSuite.tests[0]);
+ runner.emit('test end', rootSuite.tests[0]);
+ runner.emit('test', rootSuite.tests[1]);
+ rootSuite.tests[1].duration = 0;
+ rootSuite.tests[1].state = 'passed';
+ runner.emit('pass', rootSuite.tests[1]);
+ runner.emit('test end', rootSuite.tests[1]);
+ runner.emit('suite end', rootSuite);
+ runner.emit('end');
+ click(output.getElementsByClassName('test').item(0).getElementsByTagName('pre').item(0).parentNode.getElementsByTagName('h2').item(0));
+ assertDisplayed(output.getElementsByClassName('test').item(1).getElementsByTagName('pre').item(0), false);
+ restoreOutput();
+ } catch (error) {
+ try {
+ restoreOutput();
+ } catch (ignore) {}
+ throw error;
+ }
+ });
+ });
+
+ describe('grep links', function () {
+ it('should be generated for suites', function () {
+ try {
+ var output = stubOutput();
+ var runner = new Runner(1);
+ new HTML(runner); // eslint-disable-line no-new
+ var rootSuite = new Suite('', new Context());
+ var mainSuite = Suite.create(rootSuite, 'suite');
+ mainSuite.addTest(new Test('passing', function () { }));
+ runner.emit('start');
+ runner.emit('suite', rootSuite);
+ runner.emit('suite', mainSuite);
+ runner.emit('test', mainSuite.tests[0]);
+ mainSuite.tests[0].duration = 0;
+ mainSuite.tests[0].state = 'passed';
+ runner.emit('pass', mainSuite.tests[0]);
+ runner.emit('test end', mainSuite.tests[0]);
+ runner.emit('suite end', mainSuite);
+ runner.emit('suite end', rootSuite);
+ runner.emit('end');
+ var href = output.getElementsByClassName('suite').item(0).getElementsByTagName('a').item(0).href.replace(/.*[?]/, '?');
+ expect(href).to.be('?grep=suite');
+ restoreOutput();
+ } catch (error) {
+ try {
+ restoreOutput();
+ } catch (ignore) {}
+ throw error;
+ }
+ });
+
+ it('should be generated for tests', function () {
+ try {
+ var output = stubOutput();
+ var runner = new Runner(1);
+ new HTML(runner); // eslint-disable-line no-new
+ var rootSuite = new Suite('', new Context());
+ rootSuite.addTest(new Test('passing', function () { }));
+ runner.emit('start');
+ runner.emit('suite', rootSuite);
+ runner.emit('test', rootSuite.tests[0]);
+ rootSuite.tests[0].duration = 0;
+ rootSuite.tests[0].state = 'passed';
+ runner.emit('pass', rootSuite.tests[0]);
+ runner.emit('test end', rootSuite.tests[0]);
+ runner.emit('suite end', rootSuite);
+ runner.emit('end');
+ var href = output.getElementsByClassName('test').item(0).getElementsByTagName('a').item(0).href.replace(/.*[?]/, '?');
+ expect(href).to.be('?grep=%20passing');
+ restoreOutput();
+ } catch (error) {
+ try {
+ restoreOutput();
+ } catch (ignore) {}
+ throw error;
+ }
+ });
+ });
+});
+
+function Runner (total) {
+ var callbacks = {};
+ return {
+ total: total,
+ on: function (event, callback) {
+ if (!callbacks[event]) {
+ callbacks[event] = [];
+ }
+ callbacks[event].push(callback);
+ },
+ emit: function (event) {
+ var args = [].slice.call(arguments, 1);
+ (callbacks[event] || []).forEach(function (callback) {
+ callback.apply(null, args);
+ });
+ }
+ };
+}
+
+function click (element) {
+ var event;
+ try {
+ event = new MouseEvent('click');
+ } catch (ignore) {
+ event = document.createEvent('MouseEvent');
+ event.initEvent('click', true, true);
+ }
+ if (element.dispatchEvent) {
+ element.dispatchEvent(event);
+ } else {
+ element.fireEvent(event);
+ }
+}
+
+function assertDisplayed (element, yes) {
+ if (yes === undefined) { yes = true; }
+ var expectDisplay;
+ if (window.getComputedStyle) {
+ expectDisplay = expect(window.getComputedStyle(element).getPropertyValue('display'));
+ } else {
+ expectDisplay = expect(element.currentStyle.display);
+ }
+ if (yes) {
+ expectDisplay.not.to.be('none');
+ } else {
+ expectDisplay.to.be('none');
+ }
+}
diff --git a/test/browser/self-test.html b/test/browser/self-test.html
new file mode 100644
index 0000000000..337e979ddb
--- /dev/null
+++ b/test/browser/self-test.html
@@ -0,0 +1,31 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test/unit/context.spec.js b/test/unit/context.spec.js
index cbcdedb49d..a73fc86210 100644
--- a/test/unit/context.spec.js
+++ b/test/unit/context.spec.js
@@ -68,6 +68,6 @@ describe('Context Siblings', function () {
describe('timeout()', function () {
it('should return the timeout', function () {
- expect(this.timeout()).to.equal(200);
+ expect(this.timeout()).to.equal(!process.browser ? 200 : 500);
});
});