diff --git a/add-on/lib/domainmatcher.js b/add-on/lib/domainmatcher.js index 59b0f23..91a9fc3 100644 --- a/add-on/lib/domainmatcher.js +++ b/add-on/lib/domainmatcher.js @@ -58,6 +58,14 @@ return next; } + // Also apply a slightly looser match, to make rules in the form + // of *.example.com match example.com. + if (next.startsWith("*.") && + next.endsWith(hostName) && + next.length === hostName.length + 2) { + return next; + } + return prev; }; diff --git a/add-on/lib/init.js b/add-on/lib/init.js index fec0fc5..98cef0f 100644 --- a/add-on/lib/init.js +++ b/add-on/lib/init.js @@ -2,6 +2,17 @@ // the "namespace" we'll use for all the content scripts in the extension. (function () { "use strict"; + + // If this code is being included by a unit test, the window object + // won't exist, so stub it out here. + try { + if (window === undefined) { + // This will throw in node... + } + } catch (e) { + global.window = {}; + } + window.WEB_API_MANAGER = { constants: { // The name of the cookie that will be used to push domain diff --git a/package.json b/package.json index ef82442..92f4a7e 100644 --- a/package.json +++ b/package.json @@ -26,9 +26,9 @@ "firefox": "web-ext -s add-on run", "lint": "node_modules/eslint/bin/eslint.js .", "lint:fix": "node_modules/eslint/bin/eslint.js --fix .", - "test": "npm run clean; npm run bundle && ln -s `ls dist/` dist/webapi_manager.zip && cross-env node_modules/mocha/bin/mocha test/functional/*.js --only-local-tests", + "test": "npm run clean; npm run bundle && ln -s `ls dist/` dist/webapi_manager.zip && cross-env node_modules/mocha/bin/mocha test/unit/*.js test/functional/*.js --only-local-tests", "test:watch": "cross-env npm test --watch", - "test:all": "npm run clean; npm run bundle && ln -s `ls dist/` dist/webapi_manager.zip && cross-env node_modules/mocha/bin/mocha test/functional/*.js" + "test:all": "npm run clean; npm run bundle && ln -s `ls dist/` dist/webapi_manager.zip && cross-env node_modules/mocha/bin/mocha test/unit/*.js test/functional/*.js" }, "pre-push": { "run": [ diff --git a/test/unit/rule-matching.js b/test/unit/rule-matching.js new file mode 100644 index 0000000..e025d51 --- /dev/null +++ b/test/unit/rule-matching.js @@ -0,0 +1,75 @@ +/** + * Tests to ensure that the pattern matching code (what determins which + * standard blocking rules should be applied to which domain) is correct. + * + * The code being tested here mostly lives in (from the project root) + * add-on/lib/domainmatcher.js + */ +"use strict"; + +const assert = require("assert"); +const path = require("path"); +const addonLibPath = path.join(__dirname, "..", "..", "add-on", "lib"); + +// These will end up not returing anything, but will instead populate +// window.WEB_API_MANAGER +const webAPIInitStub = require(path.join(addonLibPath, "init.js")); +const domainMatcherStub = require(path.join(addonLibPath, "domainmatcher.js")); +const domainMatcherLib = window.WEB_API_MANAGER.domainMatcherLib; + +describe("Host Pattern Matching", function () { + + const testPatterns = [ + "*.example.com", + "www.uic.edu", + "cs.uic.edu", + ]; + + describe("Exact matches", function () { + + it("Positive case: input 'www.uic.edu' gives pattern 'www.uic.edu'", function (done) { + + const testHostName = "www.uic.edu"; + const matchingPattern = domainMatcherLib.matchHostName(testPatterns, testHostName); + assert.equal(matchingPattern, "www.uic.edu"); + done(); + }); + + it("Negative case: input 'nope.uic.edu' gives no pattern", function (done) { + + const testHostName = "nope.uic.edu"; + const matchingPattern = domainMatcherLib.matchHostName(testPatterns, testHostName); + assert.equal(matchingPattern, undefined); + done(); + }); + }); + + describe("Wildcard matches", function () { + + it("Positive case: input 'www.example.com' gives pattern '*.example.com'", function (done) { + + const testHostName = "www.example.com"; + const matchingPattern = domainMatcherLib.matchHostName(testPatterns, testHostName); + assert.equal(matchingPattern, "*.example.com"); + done(); + }); + + it("Negative case: input 'www.example.com.co.uk' gives no pattern", function (done) { + + const testHostName = "www.example.com.co.uk"; + const matchingPattern = domainMatcherLib.matchHostName(testPatterns, testHostName); + assert.equal(matchingPattern, undefined); + done(); + }); + }); + + describe("Collapsed matches", function () { + + it("Positive case: input 'example.com' gives pattern '*.example.com'", function (done) { + const testHostName = "example.com"; + const matchingPattern = domainMatcherLib.matchHostName(testPatterns, testHostName); + assert.equal(matchingPattern, "*.example.com"); + done(); + }); + }); +}); \ No newline at end of file