code cleanup, better eslint rules and related test configuration
This commit is contained in:
parent
5580148632
commit
ae18079a67
35 changed files with 195 additions and 151 deletions
5
.eslintignore
Normal file
5
.eslintignore
Normal file
|
@ -0,0 +1,5 @@
|
|||
node_modules/
|
||||
add-on/lib/third_party/
|
||||
add-on/lib/standards.js
|
||||
add-on/config/js/third_party/
|
||||
test.config.js
|
|
@ -7,12 +7,22 @@
|
|||
"mocha": true
|
||||
},
|
||||
"extends": [
|
||||
"eslint:recommended"
|
||||
"eslint:recommended"
|
||||
],
|
||||
"rules": {
|
||||
"no-console": "off",
|
||||
"no-trailing-spaces": "error",
|
||||
"no-unused-vars": ["error", {"varsIgnorePattern": "ignore"}],
|
||||
"semi": ["error", "always"]
|
||||
"semi": ["error", "always"],
|
||||
"indent": ["error", 4],
|
||||
"eol-last": "error",
|
||||
"quotes": ["error", "double"],
|
||||
"comma-dangle": ["error", "only-multiline"],
|
||||
"function-paren-newline": ["error"],
|
||||
"max-len": ["error", {"ignoreStrings": true, "code": 100}],
|
||||
"require-jsdoc": "error",
|
||||
"valid-jsdoc": "error",
|
||||
"prefer-const": "error",
|
||||
"no-template-curly-in-string": "error",
|
||||
"no-unused-expressions": "error"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -81,7 +81,8 @@
|
|||
|
||||
if (label === "rulesForDomains") {
|
||||
|
||||
const matchHostNameBound = domainMatcherLib.matchHostName.bind(undefined, Object.keys(domainRules));
|
||||
const matchHostName = domainMatcherLib.matchHostName;
|
||||
const matchHostNameBound = matchHostName.bind(undefined, Object.keys(domainRules));
|
||||
const rulesForDomains = data.map(matchHostNameBound);
|
||||
const domainToRuleMapping = {};
|
||||
|
||||
|
@ -113,7 +114,7 @@
|
|||
const newHeaders = details.requestHeaders.map(function (header) {
|
||||
|
||||
if (header.name.indexOf("Cookie") === -1) {
|
||||
header;
|
||||
return header;
|
||||
}
|
||||
|
||||
const cookieValue = header.value;
|
||||
|
|
|
@ -40,7 +40,7 @@
|
|||
<script src="../lib/defaults.js"></script>
|
||||
<script src="../lib/standards.js"></script>
|
||||
<script src="../lib/storage.js"></script>
|
||||
<script src="js/lib/vue.js"></script>
|
||||
<script src="js/third_party/vue.js"></script>
|
||||
<script src="js/state.js"></script>
|
||||
<script src="js/components/domain-rules.vue.js"></script>
|
||||
<script src="js/components/web-api-standards.vue.js"></script>
|
||||
|
|
|
@ -27,10 +27,15 @@
|
|||
|
||||
<div class="form-group" v-bind:class="{ 'has-error': errorMessage }">
|
||||
<label for="newDomainName">Add New Domain Rule</label>
|
||||
<input class="form-control" v-model.trim="newDomain" placeholder="*.example.org">
|
||||
<input
|
||||
class="form-control"
|
||||
v-model.trim="newDomain"
|
||||
placeholder="*.example.org">
|
||||
</div>
|
||||
|
||||
<button type="submit" class="btn btn-default btn-block" @click="newDomainSubmitted">Add Rule</button>
|
||||
<button type="submit"
|
||||
class="btn btn-default btn-block"
|
||||
@click="newDomainSubmitted">Add Rule</button>
|
||||
</div>
|
||||
`,
|
||||
data: function () {
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
const standardsCookieName = constants.cookieName;
|
||||
|
||||
const doc = window.document;
|
||||
const script = doc.createElement('script');
|
||||
const script = doc.createElement("script");
|
||||
const rootElm = doc.head || doc.documentElement;
|
||||
|
||||
// First see if we can read the standards to block out of the cookie
|
||||
|
|
|
@ -15,12 +15,12 @@
|
|||
* The `standardsToBlock` array must be a subset of all the standards
|
||||
* documented in data/standards.
|
||||
*
|
||||
* @param array standardsToBlock
|
||||
* @param {array} standardsToBlock
|
||||
* An array of strings, each a standard that should be blocked.
|
||||
* @param bool shouldLog
|
||||
* @param {boolean} shouldLog
|
||||
* Whether logging should be enabled.
|
||||
*
|
||||
* @return string
|
||||
* @return {string}
|
||||
* A cookie safe string encoding the above values.
|
||||
*/
|
||||
const toCookieValue = function (standardsToBlock, shouldLog) {
|
||||
|
@ -45,10 +45,10 @@
|
|||
* standard names, and two, a boolean flag of whether the logging option
|
||||
* is enabled.
|
||||
*
|
||||
* @param string data
|
||||
* @param {string} data
|
||||
* A string created from `toCookieValue`
|
||||
*
|
||||
* @return [array, bool]
|
||||
* @return {[array, bool]}
|
||||
* An array of strings of standard names (representing standards to
|
||||
* block), and a boolean describing whether to log blocking
|
||||
* behavior.
|
||||
|
|
|
@ -17,7 +17,7 @@ window.WEB_API_MANAGER.defaults.lite = [
|
|||
"WebRTC 1.0: Real-time Communication Between Browser",
|
||||
"WebGL Specification",
|
||||
"Geometry Interfaces Module Level 1",
|
||||
"Web Notifications",
|
||||
"Web Notifications"
|
||||
];
|
||||
|
||||
window.WEB_API_MANAGER.defaults.conservative = [
|
||||
|
@ -35,7 +35,7 @@ window.WEB_API_MANAGER.defaults.conservative = [
|
|||
"UI Events Specification",
|
||||
"WebGL Specification",
|
||||
"Web Audio API",
|
||||
"Scalable Vector Graphics (SVG) 1.1 (Second Edition)",
|
||||
"Scalable Vector Graphics (SVG) 1.1 (Second Edition)"
|
||||
];
|
||||
|
||||
window.WEB_API_MANAGER.defaults.aggressive = window.WEB_API_MANAGER.defaults.conservative.concat([
|
||||
|
|
|
@ -6,11 +6,11 @@
|
|||
const matchOperatorsRe = /[|\\{}()[\]^$+*?.]/g;
|
||||
|
||||
const escapeStringRegexp = function (aString) {
|
||||
if (typeof aString !== 'string') {
|
||||
throw new TypeError('Expected a string');
|
||||
if (typeof aString !== "string") {
|
||||
throw new TypeError("Expected a string");
|
||||
}
|
||||
|
||||
return aString.replace(matchOperatorsRe, '\\$&');
|
||||
return aString.replace(matchOperatorsRe, "\\$&");
|
||||
};
|
||||
|
||||
// From https://www.npmjs.com/package/matcher
|
||||
|
@ -24,19 +24,19 @@
|
|||
return reCache.get(cacheKey);
|
||||
}
|
||||
|
||||
const negated = pattern[0] === '!';
|
||||
const negated = pattern[0] === "!";
|
||||
|
||||
if (negated) {
|
||||
pattern = pattern.slice(1);
|
||||
}
|
||||
|
||||
pattern = escapeStringRegexp(pattern).replace(/\\\*/g, '.*');
|
||||
pattern = escapeStringRegexp(pattern).replace(/\\\*/g, ".*");
|
||||
|
||||
if (negated && shouldNegate) {
|
||||
pattern = `(?!${pattern})`;
|
||||
}
|
||||
|
||||
const re = new RegExp(`^${pattern}$`, 'i');
|
||||
const re = new RegExp(`^${pattern}$`, "i");
|
||||
re.negated = negated;
|
||||
reCache.set(cacheKey, re);
|
||||
|
||||
|
@ -61,10 +61,23 @@
|
|||
return prev;
|
||||
};
|
||||
|
||||
const matchHostName = function (domainRegExes, hostName) {
|
||||
// of the URL being requested.
|
||||
/**
|
||||
* Returns the match patern that matches given host name.
|
||||
*
|
||||
* @see https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Match_patterns
|
||||
*
|
||||
* @param {array} matchPatterns
|
||||
* An array of strings, each describing a match patern.
|
||||
* @param {string} hostName
|
||||
* A string depicting a host name.
|
||||
*
|
||||
* @return {string|undefined}
|
||||
* A match patern string that matches the hostname, or undefined if no
|
||||
* patterns match.
|
||||
*/
|
||||
const matchHostName = function (matchPatterns, hostName) {
|
||||
const matchingUrlReduceFunctionBound = matchingUrlReduceFunction.bind(undefined, hostName);
|
||||
const matchingPattern = domainRegExes
|
||||
const matchingPattern = matchPatterns
|
||||
.filter((aRule) => aRule !== defaultKey)
|
||||
.sort()
|
||||
.reduce(matchingUrlReduceFunctionBound, undefined);
|
||||
|
@ -72,9 +85,23 @@
|
|||
return matchingPattern || undefined;
|
||||
};
|
||||
|
||||
const matchUrl = function (domainRegExes, url) {
|
||||
/**
|
||||
* Returns the match patern that matches the host of a given url.
|
||||
*
|
||||
* @see https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Match_patterns
|
||||
*
|
||||
* @param {array} matchPatterns
|
||||
* An array of strings, each describing a match patern.
|
||||
* @param {string} url
|
||||
* A string depicting a url.
|
||||
*
|
||||
* @return {string|undefined}
|
||||
* A match patern string that matches the host portion of the given
|
||||
* url, or undefined if no patterns match.
|
||||
*/
|
||||
const matchUrl = function (matchPatterns, url) {
|
||||
const hostName = extractHostNameFromUrl(url);
|
||||
return matchHostName(domainRegExes, hostName);
|
||||
return matchHostName(matchPatterns, hostName);
|
||||
};
|
||||
|
||||
window.WEB_API_MANAGER.domainMatcherLib = {
|
||||
|
|
|
@ -16,10 +16,10 @@
|
|||
* @see https://developer.mozilla.org/en-US/Add-ons/WebExtensions/API/webRequest/HttpHeaders
|
||||
* @see https://w3c.github.io/webappsec-csp/
|
||||
*
|
||||
* @param object header
|
||||
* @param {object} header
|
||||
* An object describing a HTTP header
|
||||
*
|
||||
* @return boolean
|
||||
* @return {boolean}
|
||||
* true if the given object depicts a CSP policy with the above stated
|
||||
* properties, and false in all other cases.
|
||||
*/
|
||||
|
@ -63,13 +63,13 @@
|
|||
* @see https://w3c.github.io/webappsec-csp/#strict-dynamic-usage
|
||||
* @see https://w3c.github.io/webappsec-csp/#grammardef-hash-source
|
||||
*
|
||||
* @param string cspInstruction
|
||||
* @param {string} cspInstruction
|
||||
* The value of a HTTP header defining a CSP instruction.
|
||||
* @param string scriptHash
|
||||
* @param {string} scriptHash
|
||||
* A hash value, in the form of "sha256-<some hash>", that is a valid
|
||||
* hash source description.
|
||||
*
|
||||
* @return string|false
|
||||
* @return {string|false}
|
||||
* Returns false if the CSP instruction looks malformed (ie we
|
||||
* couldn't find either a "script-src" or "default-src" section),
|
||||
* otherwise, a new value CSP instruction with the given hash allowed.
|
||||
|
|
|
@ -4,7 +4,13 @@
|
|||
"use strict";
|
||||
window.WEB_API_MANAGER = {
|
||||
constants: {
|
||||
// The name of the cookie that will be used to push domain
|
||||
// configuration information into pages.
|
||||
cookieName: "_wamtcstandards",
|
||||
|
||||
// The value in the packed array of options thats used to
|
||||
// include the shouldLog option in the in bitfield encoded in
|
||||
// the above cookie.
|
||||
shouldLogKey: "shouldLogKey"
|
||||
}
|
||||
};
|
||||
|
|
|
@ -18,10 +18,19 @@
|
|||
|
||||
const bucketSize = 8;
|
||||
|
||||
/**
|
||||
* Encodes a buffer (such as a Uint8Array) to a base64 encoded string.
|
||||
*
|
||||
* @param {ArrayBuffer} buf
|
||||
* A buffer of binary data.
|
||||
*
|
||||
* @return {string}
|
||||
* A base64 encoded string.
|
||||
*/
|
||||
const bufferToBase64 = function (buf) {
|
||||
const binstr = Array.prototype.map.call(buf, function (ch) {
|
||||
return String.fromCharCode(ch);
|
||||
}).join('');
|
||||
}).join("");
|
||||
return window.btoa(binstr);
|
||||
};
|
||||
|
||||
|
@ -61,12 +70,12 @@
|
|||
*
|
||||
* This function is the inverse of the `unpack` function from this module.
|
||||
*
|
||||
* @param array options
|
||||
* @param {array} options
|
||||
* An array of all possible options that might need to be encoded.
|
||||
* @param array selected
|
||||
* @param {array} selected
|
||||
* An array containing zero or more elements from option.
|
||||
*
|
||||
* @return string
|
||||
* @return {string}
|
||||
* A base64 encoded string, which encodes which elements in `options`
|
||||
* were in the provided `selected` array.
|
||||
*/
|
||||
|
@ -83,11 +92,11 @@
|
|||
|
||||
for (i = 0; i < numBuckets; i += 1) {
|
||||
let bitfield = 0;
|
||||
let currentBucket = binnedOptions[i];
|
||||
const currentBucket = binnedOptions[i];
|
||||
|
||||
for (j = 0; j < currentBucket.length; j += 1) {
|
||||
|
||||
let currentOption = currentBucket[j];
|
||||
const currentOption = currentBucket[j];
|
||||
if (selected.indexOf(currentOption) !== -1) {
|
||||
bitfield |= 1 << j;
|
||||
}
|
||||
|
@ -108,13 +117,13 @@
|
|||
*
|
||||
* This function is the inverse of the `pack` function from this module.
|
||||
*
|
||||
* @param array options
|
||||
* @param {array} options
|
||||
* An array of all possible options that might need to be encoded.
|
||||
* @param string data
|
||||
* @param {string} data
|
||||
* A base64 encoded string, generated from the `pack` function in
|
||||
* this module.
|
||||
*
|
||||
* @return array
|
||||
* @return {array}
|
||||
* An array of zero or more elements, each of which will be in the
|
||||
* options array.
|
||||
*/
|
||||
|
@ -131,12 +140,12 @@
|
|||
let i, j;
|
||||
|
||||
for (i = 0; i < bitFields.length; i += 1) {
|
||||
let currentBitField = bitFields[i];
|
||||
let currentOptionsBin = binnedOptions[i];
|
||||
const currentBitField = bitFields[i];
|
||||
const currentOptionsBin = binnedOptions[i];
|
||||
|
||||
for (j = 0; j < bucketSize; j += 1) {
|
||||
if (currentBitField & (1 << j)) {
|
||||
let currentOption = currentOptionsBin[j];
|
||||
const currentOption = currentOptionsBin[j];
|
||||
result.push(currentOption);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -85,8 +85,7 @@
|
|||
}
|
||||
};
|
||||
|
||||
let blockingProxy;
|
||||
blockingProxy = new Proxy(defaultFunction, {
|
||||
const blockingProxy = new Proxy(defaultFunction, {
|
||||
get: function (ignore, property) {
|
||||
logKeyPath();
|
||||
|
||||
|
@ -189,16 +188,16 @@
|
|||
* but with the window.WEB_API_MANAGER_PAGE object set up
|
||||
* correctly to block the desired functions.
|
||||
*
|
||||
* @param object standards
|
||||
* @param {object} standards
|
||||
* A mapping of standard names to information about those standards.
|
||||
* The structure of this object should match whats in data/standards.js
|
||||
* @param array standardNamesToBlock
|
||||
* @param {array} standardNamesToBlock
|
||||
* An array of strings, which must be a subset of the keys of the
|
||||
* standards object.
|
||||
* @param bool shouldLog
|
||||
* @param {boolean} shouldLog
|
||||
* Whether to log the behavior of the blocking proxy.
|
||||
*
|
||||
* @return [string, hash]
|
||||
* @return {[string, string]}
|
||||
* Returns an array containing two values. First, JavaScript code
|
||||
* that instruments the DOM of page's its injected into to render the
|
||||
* standardNamesToBlock standards un-reachable, and second, a
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -37,8 +37,8 @@
|
|||
{
|
||||
"matches": ["*://*/*"],
|
||||
"js": [
|
||||
"lib/vendor/js.cookie.js",
|
||||
"lib/vendor/sjcl.js",
|
||||
"lib/third_party/js.cookie.js",
|
||||
"lib/third_party/sjcl.js",
|
||||
"lib/init.js",
|
||||
"lib/standards.js",
|
||||
"lib/pack.js",
|
||||
|
@ -52,8 +52,8 @@
|
|||
],
|
||||
"background": {
|
||||
"scripts": [
|
||||
"lib/vendor/URI.js",
|
||||
"lib/vendor/sjcl.js",
|
||||
"lib/third_party/URI.js",
|
||||
"lib/third_party/sjcl.js",
|
||||
"lib/init.js",
|
||||
"lib/standards.js",
|
||||
"lib/pack.js",
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
const configureButton = doc.getElementById("config-page-link");
|
||||
const listGroupElm = doc.querySelector("ul.list-group");
|
||||
|
||||
const addDomainRuleToListElm = function (hostToRuleMapping, listElm, aHostName) {
|
||||
const addRuleToList = function (hostToRuleMapping, listElm, aHostName) {
|
||||
|
||||
const domainRule = hostToRuleMapping[aHostName];
|
||||
|
||||
|
@ -53,9 +53,9 @@
|
|||
doc.body.className = "loaded";
|
||||
|
||||
const domainNames = Object.keys(response);
|
||||
const addDomainRuleToListElmBound = addDomainRuleToListElm.bind(undefined, response, listGroupElm);
|
||||
const addRuleToListBound = addRuleToList.bind(undefined, response, listGroupElm);
|
||||
|
||||
domainNames.forEach(addDomainRuleToListElmBound);
|
||||
domainNames.forEach(addRuleToListBound);
|
||||
});
|
||||
}
|
||||
);
|
||||
|
|
22
gulpfile.js
22
gulpfile.js
|
@ -1,17 +1,7 @@
|
|||
const gulp = require("gulp");
|
||||
const fs = require("fs");
|
||||
|
||||
gulp.task('default', function () {
|
||||
|
||||
const isLineAComment = function (aLine) {
|
||||
const lineStartsWithComment = (
|
||||
aLine.indexOf("// ") === 0 ||
|
||||
aLine.indexOf("/*") === 0 ||
|
||||
aLine.indexOf(" */") === 0 ||
|
||||
aLine.indexOf(" * ") === 0
|
||||
);
|
||||
return lineStartsWithComment;
|
||||
};
|
||||
gulp.task("default", function () {
|
||||
|
||||
const builtScriptComment = "/** This file is automatically generated. **/\n";
|
||||
const standardsDefDir = "data/standards";
|
||||
|
@ -26,14 +16,20 @@ gulp.task('default', function () {
|
|||
|
||||
const fileContents = fs.readFileSync(standardsDefDir + "/" + next, {encoding: "utf8"});
|
||||
const standardContents = JSON.parse(fileContents);
|
||||
const nameParts = [standardContents.info.name, standardContents.info.subsection_name].filter(part => !!part);
|
||||
|
||||
const stdName = standardContents.info.name;
|
||||
const stdSubName = standardContents.info.subsection_name;
|
||||
const nameParts = [stdName, stdSubName].filter(part => !!part);
|
||||
|
||||
const standardIdentifier = nameParts.join(": ").trim();
|
||||
standardContents.info.identifier = standardIdentifier;
|
||||
prev[standardIdentifier] = standardContents;
|
||||
return prev;
|
||||
}, {});
|
||||
|
||||
const renderedStandardsModule = builtScriptComment + `window.WEB_API_MANAGER.standards = ${JSON.stringify(combinedStandards)};`;
|
||||
let renderedStandardsModule = builtScriptComment + "\n";
|
||||
renderedStandardsModule += "window.WEB_API_MANAGER.standards = ";
|
||||
renderedStandardsModule += JSON.stringify(combinedStandards) + ";";
|
||||
|
||||
fs.writeFileSync("add-on/lib/standards.js", renderedStandardsModule);
|
||||
});
|
||||
|
|
2
package-lock.json
generated
2
package-lock.json
generated
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "web-api-manager",
|
||||
"version": "0.9.2",
|
||||
"version": "0.9.3",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
|
|
|
@ -24,7 +24,8 @@
|
|||
"clean": "rm -Rf dist/",
|
||||
"bundle": "gulp && web-ext -s add-on -a dist build --overwrite-dest",
|
||||
"firefox": "web-ext -s add-on run",
|
||||
"test:lint": "node_modules/eslint/bin/eslint.js test/functional/*.js test/functional/**/*.js add-on/background_scripts/*.js add-on/config/js/*.js add-on/config/js/components/*.js add-on/lib/*.js add-on/content_scripts/*.js",
|
||||
"test:lint": "node_modules/eslint/bin/eslint.js .",
|
||||
"test:lint:fix": "node_modules/eslint/bin/eslint.js --fix .",
|
||||
"test:func": "npm run clean; npm run bundle && ln -s `ls dist/` dist/webapi_manager.zip && node_modules/mocha/bin/mocha test/functional/*.js",
|
||||
"test": "npm run test:lint && npm run test:func"
|
||||
},
|
||||
|
|
|
@ -14,7 +14,16 @@ describe("Content-Security-Protocol tests", function () {
|
|||
|
||||
const [server, testUrl] = testServer.start(function (headers) {
|
||||
// Add the CSP header to every request
|
||||
headers['Content-Security-Protocol'] = "default-src https: data: 'unsafe-inline' 'unsafe-eval'; child-src https: data: blob:; connect-src https: data: blob:; font-src https: data:; img-src https: data: blob:; media-src https: data: blob:; object-src https:; script-src https: data: blob: 'unsafe-inline' 'unsafe-eval'; style-src https: 'unsafe-inline'; block-all-mixed-content; upgrade-insecure-requests; report-uri https://capture.condenastdigital.com/csp/pitchfork;";
|
||||
const pitchforkCSP = [
|
||||
"default-src https: data: 'unsafe-inline' 'unsafe-eval';",
|
||||
"child-src https: data: blob:; connect-src https: data: blob:;",
|
||||
"font-src https: data:; img-src https: data: blob:;",
|
||||
"media-src https: data: blob:;",
|
||||
"object-src https:;",
|
||||
"script-src https: data: blob: 'unsafe-inline' 'unsafe-eval';",
|
||||
"style-src https: 'unsafe-inline';",
|
||||
];
|
||||
headers["Content-Security-Protocol"] = pitchforkCSP.join(" ");
|
||||
});
|
||||
|
||||
const svgTestScript = injected.testSVGTestScript();
|
||||
|
|
|
@ -21,12 +21,12 @@ module.exports.temporaryAddOnInstallScript = (function () {
|
|||
const funcToInject = function () {
|
||||
|
||||
const {Components, AddonManager} = window;
|
||||
let fileUtils = Components.utils.import('resource://gre/modules/FileUtils.jsm');
|
||||
let FileUtils = fileUtils.FileUtils;
|
||||
let callback = arguments[arguments.length - 1];
|
||||
Components.utils.import('resource://gre/modules/AddonManager.jsm');
|
||||
const fileUtils = Components.utils.import("resource://gre/modules/FileUtils.jsm");
|
||||
const FileUtils = fileUtils.FileUtils;
|
||||
const callback = arguments[arguments.length - 1];
|
||||
Components.utils.import("resource://gre/modules/AddonManager.jsm");
|
||||
|
||||
let listener = {
|
||||
const listener = {
|
||||
onInstallEnded: function(install, addon) {
|
||||
callback([addon.id, 0]);
|
||||
},
|
||||
|
@ -39,7 +39,7 @@ module.exports.temporaryAddOnInstallScript = (function () {
|
|||
}
|
||||
};
|
||||
|
||||
let file = new FileUtils.File(arguments[0]);
|
||||
const file = new FileUtils.File(arguments[0]);
|
||||
|
||||
AddonManager.addAddonListener(listener);
|
||||
AddonManager.installTemporaryAddon(file).catch(error => {
|
||||
|
@ -73,7 +73,7 @@ module.exports.setStandardsAsBlockedScript = (function () {
|
|||
const funcSource = stripFuncFromSource(funcToInject.toString());
|
||||
|
||||
return function (standardsToBlock) {
|
||||
return funcSource.replace('"###REPLACE###"', JSON.stringify(standardsToBlock));
|
||||
return funcSource.replace("\"###REPLACE###\"", JSON.stringify(standardsToBlock));
|
||||
};
|
||||
}());
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ module.exports.start = function (callback) {
|
|||
|
||||
const httpServer = http.createServer(function (req, res) {
|
||||
|
||||
let headers = {"Content-Type": "text/html; charset=utf-8"};
|
||||
const headers = {"Content-Type": "text/html; charset=utf-8"};
|
||||
|
||||
if (callback !== undefined) {
|
||||
callback(headers);
|
||||
|
|
|
@ -49,9 +49,7 @@ module.exports.promiseSetFormAndSubmit = function (driver, values) {
|
|||
|
||||
module.exports.promiseAddonButton = function (driver) {
|
||||
driver.setContext(Context.CHROME);
|
||||
return driver.wait(until.elementLocated(
|
||||
by.css("[tooltiptext='WebAPI Manager']")
|
||||
), 2000);
|
||||
return driver.wait(until.elementLocated(by.css("[tooltiptext='WebAPI Manager']")), 2000);
|
||||
};
|
||||
|
||||
module.exports.promiseExtensionConfigPage = function (driver) {
|
||||
|
@ -68,9 +66,7 @@ module.exports.promiseExtensionConfigPage = function (driver) {
|
|||
|
||||
module.exports.promiseAddonConfigButton = function (driver) {
|
||||
driver.setContext(Context.CHROME);
|
||||
return driver.wait(until.elementLocated(
|
||||
by.id("config-page-link")
|
||||
), 2000);
|
||||
return driver.wait(until.elementLocated(by.id("config-page-link")), 2000);
|
||||
};
|
||||
|
||||
module.exports.promiseSetBlockingRules = function (driver, standardsToBlock) {
|
||||
|
@ -83,18 +79,18 @@ module.exports.promiseSetBlockingRules = function (driver, standardsToBlock) {
|
|||
|
||||
module.exports.promiseGetDriver = function () {
|
||||
|
||||
let driver = new webdriver.Builder()
|
||||
.forBrowser('firefox')
|
||||
const driver = new webdriver.Builder()
|
||||
.forBrowser("firefox")
|
||||
.build();
|
||||
|
||||
driver.setContext(Context.CHROME);
|
||||
|
||||
let fileLocation = path.join(process.cwd(), "dist", "webapi_manager.zip");
|
||||
const fileLocation = path.join(process.cwd(), "dist", "webapi_manager.zip");
|
||||
|
||||
// This manually installs the add-on as a temporary add-on.
|
||||
// Hopefully selenium/geckodriver will get a way to do this soon:
|
||||
// https://bugzilla.mozilla.org/show_bug.cgi?id=1298025
|
||||
let installAddOnPromise = driver.executeAsyncScript(
|
||||
const installAddOnPromise = driver.executeAsyncScript(
|
||||
injectedScripts.temporaryAddOnInstallScript(),
|
||||
fileLocation
|
||||
);
|
||||
|
|
|
@ -5,7 +5,7 @@ let testParams;
|
|||
try {
|
||||
testParams = require("../../test.config.js");
|
||||
} catch (e) {
|
||||
throw "Unable to load a test.config.js module in the project root. Copy test.config.example.js to test.config.js and try again";
|
||||
throw "Unable to load a test.config.js module in the project root. Copy test.config.example.js to test.config.js.";
|
||||
}
|
||||
const injected = require("./lib/injected");
|
||||
const webdriver = require("selenium-webdriver");
|
||||
|
@ -42,15 +42,11 @@ describe("Logging into popular sites", function () {
|
|||
return driverReference.get("https://github.com/login");
|
||||
})
|
||||
.then(function () {
|
||||
return driverReference.wait(until.elementLocated(
|
||||
by.name("password")
|
||||
), 2000);
|
||||
return driverReference.wait(until.elementLocated(by.name("password")), 2000);
|
||||
})
|
||||
.then(() => utils.promiseSetFormAndSubmit(driverReference, formValues))
|
||||
.then(function () {
|
||||
return driverReference.wait(until.elementLocated(
|
||||
by.css("body.logged-in")
|
||||
), 2000);
|
||||
return driverReference.wait(until.elementLocated(by.css("body.logged-in")), 2000);
|
||||
})
|
||||
.then(function () {
|
||||
driverReference.quit();
|
||||
|
@ -75,15 +71,11 @@ describe("Logging into popular sites", function () {
|
|||
})
|
||||
.then(() => driverReference.get("https://github.com/login"))
|
||||
.then(function () {
|
||||
return driverReference.wait(until.elementLocated(
|
||||
by.name("password")
|
||||
), 2000);
|
||||
return driverReference.wait(until.elementLocated(by.name("password")), 2000);
|
||||
})
|
||||
.then(() => utils.promiseSetFormAndSubmit(driverReference, formValues))
|
||||
.then(function () {
|
||||
return driverReference.wait(until.elementLocated(
|
||||
by.css("body.logged-in")
|
||||
), 2000);
|
||||
return driverReference.wait(until.elementLocated(by.css("body.logged-in")), 2000);
|
||||
})
|
||||
.then(() => driverReference.executeAsyncScript(svgTestScript))
|
||||
.then(function () {
|
||||
|
@ -123,15 +115,11 @@ describe("Logging into popular sites", function () {
|
|||
return driverReference.get("https://www.facebook.com/");
|
||||
})
|
||||
.then(function () {
|
||||
return driverReference.wait(until.elementsLocated(
|
||||
by.name("email")
|
||||
), 5000);
|
||||
return driverReference.wait(until.elementsLocated(by.name("email")), 5000);
|
||||
})
|
||||
.then(() => utils.promiseSetFormAndSubmit(driverReference, formValues))
|
||||
.then(function () {
|
||||
return driverReference.wait(until.elementLocated(
|
||||
by.css("div[data-click='profile_icon']")
|
||||
), 10000);
|
||||
return driverReference.wait(until.elementLocated(by.css("div[data-click='profile_icon']")), 10000);
|
||||
})
|
||||
.then(function () {
|
||||
driverReference.quit();
|
||||
|
@ -158,47 +146,38 @@ describe("Logging into popular sites", function () {
|
|||
|
||||
it("Log in", function (done) {
|
||||
|
||||
let driverReference;
|
||||
let driver;
|
||||
|
||||
utils.promiseGetDriver()
|
||||
.then(function (driver) {
|
||||
driverReference = driver;
|
||||
return driverReference.get("https://www.youtube.com");
|
||||
.then(function (testDriver) {
|
||||
driver = testDriver;
|
||||
return driver.get("https://www.youtube.com");
|
||||
})
|
||||
.then(function () {
|
||||
return driverReference.wait(until.elementsLocated(
|
||||
by.css("#buttons ytd-button-renderer a")
|
||||
), 5000);
|
||||
return driver.wait(until.elementsLocated(by.css("#buttons ytd-button-renderer a")), 5000);
|
||||
})
|
||||
.then(anchors => anchors[anchors.length - 1].click())
|
||||
.then(() => utils.pause(2000))
|
||||
.then(function () {
|
||||
return driverReference.wait(until.elementLocated(
|
||||
by.name("identifier")
|
||||
), 5000);
|
||||
return driver.wait(until.elementLocated(by.name("identifier")), 5000);
|
||||
})
|
||||
.then(identifierElm => driverReference.wait(until.elementIsVisible(identifierElm)))
|
||||
.then(identifierElm => identifierElm.sendKeys(testParams.google.username, keys.ENTER))
|
||||
.then(idElm => driver.wait(until.elementIsVisible(idElm)))
|
||||
.then(idElm => idElm.sendKeys(testParams.google.username, keys.ENTER))
|
||||
.then(() => utils.pause(2000))
|
||||
.then(function () {
|
||||
return driverReference.wait(until.elementLocated(
|
||||
by.name("password")
|
||||
), 5000);
|
||||
return driver.wait(until.elementLocated(by.name("password")), 5000);
|
||||
})
|
||||
.then(passwordElm => driverReference.wait(until.elementIsVisible(passwordElm)))
|
||||
.then(passwordElm => driver.wait(until.elementIsVisible(passwordElm)))
|
||||
.then(passwordElm => passwordElm.sendKeys(testParams.google.password, keys.ENTER))
|
||||
.then(function () {
|
||||
return driverReference.wait(until.elementLocated(
|
||||
by.css("ytd-app")
|
||||
), 10000);
|
||||
return driver.wait(until.elementLocated(by.css("ytd-app")), 10000);
|
||||
})
|
||||
.then(function () {
|
||||
driverReference.quit();
|
||||
driver.quit();
|
||||
done();
|
||||
})
|
||||
.catch(function (e) {
|
||||
driverReference.quit();
|
||||
console.log(e);
|
||||
.catch(function () {
|
||||
driver.quit();
|
||||
done(new Error("Was not able to log in"));
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue