webextension-polyfill/test/setup.js

139 lines
4.7 KiB
JavaScript

"use strict";
const fs = require("fs");
const {createInstrumenter} = require("istanbul-lib-instrument");
const {jsdom, createVirtualConsole} = require("jsdom");
var virtualConsole = createVirtualConsole();
// Optionally print console logs from the jsdom window.
if (process.env.ENABLE_JSDOM_CONSOLE == "y") {
virtualConsole.sendTo(console);
}
// Path to the browser-polyfill script, relative to the current work dir
// where mocha is executed.
let BROWSER_POLYFILL_PATH = "./dist/browser-polyfill.js";
if (process.env.TEST_MINIFIED_POLYFILL) {
BROWSER_POLYFILL_PATH = "./dist/browser-polyfill.min.js";
} else if (process.env.TEST_BUNDLED_POLYFILL) {
BROWSER_POLYFILL_PATH = process.env.TEST_BUNDLED_POLYFILL;
}
function getInputSourceMap() {
// Enabled only on CI until we have fixed the mapping to the source file
// (by making sure that babel generates a sourcemap that does also take into
// account the api metadata being interpolated into the src script).
//
// TODO(https://github.com/mozilla/webextension-polyfill/issues/348):
// disabling the sourcemapped code coverage will not be necessary anymore
// once we fix the generated sourcemap to correctly map to src/browser-polyfill.js
if (process.env.COVERAGE_WITH_SOURCEMAP != "1") {
return undefined;
}
if (process.env.TEST_BUNDLED_POLYFILL) {
// Running the unit tests on the bundled files are meant to be used as smoke tests,
// we don't need to collect code coverage for it.
throw new Error("Unexpected code coverage enabled while testing bundled modules");
}
let sourceMapPath = process.env.TEST_MINIFIED_POLYFILL
? "./dist/browser-polyfill.js.min.map"
: "./dist/browser-polyfill.js.map";
let sourceMap = JSON.parse(fs.readFileSync(sourceMapPath, {encoding: "utf-8"}));
sourceMap.sources = ["../src/browser-polyfill.js"];
return sourceMap;
}
// Create the jsdom window used to run the tests
const testDOMWindow = jsdom("", {virtualConsole}).defaultView;
// Copy the code coverage of the browser-polyfill script from the jsdom window
// to the nodejs global, where nyc expects to find the code coverage data to
// render in the reports.
after(() => {
if (testDOMWindow && process.env.COVERAGE == "y") {
global.__coverage__ = testDOMWindow.__coverage__;
}
});
function setupTestDOMWindow(chromeObject, browserObject = undefined) {
return new Promise((resolve, reject) => {
const window = testDOMWindow;
// Ensure that "chrome.runtime.id" is set, because the polyfill is only
// loaded in extension environments.
if (chromeObject) {
if (!chromeObject.runtime) {
chromeObject.runtime = {};
}
if (!chromeObject.runtime.id) {
chromeObject.runtime.id = "some-test-id-from-test-setup";
}
}
// Inject the fake chrome object used as a fixture for the particular
// browser-polyfill test scenario.
window.chrome = chromeObject;
// Set (or reset) the browser property.
if (browserObject) {
// Make the fake browser object a `window.Object` instance, so that
// it passes the `Object.getPrototypeOf(browser) !== Object.prototype`
// check, otherwise it is going to be overridden by the polyfill (See #153).
window.browser = Object.assign(window.Object(), browserObject);
} else {
delete window.browser;
}
const scriptEl = window.document.createElement("script");
if (process.env.COVERAGE == "y") {
// If the code coverage is enabled, instrument the code on the fly
// before executing it in the jsdom window.
const inst = createInstrumenter({
compact: false, esModules: false, produceSourceMap: false,
});
const scriptContent = fs.readFileSync(BROWSER_POLYFILL_PATH, "utf-8");
scriptEl.textContent = inst.instrumentSync(
scriptContent,
BROWSER_POLYFILL_PATH,
getInputSourceMap()
);
} else {
scriptEl.src = BROWSER_POLYFILL_PATH;
}
let onLoad;
let onLoadError;
let onError;
let cleanLoadListeners = () => {
scriptEl.removeEventListener("load", onLoad);
scriptEl.removeEventListener("error", onLoadError);
window.removeEventListener("error", onError);
};
onLoad = () => { cleanLoadListeners(); resolve(window); };
onLoadError = () => {
cleanLoadListeners();
reject(new Error(`Error loading script: ${BROWSER_POLYFILL_PATH}`));
};
onError = (err) => { cleanLoadListeners(); reject(err); };
// Listen to any uncaught errors.
window.addEventListener("error", onError);
scriptEl.addEventListener("error", onLoadError);
scriptEl.addEventListener("load", onLoad);
window.document.body.appendChild(scriptEl);
});
}
module.exports = {
BROWSER_POLYFILL_PATH,
setupTestDOMWindow,
};