Skip to content

Commit

Permalink
Merge branch 'master' into test/schema
Browse files Browse the repository at this point in the history
  • Loading branch information
ExE-Boss committed May 29, 2019
2 parents 2958ccd + 10bc37b commit 791c010
Show file tree
Hide file tree
Showing 24 changed files with 281 additions and 75 deletions.
2 changes: 2 additions & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
coverage/
dist/
3 changes: 1 addition & 2 deletions .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,8 @@
},

"env": {
"browser": true,
"es6": true,
"webextensions": true,
"node": true,
},

"globals": {
Expand Down
4 changes: 2 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
10 changes: 10 additions & 0 deletions CODE_OF_CONDUCT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Community Participation Guidelines

This repository is governed by Mozilla's code of conduct and etiquette guidelines.
For more details, please read the
[Mozilla Community Participation Guidelines](https://www.mozilla.org/about/governance/policies/participation/).

## How to Report

For more information on how to report violations of the Community Participation Guidelines,
please read our '[How to Report](https://www.mozilla.org/about/governance/policies/participation/reporting/)' page.
6 changes: 2 additions & 4 deletions Gruntfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -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({
Expand All @@ -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: {
Expand Down
23 changes: 19 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ Supported Browsers
| Chrome | *Officially Supported* (with automated tests) |
| Firefox | *Officially Supported as a NO-OP* (with automated tests for comparison with the behaviors on Chrome) |
| Opera | *Unofficially Supported* as a Chrome-compatible target (but not explicitly tested in automation) |
| Edge | *Not supported* (may become unofficially supported once [#114][PR-114] lands) |
| Edge | *Not supported* (See [MSEdge Support](#msedge-support) section) |

The polyfill is being tested explictly (with automated tests that run on every pull request) on **officially supported**
browsers (that are currently the last stable versions of Chrome and Firefox).
Expand Down Expand Up @@ -60,7 +60,7 @@ For extensions that do not include a package.json file and/or prefer to download

- https://unpkg.com/webextension-polyfill/dist/

and linked to the github releases:
and linked to the Github releases:

- https://github.com/mozilla/webextension-polyfill/releases

Expand Down Expand Up @@ -284,8 +284,11 @@ This library takes its knowledge of the APIs to wrap and their signatures from a
If an API method is not yet included in this "API metadata" file, it will not be recognized.
Promises are not supported for unrecognized APIs, and callbacks have to be used for them.

File an issue in this repository for API methods that supports a callback on Chrome and
are currently missing from the "API metadata" file.
Chrome-only APIs have no promise version, because extensions that use such APIs
would not be compatible with Firefox.

File an issue in this repository for API methods that support callbacks in Chrome *and*
Firefox but are currently missing from the "API metadata" file.

### Issues that happen only when running on Firefox

Expand All @@ -305,6 +308,18 @@ On Firefox `browser.tabs.executeScript` returns a promise which resolves to the
On Chrome, the `browser.tabs.executeScript` API method as polyfilled by this library also returns a promise which resolves to the result of the content script code, but only immediate values are supported.
If the content script code result is a Promise, the promise returned by `browser.tabs.executeScript` will be resolved to `undefined`.

### MSEdge support

[With the Microsoft announcement related to the MSEdge future](https://github.com/MicrosoftEdge/MSEdge/blob/master/README.md) there aren't many compelling reasons to officially include in this polyfill any workarounds specific to the current MSEdge versions (and then maintaining them over the time), and so MSEdge is currently **unsupported**.

Once the first Chrome-based MSEdge version is going to be released, we will be able to verify if any actual changes to this polyfill are needed to officially support the Chrome-based MSEdge versions.

In the meantime, for extension developers that still have to work on MSEdge extensions before it is switched to the next Chromium-based version, the MSEdge `--ms-preload` manifest key and the [Microsoft Edge Extension Toolkit](https://docs.microsoft.com/en-us/microsoft-edge/extensions/guides/porting-chrome-extensions)'s Chrome API bridge can be used to be able to load the webextension-polyfill without any MSEdge specific changes.

The following Github repository provides some additional detail about this strategy and a minimal test extension that shows how to put it together:

- https://github.com/rpl/example-msedge-extension-with-webextension-polyfill

## Contributing to this project

Read the [contributing section](CONTRIBUTING.md) for additional information about how to build the library from this repository and how to contribute and test changes.
Expand Down
3 changes: 2 additions & 1 deletion api-metadata.json
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,8 @@
"inspectedWindow": {
"eval": {
"minArgs": 1,
"maxArgs": 2
"maxArgs": 2,
"singleCallbackArg": false
}
},
"panels": {
Expand Down
13 changes: 8 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "webextension-polyfill",
"version": "0.3.1",
"version": "0.4.0",
"description": "A lightweight polyfill library for Promise-based WebExtension APIs in Chrome.",
"main": "dist/browser-polyfill.js",
"files": [
Expand Down Expand Up @@ -28,9 +28,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",
Expand Down Expand Up @@ -64,8 +65,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"
}
}
28 changes: 28 additions & 0 deletions scripts/run-browsers-smoketests.js
Original file line number Diff line number Diff line change
@@ -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);
22 changes: 22 additions & 0 deletions scripts/run-module-bundlers-smoketests.js
Original file line number Diff line number Diff line change
@@ -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);
11 changes: 11 additions & 0 deletions src/.eslintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"env": {
"browser": true,
"node": false,
"webextensions": true,
},
"globals": {
// Allow the `module` global, but not the `require(…)` function
"module": false,
},
}
7 changes: 4 additions & 3 deletions src/browser-polyfill.js
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,8 @@ if (typeof browser === "undefined" || Object.getPrototypeOf(browser) !== Object.
return (...callbackArgs) => {
if (extensionAPIs.runtime.lastError) {
promise.reject(extensionAPIs.runtime.lastError);
} else if (metadata.singleCallbackArg || callbackArgs.length <= 1) {
} else if (metadata.singleCallbackArg ||
(callbackArgs.length <= 1 && metadata.singleCallbackArg !== false)) {
promise.resolve(callbackArgs[0]);
} else {
promise.resolve(callbackArgs);
Expand Down Expand Up @@ -509,7 +510,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;
}
6 changes: 2 additions & 4 deletions test/.eslintrc
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
{
"env": {
"mocha": true,
"node": true,
"browser": true,
"webextensions": true
"mocha": true,
"webextensions": true,
},
"globals": {},
"rules": {
"max-nested-callbacks": ["warn", 6]
}
Expand Down
12 changes: 12 additions & 0 deletions test/fixtures/devtools-extension/background.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
let onDevToolsPageLoaded = new Promise(resolve => {
const listener = () => {
browser.runtime.onConnect.removeListener(listener);
resolve();
};
browser.runtime.onConnect.addListener(listener);
});

browser.runtime.onMessage.addListener(async msg => {
await onDevToolsPageLoaded;
return browser.runtime.sendMessage(msg);
});
34 changes: 34 additions & 0 deletions test/fixtures/devtools-extension/content.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
test("devtools.inspectedWindow.eval resolved with an error result", {
timeout: 5000,
}, async (t) => {
const {evalResult} = await browser.runtime.sendMessage({
apiMethod: "devtools.inspectedWindow.eval",
params: ["throw new Error('fake error');"],
});

t.ok(Array.isArray(evalResult), "devtools.inspectedWindow.eval should resolve to an array");

t.equal(evalResult[0], navigator.userAgent.includes("Firefox/") ? undefined : null,
"the first element should be null (on chrome) or undefined (on firefox)");

t.ok(evalResult[1].isException, "the second element should represent an exception");
t.ok(evalResult[1].value && evalResult[1].value.includes("fake error"),
"the second element value property should include the expected error message");
});

test("devtools.inspectedWindow.eval resolved without an error result", {
timeout: 5000,
}, async (t) => {
const {evalResult} = await browser.runtime.sendMessage({
apiMethod: "devtools.inspectedWindow.eval",
params: ["[document.documentElement.localName]"],
});

t.ok(Array.isArray(evalResult), "devtools.inspectedWindow.eval should resolve to an array");

if (navigator.userAgent.includes("Firefox/")) {
t.deepEqual(evalResult, [["html"], undefined], "got the expected values in the array");
} else {
t.deepEqual(evalResult, [["html"]], "got the expected values in the array");
}
});
7 changes: 7 additions & 0 deletions test/fixtures/devtools-extension/devtools_page.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<!DOCTYPE html>
<html>
<head>
<script src="browser-polyfill.js"></script>
<script src="devtools_page.js"></script>
</head>
</html>
14 changes: 14 additions & 0 deletions test/fixtures/devtools-extension/devtools_page.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
console.log("devtools page loaded");

browser.runtime.onMessage.addListener(async msg => {
switch (msg.apiMethod) {
case "devtools.inspectedWindow.eval": {
const evalResult = await browser.devtools.inspectedWindow.eval(...msg.params);
return {evalResult};
}
}

throw new Error(`devtools_page received an unxpected message: ${msg}`);
});

browser.runtime.connect({name: "devtools_page"});
27 changes: 27 additions & 0 deletions test/fixtures/devtools-extension/manifest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
"manifest_version": 2,
"name": "test-extension-devtools-api",
"version": "0.1",
"description": "test-extension-devtools-api",
"content_scripts": [
{
"matches": [
"http://localhost/*"
],
"js": [
"browser-polyfill.js",
"tape.js",
"content.js"
],
"run_at": "document_end"
}
],
"permissions": [],
"background": {
"scripts": [
"browser-polyfill.js",
"background.js"
]
},
"devtools_page": "devtools_page.html"
}
2 changes: 1 addition & 1 deletion test/fixtures/index.html
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<!DOCTYPE>
<!DOCTYPE html>
<html>
<head>
<title>Browser Polyfill Test Page</title>
Expand Down
27 changes: 24 additions & 3 deletions test/fixtures/tape-standalone.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,30 @@ if (navigator.userAgent.includes("Chrome/")) {
}

// Export as a global a wrapped test function which enforces a timeout by default.
window.test = (desc, fn) => {
tape(`${desc} (${browser})`, async (t) => {
t.timeoutAfter(DEFAULT_TIMEOUT);
/**
* @param {string} desc
* The test description
* @param {object} [options]
* The test options, can be omitted.
* @param {number} [options.timeout=DEFAULT_TIMEOUT]
* The time after which the test fails automatically, unless it has already passed.
* @param {boolean} [options.skip]
* Whether the test case should be skipped.
* @param {function(tape.Test):(void|Promise<void>)} fn
* The test case function, takes the test object as a callback.
*/
window.test = (desc, options, fn) => {
if (typeof options === "function") {
// Allow swapping options with fn
[fn, options] = [options, fn];
}

options = {
timeout: DEFAULT_TIMEOUT,
...options,
};

tape(`${desc} (${browser})`, options, async (t) => {
await fn(t);
});
};
Expand Down
Loading

0 comments on commit 791c010

Please sign in to comment.