diff --git a/.eslintrc b/.eslintrc index 13ed046..c786328 100644 --- a/.eslintrc +++ b/.eslintrc @@ -10,6 +10,7 @@ "env": { "browser": true, "es6": true, + "node": true, "webextensions": true, }, diff --git a/.travis.yml b/.travis.yml index dd3550f..33e9ce5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,11 +10,11 @@ script: - echo "RE-RUN tests on the minified file" && npm run test-minified - echo "RE-RUN tests on the webpack and browserify bundled files" && npm install -g browserify webpack webpack-cli && - ./test/run-module-bundlers-smoketests.sh + node ./scripts/run-module-bundlers-smoketests.js - export DISPLAY=:99.0 - sh -e /etc/init.d/xvfb start - echo "RUN integration tests on real browsers" && - TRAVIS_CI=true ./test/run-browsers-smoketests.sh + TRAVIS_CI=true node ./scripts/run-browsers-smoketests.js ## See https://docs.travis-ci.com/user/chrome sudo: required diff --git a/Gruntfile.js b/Gruntfile.js index 7b8f808..c21e55d 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -2,13 +2,11 @@ /* vim: set sts=2 sw=2 et tw=80: */ "use strict"; -/* eslint-env commonjs */ - const LICENSE = `/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */`; -const MINIFIED_FILE_FOOTER = `\n\n// <%= pkg.name %> v.<%= pkg.version %> (<%= pkg.homepage %>)\n\n${LICENSE}`; +const MINIFIED_FILE_FOOTER = `\n// <%= pkg.name %> v.<%= pkg.version %> (<%= pkg.homepage %>)\n\n${LICENSE}\n`; module.exports = function(grunt) { grunt.initConfig({ @@ -22,7 +20,7 @@ module.exports = function(grunt) { eslint: { src: ["src/browser-polyfill.js", "Gruntfile.js"], - test: ["test/**/*.js"], + test: ["test/**/*.js", "scripts/**/*.js"], }, replace: { diff --git a/package.json b/package.json index 8eed18c..f436aa5 100644 --- a/package.json +++ b/package.json @@ -26,9 +26,10 @@ "browserify": "^16.2.2", "chai": "^3.5.0", "chromedriver": "^2.38.3", + "cross-env": "^5.2.0", "eslint": "^3.9.1", "finalhandler": "^1.1.0", - "geckodriver": "^1.11.0", + "geckodriver": "^1.11.2", "global-replaceify": "^1.0.0", "grunt": "^1.0.1", "grunt-babel": "^6.0.0", @@ -62,8 +63,10 @@ "prepublish": "npm run build && npm run test", "publish-coverage": "grunt coveralls", "test": "mocha", - "test-coverage": "COVERAGE=y nyc mocha", - "test-minified": "TEST_MINIFIED_POLYFILL=1 mocha", - "test-integration": "tape test/integration/test-*" + "test-coverage": "cross-env COVERAGE=y nyc mocha", + "test-minified": "cross-env TEST_MINIFIED_POLYFILL=1 mocha", + "test-integration": "tape test/integration/test-*", + "test-integration:chrome": "cross-env TEST_BROWSER_TYPE=chrome npm run test-integration | tap-nirvana", + "test-integration:firefox": "cross-env TEST_BROWSER_TYPE=firefox npm run test-integration | tap-nirvana" } } diff --git a/scripts/run-browsers-smoketests.js b/scripts/run-browsers-smoketests.js new file mode 100755 index 0000000..277cd7f --- /dev/null +++ b/scripts/run-browsers-smoketests.js @@ -0,0 +1,28 @@ +#!/usr/bin/env node +"use strict"; +const shell = require("shelljs"); + +/** + * This is to make sure that even if the tests fail on Chrome, + * the tests still run on Firefox, so that it can be seen whether + * Firefox broke too or is unaffected. + */ +let result = 0; + +console.log(` +Test webextension-polyfill on real browsers +===========================================`); + +// Enable headless mode (currently only used when running on Firefox +// because Chrome doesn't currently support the extensions in headless mode) +process.env.HEADLESS = 1; + +console.log("\nRunning smoketests on Chrome"); +process.env.TEST_BROWSER_TYPE = "chrome"; +result = shell.exec("npm run test-integration:chrome").code || result; + +console.log("\nRunning smoketests on Firefox"); +process.env.TEST_BROWSER_TYPE = "firefox"; +result = shell.exec("npm run test-integration:firefox").code || result; + +process.exit(result); diff --git a/scripts/run-module-bundlers-smoketests.js b/scripts/run-module-bundlers-smoketests.js new file mode 100755 index 0000000..9a68824 --- /dev/null +++ b/scripts/run-module-bundlers-smoketests.js @@ -0,0 +1,22 @@ +#!/usr/bin/env node +const shell = require("shelljs"); + +let result = 0; + +console.log(` +Test webextension-polyfill bundled with webpack +===============================================`); + +process.env.TEST_BUNDLED_POLYFILL = "/tmp/webpack-bundle.js"; +result = shell.exec(`webpack --mode production --entry ./test/fixtures/bundle-entrypoint.js --output ${process.env.TEST_BUNDLED_POLYFILL}`).code || + shell.exec("npm run test").code || result; + +console.log(` +Test webextension-polyfill bundled with browserify +==================================================`); + +process.env.TEST_BUNDLED_POLYFILL = "/tmp/browserify-bundle.js"; +result = shell.exec(`browserify test/fixtures/bundle-entrypoint.js > ${process.env.TEST_BUNDLED_POLYFILL}`).code || + shell.exec("npm run test").code || result; + +process.exit(result); diff --git a/src/.eslintrc b/src/.eslintrc new file mode 100644 index 0000000..e76e457 --- /dev/null +++ b/src/.eslintrc @@ -0,0 +1,9 @@ +{ + "env": { + "node": false, + }, + "globals": { + // Allow the `module` global, but not the `require(…)` function + "module": false, + }, +} \ No newline at end of file diff --git a/src/browser-polyfill.js b/src/browser-polyfill.js index f4b6dec..fbbcc49 100644 --- a/src/browser-polyfill.js +++ b/src/browser-polyfill.js @@ -509,7 +509,7 @@ if (typeof browser === "undefined" || Object.getPrototypeOf(browser) !== Object. // The build process adds a UMD wrapper around this file, which makes the // `module` variable available. - module.exports = wrapAPIs(chrome); // eslint-disable-line no-undef + module.exports = wrapAPIs(chrome); } else { - module.exports = browser; // eslint-disable-line no-undef + module.exports = browser; } diff --git a/test/.eslintrc b/test/.eslintrc index 70b013e..688def0 100644 --- a/test/.eslintrc +++ b/test/.eslintrc @@ -1,11 +1,7 @@ { "env": { "mocha": true, - "node": true, - "browser": true, - "webextensions": true }, - "globals": {}, "rules": { "max-nested-callbacks": ["warn", 6] } diff --git a/test/fixtures/index.html b/test/fixtures/index.html index 4066e38..896d985 100644 --- a/test/fixtures/index.html +++ b/test/fixtures/index.html @@ -1,4 +1,4 @@ - + Browser Polyfill Test Page diff --git a/test/integration/setup.js b/test/integration/setup.js index 8d97cd1..9c24051 100644 --- a/test/integration/setup.js +++ b/test/integration/setup.js @@ -16,7 +16,7 @@ const {cp} = require("shelljs"); const TEST_TIMEOUT = 5000; const launchBrowser = async (launchOptions) => { - const browser = launchOptions.browser || process.env.TEST_BROWSER_TYPE; + const browser = launchOptions.browser; const extensionPath = launchOptions.extensionPath; let driver; @@ -98,12 +98,12 @@ const createHTTPServer = async (path) => { }); }; -async function runExtensionTest(t, server, driver, extensionDirName) { +async function runExtensionTest(t, server, driver, extensionDirName, browser) { try { const url = `http://localhost:${server.address().port}`; const userAgent = await driver.executeScript(() => window.navigator.userAgent); - t.pass(`Connected to browser: ${userAgent}"`); + t.pass(`Connected to ${browser} browser: ${userAgent}"`); await driver.get(url); @@ -138,16 +138,26 @@ const bundleTapeStandalone = async (destDir) => { const stream = b.bundle(); const onceStreamEnd = awaitStreamEnd(stream); - stream.pipe(fs.createWriteStream(bundleFileName)); + const destFileStream = fs.createWriteStream(bundleFileName); + const onceWritten = new Promise(resolve => { + destFileStream.on("close", resolve); + }); + stream.pipe(destFileStream); - await onceStreamEnd; + await Promise.all([onceStreamEnd, onceWritten]); }; test.onFailure(() => { process.exit(1); }); -const defineExtensionTests = ({description, extensions}) => { +/** + * @param {object} parameters + * @param {string} parameters.description + * @param {string[]} parameters.extensions + * @param {boolean|string|string[]} [parameters.skip] + */ +const defineExtensionTests = ({description, extensions, skip}) => { for (const extensionDirName of extensions) { test(`${description} (test extension: ${extensionDirName})`, async (tt) => { let timeout; @@ -155,6 +165,19 @@ const defineExtensionTests = ({description, extensions}) => { let server; let tempDir; + const browser = process.env.TEST_BROWSER_TYPE; + + if (skip) { + if (skip === true) { + tt.skip("Test extension skipped"); + return; + } else if (skip instanceof Array ? skip.includes(browser) : skip === browser) { + tt.skip("Test extension skipped on: " + browser); + return; + } + console.log(`Skip condition ignored: '${skip}' != '${browser}'`); + } + try { const srcExtensionPath = path.resolve( path.join(__dirname, "..", "fixtures", extensionDirName)); @@ -169,9 +192,9 @@ const defineExtensionTests = ({description, extensions}) => { await bundleTapeStandalone(extensionPath); server = await createHTTPServer(path.join(__dirname, "..", "fixtures")); - driver = await launchBrowser({extensionPath}); + driver = await launchBrowser({extensionPath, browser}); await Promise.race([ - runExtensionTest(tt, server, driver, extensionDirName), + runExtensionTest(tt, server, driver, extensionDirName, browser), new Promise((resolve, reject) => { timeout = setTimeout(() => reject(new Error(`test timeout after ${TEST_TIMEOUT}`)), TEST_TIMEOUT); }), diff --git a/test/run-browsers-smoketests.sh b/test/run-browsers-smoketests.sh deleted file mode 100755 index 8e3e738..0000000 --- a/test/run-browsers-smoketests.sh +++ /dev/null @@ -1,20 +0,0 @@ -#!/bin/bash -set -eo pipefail - -echo "" -echo "Test webextension-polyfill on real browsers" -echo "===========================================" - -export PATH=$PATH:./node_modules/.bin/ - -## HEADLESS=1 Enable the headless mode (currently used only on Firefox -## because Chrome doesn't currently support the extensions in headless mode) -export HEADLESS=1 - -echo "" -echo "Run smoketests on Chrome" -TEST_BROWSER_TYPE=chrome npm run test-integration | tap-nirvana - -echo "" -echo "Run smoketests on Firefox" -TEST_BROWSER_TYPE=firefox npm run test-integration | tap-nirvana diff --git a/test/run-module-bundlers-smoketests.sh b/test/run-module-bundlers-smoketests.sh deleted file mode 100755 index 0a0c6d0..0000000 --- a/test/run-module-bundlers-smoketests.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/bash -set -eo pipefail - -echo "" -echo "Test webextension-polyfill bundled with webpack" -echo "===============================================" - -webpack --mode production --entry ./test/fixtures/bundle-entrypoint.js --output /tmp/webpack-bundle.js -TEST_BUNDLED_POLYFILL=/tmp/webpack-bundle.js npm run test - -echo "" -echo "Test webextension-polyfill bundled with browserify" -echo "==================================================" - -browserify test/fixtures/bundle-entrypoint.js > /tmp/browserify-bundle.js -TEST_BUNDLED_POLYFILL=/tmp/browserify-bundle.js npm run test