From 03c866c768847ccba888a924d4787dfd64f34ea8 Mon Sep 17 00:00:00 2001 From: Christopher Hiller Date: Tue, 12 Dec 2017 02:38:50 -0800 Subject: [PATCH 1/2] fix bundling; closes #3091 This became too difficult to manage on the command-line. What we're trying to do here is ship a version of the `Buffer` shim which plays well with IE9/IE10. Browserify ships with a version which does NOT play well, meaning we have to force it to use the version we choose (`buffer@4.9.x`). The fix is in two parts: 1. `insertGlobalVars` option replaces usages of global `Buffer` with `require('/path/to/mocha/node_modules/buffer').Buffer` 2. Any *other* module which explicitly requires `buffer` or, yes, `buffer/`, must *also* use `/path/to/mocha/node_modules/buffer` If *both* of these are not in place, Browserify will use its *own* version of the `buffer` shim. --- Makefile | 10 ++------- karma.conf.js | 34 ++++++++++++++-------------- package-lock.json | 57 +++++++++++++++++++++++++++++++++++++++++++++++ package.json | 1 + scripts/build.js | 46 ++++++++++++++++++++++++++++++++++++++ 5 files changed, 123 insertions(+), 25 deletions(-) create mode 100755 scripts/build.js diff --git a/Makefile b/Makefile index 7567fc16a0..232b4be574 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -BROWSERIFY := "node_modules/.bin/browserify" +BROWSERIFY := "scripts/build.js" KARMA := "node_modules/.bin/karma" MOCHA := "bin/mocha" NYC := "node_modules/.bin/nyc" @@ -20,13 +20,7 @@ all: mocha.js mocha.js: $(SRC) browser-entry.js @printf "==> [Browser :: build]\n" mkdir -p ${@D} - $(BROWSERIFY) ./browser-entry \ - --require buffer/:buffer \ - --plugin ./scripts/dedefine \ - --ignore 'fs' \ - --ignore 'glob' \ - --ignore 'path' \ - --ignore 'supports-color' > $@ + $(BROWSERIFY) > $@ clean: @printf "==> [Clean]\n" diff --git a/karma.conf.js b/karma.conf.js index cf07b0b905..25169630c2 100644 --- a/karma.conf.js +++ b/karma.conf.js @@ -4,6 +4,9 @@ var fs = require('fs'); var path = require('path'); var mkdirp = require('mkdirp'); var baseBundleDirpath = path.join(__dirname, '.karma'); +var builder = require('./scripts/build'); +var build = builder.build; +var bundlerOptions = builder.options; var browserPlatformPairs = { 'chrome@latest': 'Windows 8', @@ -32,23 +35,20 @@ module.exports = function (config) { preprocessors: { 'test/**/*.js': ['browserify'] }, - browserify: { - debug: true, - configure: function configure (b) { - b.ignore('glob') - .ignore('fs') - .ignore('path') - .ignore('supports-color') - .require(path.join(__dirname, 'node_modules', 'buffer'), {expose: 'buffer'}) - .on('bundled', function (err, content) { - if (!err && bundleDirpath) { - // write bundle to directory for debugging - fs.writeFileSync(path.join(bundleDirpath, - 'bundle.' + Date.now() + '.js'), content); - } - }); - } - }, + browserify: Object.assign({insertGlobalVars: bundlerOptions.insertGlobalVars}, + { + debug: true, + configure: function configure (b) { + build(b) + .on('bundled', function (err, content) { + if (!err && bundleDirpath) { + // write bundle to directory for debugging + fs.writeFileSync(path.join(bundleDirpath, 'bundle.' + + Date.now() + '.js'), content); + } + }); + } + }), reporters: ['mocha'], colors: true, browsers: ['PhantomJS'], diff --git a/package-lock.json b/package-lock.json index 70161b267e..8ff4b52670 100644 --- a/package-lock.json +++ b/package-lock.json @@ -106,6 +106,15 @@ "integrity": "sha1-opbhf3v658HOT34N5T0pyzIWLfA=", "dev": true }, + "aliasify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/aliasify/-/aliasify-2.1.0.tgz", + "integrity": "sha1-fDCCW5RQueYYW6J1M+r24gZ9S0I=", + "dev": true, + "requires": { + "browserify-transform-tools": "1.7.0" + } + }, "ansi-escapes": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.0.0.tgz", @@ -690,6 +699,16 @@ "parse-asn1": "5.1.0" } }, + "browserify-transform-tools": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/browserify-transform-tools/-/browserify-transform-tools-1.7.0.tgz", + "integrity": "sha1-g+J3Ih9jJZvtLn6yooOpcKUB9MQ=", + "dev": true, + "requires": { + "falafel": "2.1.0", + "through": "2.3.8" + } + }, "browserify-zlib": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.1.4.tgz", @@ -1935,6 +1954,32 @@ "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", "dev": true }, + "falafel": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/falafel/-/falafel-2.1.0.tgz", + "integrity": "sha1-lrsXdh2rqU9G0AFzizzt86Z/4Gw=", + "dev": true, + "requires": { + "acorn": "5.2.1", + "foreach": "2.0.5", + "isarray": "0.0.1", + "object-keys": "1.0.11" + }, + "dependencies": { + "acorn": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.2.1.tgz", + "integrity": "sha512-jG0u7c4Ly+3QkkW18V+NRDN+4bWHdln30NL1ZL2AvFZZmQe/BfopYCtghCKKVBUSetZ4QKcyA0pY6/4Gw8Pv8w==", + "dev": true + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + } + } + }, "fast-deep-equal": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz", @@ -2057,6 +2102,12 @@ "for-in": "1.0.2" } }, + "foreach": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz", + "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=", + "dev": true + }, "forever-agent": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", @@ -6319,6 +6370,12 @@ "integrity": "sha1-8MaapQ78lbhmwYb0AKM3acsvEpE=", "dev": true }, + "object-keys": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.11.tgz", + "integrity": "sha1-xUYBd4rVYPEULODgG8yotW0TQm0=", + "dev": true + }, "object.omit": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", diff --git a/package.json b/package.json index 1fcbd718ed..909bb23577 100644 --- a/package.json +++ b/package.json @@ -321,6 +321,7 @@ "supports-color": "4.4.0" }, "devDependencies": { + "aliasify": "^2.1.0", "assert": "^1.4.1", "browserify": "^14.4.0", "buffer": "^4.9.1", diff --git a/scripts/build.js b/scripts/build.js new file mode 100755 index 0000000000..d09d5d378d --- /dev/null +++ b/scripts/build.js @@ -0,0 +1,46 @@ +#!/usr/bin/env node +'use strict'; + +/** + * Mocha's build script which is sadly too complex to manage from the command + * line + * @type {Browserify} + */ + +const browserify = require('browserify'); +const path = require('path'); +const dedefine = require('./dedefine'); +const aliasify = require('aliasify'); + +const options = { + basedir: path.join(__dirname, '..'), + entries: ['./browser-entry.js'], + insertGlobalVars: { + Buffer (file, basedir) { + const filepath = path.join(path.relative(path.dirname(file), basedir), + 'node_modules', + 'buffer'); + return `require('${filepath}').Buffer`; + } + } +}; + +const build = (b) => b.ignore('fs') + .ignore('glob') + .ignore('path') + .ignore('supports-color') + .transform(aliasify, { + replacements: { + '^buffer/?': () => require.resolve('buffer/index.js') + }, + global: true + }) + .plugin(dedefine); + +exports.build = build; +exports.options = options; + +if (require.main === module) { + build(browserify(options)).bundle() + .pipe(process.stdout); +} From add32814a419ec6faf98878627e019535bb1a984 Mon Sep 17 00:00:00 2001 From: Christopher Hiller Date: Tue, 12 Dec 2017 14:03:53 -0800 Subject: [PATCH 2/2] test support for #3091 - this will assert that using `import` with `mocha.js` does not break - fix: remove missing `Makefile` target; add `test-browser-esm` target - fix: update invalid comments regarding running SauceLabs locally in `karma.conf` - fix: break if attempting to run Karma on AppVeyor - refactor Karma test flags to all use `MOCHA_TEST` env var - a few reformats Signed-off-by: Christopher Hiller --- Makefile | 16 ++-- karma.conf.js | 112 +++++++++++++++---------- test/browser-fixtures/esm.fixture.html | 7 ++ test/browser-specific/esm.spec.js | 5 ++ 4 files changed, 89 insertions(+), 51 deletions(-) create mode 100644 test/browser-fixtures/esm.fixture.html create mode 100644 test/browser-specific/esm.spec.js diff --git a/Makefile b/Makefile index 232b4be574..c2a744ceed 100644 --- a/Makefile +++ b/Makefile @@ -5,10 +5,10 @@ NYC := "node_modules/.bin/nyc" ifdef COVERAGE define test_node - $(NYC) --no-clean --report-dir coverage/reports/$(1) $(MOCHA) +$(NYC) --no-clean --report-dir coverage/reports/$(1) $(MOCHA) endef else - test_node := $(MOCHA) +test_node := $(MOCHA) endif TM_BUNDLE = JavaScript\ mocha.tmbundle @@ -32,7 +32,7 @@ lint: test-node: test-bdd test-tdd test-qunit test-exports test-unit test-integration test-jsapi test-compilers test-requires test-reporters test-only test-global-only -test-browser: clean mocha.js test-browser-unit test-browser-bdd test-browser-qunit test-browser-tdd test-browser-exports +test-browser: clean mocha.js test-browser-unit test-browser-bdd test-browser-qunit test-browser-tdd test-browser-esm test: lint test-node test-browser @@ -42,15 +42,19 @@ test-browser-unit: test-browser-bdd: @printf "==> [Test :: Browser :: BDD]\n" - MOCHA_UI=bdd $(MAKE) test-browser-unit + MOCHA_TEST=bdd $(MAKE) test-browser-unit test-browser-qunit: @printf "==> [Test :: Browser :: QUnit]\n" - MOCHA_UI=qunit $(MAKE) test-browser-unit + MOCHA_TEST=qunit $(MAKE) test-browser-unit test-browser-tdd: @printf "==> [Test :: Browser :: TDD]\n" - MOCHA_UI=tdd $(MAKE) test-browser-unit + MOCHA_TEST=tdd $(MAKE) test-browser-unit + +test-browser-esm: + @printf "==> [Test :: Browser :: ESM]\n" + MOCHA_TEST=esm $(MAKE) test-browser-unit test-jsapi: @printf "==> [Test :: JS API]\n" diff --git a/karma.conf.js b/karma.conf.js index 25169630c2..1dba3a7b83 100644 --- a/karma.conf.js +++ b/karma.conf.js @@ -35,20 +35,24 @@ module.exports = function (config) { preprocessors: { 'test/**/*.js': ['browserify'] }, - browserify: Object.assign({insertGlobalVars: bundlerOptions.insertGlobalVars}, - { - debug: true, - configure: function configure (b) { - build(b) - .on('bundled', function (err, content) { - if (!err && bundleDirpath) { - // write bundle to directory for debugging - fs.writeFileSync(path.join(bundleDirpath, 'bundle.' + - Date.now() + '.js'), content); - } - }); - } - }), + browserify: Object.assign({ + insertGlobalVars: bundlerOptions.insertGlobalVars + }, { + debug: true, + configure: function configure (b) { + build(b) + .on('bundled', function (err, content) { + if (err) { + throw err; + } + if (bundleDirpath) { + // write bundle to directory for debugging + fs.writeFileSync(path.join(bundleDirpath, 'mocha.' + Date.now() + + '.js'), content); + } + }); + } + }), reporters: ['mocha'], colors: true, browsers: ['PhantomJS'], @@ -63,18 +67,8 @@ module.exports = function (config) { } }; - // see https://github.com/saucelabs/karma-sauce-example - - // We define the browser to run on the Saucelabs Infrastructure - // via the environment variables BROWSER and PLATFORM. - // PLATFORM is e.g. "Windows" - // BROWSER is expected to be in the format "@", - // e.g. "MicrosoftEdge@latest" - // See https://wiki.saucelabs.com/display/DOCS/Platform+Configurator#/ - // for available browsers. - - // TO RUN LOCALLY, execute: - // `CI=1 SAUCE_USERNAME= SAUCE_ACCESS_KEY= BROWSER= PLATFORM= make test-browser` + // TO RUN AGAINST SAUCELABS LOCALLY, execute: + // `CI=1 SAUCE_USERNAME= SAUCE_ACCESS_KEY= make test-browser` var env = process.env; var sauceConfig; @@ -86,8 +80,8 @@ module.exports = function (config) { if (env.SAUCE_USERNAME && env.SAUCE_ACCESS_KEY) { // correlate build/tunnel with Travis sauceConfig = { - build: 'TRAVIS #' + env.TRAVIS_BUILD_NUMBER + - ' (' + env.TRAVIS_BUILD_ID + ')', + build: 'TRAVIS #' + env.TRAVIS_BUILD_NUMBER + ' (' + + env.TRAVIS_BUILD_ID + ')', tunnelIdentifier: env.TRAVIS_JOB_NUMBER, startConnect: false }; @@ -96,8 +90,7 @@ module.exports = function (config) { console.error('No SauceLabs credentials present'); } } else if (env.APPVEYOR) { - console.error('AppVeyor detected'); - bundleDirpath = path.join(baseBundleDirpath, process.env.APPVEYOR_BUILD_ID); + throw new Error('no browser tests should run on AppVeyor!'); } else { console.error('Local/unknown environment detected'); bundleDirpath = path.join(baseBundleDirpath, 'local'); @@ -124,21 +117,50 @@ module.exports = function (config) { addSauceTests(cfg); } - // the MOCHA_UI env var will determine if we're running interface-specific - // tests. since you can only load one at a time, each must be run separately. - // each has its own set of acceptance tests and a fixture. - // the "bdd" fixture is used by default. - var ui = env.MOCHA_UI; - if (ui) { - if (cfg.sauceLabs) { - cfg.sauceLabs.testName = 'Interface "' + ui + '" integration tests'; - } - cfg.files = [ - 'test/browser-fixtures/' + ui + '.fixture.js', - 'test/interfaces/' + ui + '.spec.js' - ]; - } else if (cfg.sauceLabs) { - cfg.sauceLabs.testName = 'Unit Tests'; + /* the MOCHA_TEST env var will be set for "special" cases of tests. + * these may require different interfaces or other setup which make + * them unable to be batched w/ the rest. + */ + var MOCHA_TEST = env.MOCHA_TEST; + switch (MOCHA_TEST) { + case 'bdd': + case 'tdd': + case 'qunit': + if (cfg.sauceLabs) { + cfg.sauceLabs.testName = + 'Interface "' + MOCHA_TEST + '" Integration Tests'; + } + cfg.files = [ + 'test/browser-fixtures/' + MOCHA_TEST + '.fixture.js', + 'test/interfaces/' + MOCHA_TEST + '.spec.js' + ]; + break; + + case 'esm': + // for now we will only run against Chrome to test this. + if (cfg.sauceLabs) { + cfg.sauceLabs.testName = 'ESM Integration Tests'; + cfg.browsers = ['chrome@latest']; + var launcher = cfg.customLaunchers['chrome@latest']; + cfg.customLaunchers = { + 'chrome@latest': launcher + }; + } else if (!env.TRAVIS) { + cfg.browsers = ['Chrome']; + } else { + console.error( + 'skipping ESM tests & exiting; no SauceLabs nor local run detected'); + process.exit(0); + } + cfg.files = [ + 'test/browser-fixtures/esm.fixture.html', + 'test/browser-specific/esm.spec.js' + ]; + break; + default: + if (cfg.sauceLabs) { + cfg.sauceLabs.testName = 'Unit Tests'; + } } config.set(cfg); diff --git a/test/browser-fixtures/esm.fixture.html b/test/browser-fixtures/esm.fixture.html new file mode 100644 index 0000000000..caf03c9ee5 --- /dev/null +++ b/test/browser-fixtures/esm.fixture.html @@ -0,0 +1,7 @@ + + diff --git a/test/browser-specific/esm.spec.js b/test/browser-specific/esm.spec.js new file mode 100644 index 0000000000..d7460f8090 --- /dev/null +++ b/test/browser-specific/esm.spec.js @@ -0,0 +1,5 @@ +'use strict'; + +it('should register a global if it did not fail', function () { + expect(window.MOCHA_IS_OK).to.be.ok(); +});