diff options
author | Matt A. Tobin <email@mattatobin.com> | 2018-02-09 11:10:00 -0500 |
---|---|---|
committer | Matt A. Tobin <email@mattatobin.com> | 2018-02-09 11:10:00 -0500 |
commit | f164d9124708b50789dbb6959e1de96cc5697c48 (patch) | |
tree | 6dffd12e08c5383130df0252fb69cd6d6330794f /toolkit/components/webextensions/test/mochitest/test_ext_storage_content.html | |
parent | 30de4018913f0cdaea19d1dd12ecd8209e2ed08e (diff) | |
download | UXP-f164d9124708b50789dbb6959e1de96cc5697c48.tar UXP-f164d9124708b50789dbb6959e1de96cc5697c48.tar.gz UXP-f164d9124708b50789dbb6959e1de96cc5697c48.tar.lz UXP-f164d9124708b50789dbb6959e1de96cc5697c48.tar.xz UXP-f164d9124708b50789dbb6959e1de96cc5697c48.zip |
Rename Toolkit's webextensions component directory to better reflect what it is.
Diffstat (limited to 'toolkit/components/webextensions/test/mochitest/test_ext_storage_content.html')
-rw-r--r-- | toolkit/components/webextensions/test/mochitest/test_ext_storage_content.html | 330 |
1 files changed, 330 insertions, 0 deletions
diff --git a/toolkit/components/webextensions/test/mochitest/test_ext_storage_content.html b/toolkit/components/webextensions/test/mochitest/test_ext_storage_content.html new file mode 100644 index 000000000..09a33814a --- /dev/null +++ b/toolkit/components/webextensions/test/mochitest/test_ext_storage_content.html @@ -0,0 +1,330 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>WebExtension test</title> + <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <script type="text/javascript" src="/tests/SimpleTest/SpawnTask.js"></script> + <script type="text/javascript" src="/tests/SimpleTest/ExtensionTestUtils.js"></script> + <script type="text/javascript" src="head.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> + +<script type="application/javascript"> +"use strict"; + +// Copied from toolkit/components/extensions/test/xpcshell/test_ext_storage.js. +// The storage API in content scripts should behave identical to the storage API +// in background pages. +const STORAGE_SYNC_PREF = "webextensions.storage.sync.enabled"; +/** + * Utility function to ensure that all supported APIs for getting are + * tested. + * + * @param {string} areaName + * either "local" or "sync" according to what we want to test + * @param {string} prop + * "key" to look up using the storage API + * @param {Object} value + * "value" to compare against + */ +async function checkGetImpl(areaName, prop, value) { + let storage = browser.storage[areaName]; + + let data = await storage.get(null); + browser.test.assertEq(value, data[prop], `null getter worked for ${prop} in ${areaName}`); + + data = await storage.get(prop); + browser.test.assertEq(value, data[prop], `string getter worked for ${prop} in ${areaName}`); + + data = await storage.get([prop]); + browser.test.assertEq(value, data[prop], `array getter worked for ${prop} in ${areaName}`); + + data = await storage.get({[prop]: undefined}); + browser.test.assertEq(value, data[prop], `object getter worked for ${prop} in ${areaName}`); +} + +async function contentScript(checkGet) { + let globalChanges, gResolve; + function clearGlobalChanges() { + globalChanges = new Promise(resolve => { gResolve = resolve; }); + } + clearGlobalChanges(); + let expectedAreaName; + + browser.storage.onChanged.addListener((changes, areaName) => { + browser.test.assertEq(expectedAreaName, areaName, + "Expected area name received by listener"); + gResolve(changes); + }); + + async function checkChanges(areaName, changes, message) { + function checkSub(obj1, obj2) { + for (let prop in obj1) { + browser.test.assertTrue(obj1[prop] !== undefined, + `checkChanges ${areaName} ${prop} is missing (${message})`); + browser.test.assertTrue(obj2[prop] !== undefined, + `checkChanges ${areaName} ${prop} is missing (${message})`); + browser.test.assertEq(obj1[prop].oldValue, obj2[prop].oldValue, + `checkChanges ${areaName} ${prop} old (${message})`); + browser.test.assertEq(obj1[prop].newValue, obj2[prop].newValue, + `checkChanges ${areaName} ${prop} new (${message})`); + } + } + + const recentChanges = await globalChanges; + checkSub(changes, recentChanges); + checkSub(recentChanges, changes); + clearGlobalChanges(); + } + + /* eslint-disable dot-notation */ + async function runTests(areaName) { + expectedAreaName = areaName; + let storage = browser.storage[areaName]; + // Set some data and then test getters. + try { + await storage.set({"test-prop1": "value1", "test-prop2": "value2"}); + await checkChanges(areaName, + {"test-prop1": {newValue: "value1"}, "test-prop2": {newValue: "value2"}}, + "set (a)"); + + await checkGet(areaName, "test-prop1", "value1"); + await checkGet(areaName, "test-prop2", "value2"); + + let data = await storage.get({"test-prop1": undefined, "test-prop2": undefined, "other": "default"}); + browser.test.assertEq("value1", data["test-prop1"], "prop1 correct (a)"); + browser.test.assertEq("value2", data["test-prop2"], "prop2 correct (a)"); + browser.test.assertEq("default", data["other"], "other correct"); + + data = await storage.get(["test-prop1", "test-prop2", "other"]); + browser.test.assertEq("value1", data["test-prop1"], "prop1 correct (b)"); + browser.test.assertEq("value2", data["test-prop2"], "prop2 correct (b)"); + browser.test.assertFalse("other" in data, "other correct"); + + // Remove data in various ways. + await storage.remove("test-prop1"); + await checkChanges(areaName, {"test-prop1": {oldValue: "value1"}}, "remove string"); + + data = await storage.get(["test-prop1", "test-prop2"]); + browser.test.assertFalse("test-prop1" in data, "prop1 absent (remove string)"); + browser.test.assertTrue("test-prop2" in data, "prop2 present (remove string)"); + + await storage.set({"test-prop1": "value1"}); + await checkChanges(areaName, {"test-prop1": {newValue: "value1"}}, "set (c)"); + + data = await storage.get(["test-prop1", "test-prop2"]); + browser.test.assertEq(data["test-prop1"], "value1", "prop1 correct (c)"); + browser.test.assertEq(data["test-prop2"], "value2", "prop2 correct (c)"); + + await storage.remove(["test-prop1", "test-prop2"]); + await checkChanges(areaName, + {"test-prop1": {oldValue: "value1"}, "test-prop2": {oldValue: "value2"}}, + "remove array"); + + data = await storage.get(["test-prop1", "test-prop2"]); + browser.test.assertFalse("test-prop1" in data, "prop1 absent (remove array)"); + browser.test.assertFalse("test-prop2" in data, "prop2 absent (remove array)"); + + // test storage.clear + await storage.set({"test-prop1": "value1", "test-prop2": "value2"}); + // Make sure that set() handler happened before we clear the + // promise again. + await globalChanges; + + clearGlobalChanges(); + await storage.clear(); + + await checkChanges(areaName, + {"test-prop1": {oldValue: "value1"}, "test-prop2": {oldValue: "value2"}}, + "clear"); + data = await storage.get(["test-prop1", "test-prop2"]); + browser.test.assertFalse("test-prop1" in data, "prop1 absent (clear)"); + browser.test.assertFalse("test-prop2" in data, "prop2 absent (clear)"); + + // Make sure we can store complex JSON data. + // known previous values + await storage.set({"test-prop1": "value1", "test-prop2": "value2"}); + + // Make sure the set() handler landed. + await globalChanges; + + clearGlobalChanges(); + await storage.set({ + "test-prop1": { + str: "hello", + bool: true, + null: null, + undef: undefined, + obj: {}, + arr: [1, 2], + date: new Date(0), + regexp: /regexp/, + func: function func() {}, + window, + }, + }); + + await storage.set({"test-prop2": function func() {}}); + const recentChanges = await globalChanges; + + browser.test.assertEq("value1", recentChanges["test-prop1"].oldValue, "oldValue correct"); + browser.test.assertEq("object", typeof(recentChanges["test-prop1"].newValue), "newValue is obj"); + clearGlobalChanges(); + + data = await storage.get({"test-prop1": undefined, "test-prop2": undefined}); + let obj = data["test-prop1"]; + + browser.test.assertEq("hello", obj.str, "string part correct"); + browser.test.assertEq(true, obj.bool, "bool part correct"); + browser.test.assertEq(null, obj.null, "null part correct"); + browser.test.assertEq(undefined, obj.undef, "undefined part correct"); + browser.test.assertEq(undefined, obj.func, "function part correct"); + browser.test.assertEq(undefined, obj.window, "window part correct"); + browser.test.assertEq("1970-01-01T00:00:00.000Z", obj.date, "date part correct"); + browser.test.assertEq("/regexp/", obj.regexp, "regexp part correct"); + browser.test.assertEq("object", typeof(obj.obj), "object part correct"); + browser.test.assertTrue(Array.isArray(obj.arr), "array part present"); + browser.test.assertEq(1, obj.arr[0], "arr[0] part correct"); + browser.test.assertEq(2, obj.arr[1], "arr[1] part correct"); + browser.test.assertEq(2, obj.arr.length, "arr.length part correct"); + + obj = data["test-prop2"]; + + browser.test.assertEq("[object Object]", {}.toString.call(obj), "function serialized as a plain object"); + browser.test.assertEq(0, Object.keys(obj).length, "function serialized as an empty object"); + } catch (e) { + browser.test.fail(`Error: ${e} :: ${e.stack}`); + browser.test.notifyFail("storage"); + } + } + + browser.test.onMessage.addListener(msg => { + let promise; + if (msg === "test-local") { + promise = runTests("local"); + } else if (msg === "test-sync") { + promise = runTests("sync"); + } + promise.then(() => browser.test.sendMessage("test-finished")); + }); + + browser.test.sendMessage("ready"); +} + +let extensionData = { + manifest: { + content_scripts: [{ + "matches": ["http://mochi.test/*/file_sample.html"], + "js": ["content_script.js"], + "run_at": "document_idle", + }], + + permissions: ["storage"], + }, + + files: { + "content_script.js": `(${contentScript})(${checkGetImpl})`, + }, +}; + +add_task(function* test_contentscript() { + let win = window.open("file_sample.html"); + yield waitForLoad(win); + + yield SpecialPowers.pushPrefEnv({ + set: [[STORAGE_SYNC_PREF, true]], + }); + + let extension = ExtensionTestUtils.loadExtension(extensionData); + yield Promise.all([extension.startup(), extension.awaitMessage("ready")]); + extension.sendMessage("test-local"); + yield extension.awaitMessage("test-finished"); + + extension.sendMessage("test-sync"); + yield extension.awaitMessage("test-finished"); + + yield SpecialPowers.popPrefEnv(); + yield extension.unload(); + + win.close(); +}); + +add_task(function* test_local_cache_invalidation() { + let win = window.open("file_sample.html"); + + function background(checkGet) { + browser.test.onMessage.addListener(async msg => { + if (msg === "set-initial") { + await browser.storage.local.set({"test-prop1": "value1", "test-prop2": "value2"}); + browser.test.sendMessage("set-initial-done"); + } else if (msg === "check") { + await checkGet("local", "test-prop1", "value1"); + await checkGet("local", "test-prop2", "value2"); + browser.test.sendMessage("check-done"); + } + }); + + browser.test.sendMessage("ready"); + } + + let extension = ExtensionTestUtils.loadExtension({ + manifest: { + permissions: ["storage"], + }, + background: `(${background})(${checkGetImpl})`, + }); + + yield extension.startup(); + yield extension.awaitMessage("ready"); + + extension.sendMessage("set-initial"); + yield extension.awaitMessage("set-initial-done"); + + SpecialPowers.invalidateExtensionStorageCache(); + + extension.sendMessage("check"); + yield extension.awaitMessage("check-done"); + + yield extension.unload(); + win.close(); +}); + +add_task(function* test_config_flag_needed() { + let win = window.open("file_sample.html"); + yield waitForLoad(win); + + function background() { + let promises = []; + let apiTests = [ + {method: "get", args: ["foo"]}, + {method: "set", args: [{foo: "bar"}]}, + {method: "remove", args: ["foo"]}, + {method: "clear", args: []}, + ]; + apiTests.forEach(testDef => { + promises.push(browser.test.assertRejects( + browser.storage.sync[testDef.method](...testDef.args), + "Please set webextensions.storage.sync.enabled to true in about:config", + `storage.sync.${testDef.method} is behind a flag`)); + }); + + Promise.all(promises).then(() => browser.test.notifyPass("flag needed")); + } + + let extension = ExtensionTestUtils.loadExtension({ + manifest: { + permissions: ["storage"], + }, + background: `(${background})(${checkGetImpl})`, + }); + + yield extension.startup(); + yield extension.awaitFinish("flag needed"); + yield extension.unload(); + win.close(); +}); +</script> + +</body> +</html> |