diff --git a/test/test-browser-global.js b/test/test-browser-global.js index 4bebb17..cc9f56e 100644 --- a/test/test-browser-global.js +++ b/test/test-browser-global.js @@ -11,4 +11,55 @@ describe("browser-polyfill", () => { assert.equal(typeof window.browser, "object", "Got the window.browser object"); }); }); + + it("do not override the global browser namespace if it already exists", () => { + const fakeChrome = { + runtime: {lastError: null}, + }; + const fakeBrowser = { + mycustomns: {mykey: true}, + }; + + return setupTestDOMWindow(fakeChrome, fakeBrowser).then(window => { + assert.deepEqual(window.browser, fakeBrowser, + "The existent browser has not been wrapped"); + }); + }); + + describe("browser wrapper", () => { + it("supports custom properties defined using Object.defineProperty", () => { + const fakeChrome = {}; + return setupTestDOMWindow(fakeChrome).then(window => { + Object.defineProperty(window.browser, "myns", { + enumerable: true, + configurable: true, + value: {mykey: true}, + }); + + assert.ok("myns" in window.browser, "The custom property exists"); + assert.ok("mykey" in window.browser.myns, + "The content of the custom property exists"); + + assert.deepEqual(window.browser.myns, {mykey: true}, + "The custom property has the expected content"); + + delete window.browser.myns; + + assert.ok(!("myns" in window.browser), + "The deleted custom defined property has been removed"); + }); + }); + + it("returns undefined for property undefined in the target", () => { + const fakeChrome = {myns: {mykey: true}}; + return setupTestDOMWindow(fakeChrome).then(window => { + assert.equal(window.browser.myns.mykey, true, + "Got the expected result from a wrapped property"); + assert.equal(window.browser.myns.nonexistent, undefined, + "Got undefined for non existent property"); + assert.equal(window.browser.nonexistent, undefined, + "Got undefined for non existent namespaces"); + }); + }); + }); }); diff --git a/test/test-proxied-properties.js b/test/test-proxied-properties.js index f969d69..867ddf6 100644 --- a/test/test-proxied-properties.js +++ b/test/test-proxied-properties.js @@ -1,11 +1,31 @@ "use strict"; const {assert} = require("chai"); +const sinon = require("sinon"); const {setupTestDOMWindow} = require("./setup"); describe("browser-polyfill", () => { describe("proxies non-wrapped functions", () => { + it("should proxy non-wrapped methods", () => { + const fakeChrome = { + runtime: { + nonwrappedmethod: sinon.spy(), + }, + }; + return setupTestDOMWindow(fakeChrome).then(window => { + assert.ok(window.browser.runtime.nonwrappedmethod); + + const fakeCallback = () => {}; + window.browser.runtime.nonwrappedmethod(fakeCallback); + + const receivedCallback = fakeChrome.runtime.nonwrappedmethod.firstCall.args[0]; + + assert.equal(fakeCallback, receivedCallback, + "The callback has not been wrapped for the nonwrappedmethod"); + }); + }); + it("should proxy getters and setters", () => { const fakeChrome = { runtime: {myprop: "previous-value"}, @@ -58,6 +78,10 @@ describe("browser-polyfill", () => { const fakeChrome = {}; return setupTestDOMWindow(fakeChrome).then(window => { window.browser.newns = {newkey: "test-value"}; + + assert.ok("newns" in window.browser, "The custom namespace is in the wrapper"); + assert.ok("newns" in window.chrome, "The custom namespace is in the target"); + assert.equal(window.browser.newns.newkey, "test-value", "Got the expected result from setting a wrapped property name"); @@ -69,7 +93,6 @@ describe("browser-polyfill", () => { assert.deepEqual(window.browser.newns, window.chrome.newns, "chrome.newns and browser.newns are the same"); - delete window.browser.newns.newkey2; assert.equal(window.browser.newns.newkey2, undefined, "Got the expected result from setting a wrapped property name"); diff --git a/test/test-runtime-onMessage.js b/test/test-runtime-onMessage.js index 048dad7..54085d1 100644 --- a/test/test-runtime-onMessage.js +++ b/test/test-runtime-onMessage.js @@ -7,6 +7,29 @@ const {setupTestDOMWindow} = require("./setup"); describe("browser-polyfill", () => { describe("wrapped runtime.onMessage listener", () => { + it("do not wrap the listener if it is not a function", () => { + const fakeChrome = { + runtime: { + lastError: null, + onMessage: { + addListener: sinon.spy(), + hasListener: sinon.stub(), + removeListener: sinon.spy(), + }, + }, + }; + + return setupTestDOMWindow(fakeChrome).then(window => { + const fakeNonFunctionListener = {fake: "non function listener"}; + + window.browser.runtime.onMessage.addListener(fakeNonFunctionListener); + + assert.deepEqual(fakeChrome.runtime.onMessage.addListener.firstCall.args[0], + fakeNonFunctionListener, + "The non-function listener has not been wrapped"); + }); + }); + it("keeps track of the listeners added", () => { const messageListener = sinon.spy(); @@ -75,20 +98,29 @@ describe("browser-polyfill", () => { }, }; + // Plain value returned. const messageListener = sinon.stub(); const firstResponse = "fake reply"; - const secondResponse = Promise.resolve("fake reply2"); + // Resolved Promise returned. + const secondResponse = Promise.resolve("fake reply 2"); + // Rejected Promise returned. + const thirdResponse = Promise.reject("fake error 3"); + const sendResponseSpy = sinon.spy(); - messageListener.onFirstCall().returns(firstResponse) - .onSecondCall().returns(secondResponse); + messageListener + .onFirstCall().returns(firstResponse) + .onSecondCall().returns(secondResponse) + .onThirdCall().returns(thirdResponse); + + let wrappedListener; return setupTestDOMWindow(fakeChrome).then(window => { window.browser.runtime.onMessage.addListener(messageListener); assert.ok(fakeChrome.runtime.onMessage.addListener.calledOnce); - const wrappedListener = fakeChrome.runtime.onMessage.addListener.firstCall.args[0]; + wrappedListener = fakeChrome.runtime.onMessage.addListener.firstCall.args[0]; wrappedListener("fake message", {name: "fake sender"}, sendResponseSpy); @@ -110,11 +142,27 @@ describe("browser-polyfill", () => { "The unwrapped message listener has been called"); assert.deepEqual(messageListener.secondCall.args, ["fake message2", {name: "fake sender2"}], - "The unwrapped message listener has received the expected parameters"); + "The unwrapped listener has received the expected parameters"); assert.ok(sendResponseSpy.calledTwice, "The sendResponse function has been called"); - assert.equal(sendResponseSpy.secondCall.args[0], "fake reply2", + assert.equal(sendResponseSpy.secondCall.args[0], "fake reply 2", "sendResponse callback has been called with the expected parameters"); + }).then(() => { + wrappedListener("fake message3", {name: "fake sender3"}, sendResponseSpy); + + // Wait the third response promise to be rejected. + return thirdResponse.catch(err => { + assert.equal(messageListener.callCount, 3, + "The unwrapped message listener has been called"); + assert.deepEqual(messageListener.thirdCall.args, + ["fake message3", {name: "fake sender3"}], + "The unwrapped listener has received the expected parameters"); + + assert.equal(sendResponseSpy.callCount, 3, + "The sendResponse function has been called"); + assert.equal(sendResponseSpy.thirdCall.args[0], err, + "sendResponse callback has been called with the expected parameters"); + }); }); }); });