diff options
Diffstat (limited to 'devtools/shared/webconsole/test/test_console_serviceworker.html')
-rw-r--r-- | devtools/shared/webconsole/test/test_console_serviceworker.html | 157 |
1 files changed, 157 insertions, 0 deletions
diff --git a/devtools/shared/webconsole/test/test_console_serviceworker.html b/devtools/shared/webconsole/test/test_console_serviceworker.html new file mode 100644 index 000000000..83d728d92 --- /dev/null +++ b/devtools/shared/webconsole/test/test_console_serviceworker.html @@ -0,0 +1,157 @@ +<!DOCTYPE HTML> +<html lang="en"> +<head> + <meta charset="utf8"> + <title>Test for the Console API and Service Workers</title> + <script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + <script type="text/javascript;version=1.8" src="common.js"></script> + <!-- Any copyright is dedicated to the Public Domain. + - http://creativecommons.org/publicdomain/zero/1.0/ --> +</head> +<body> +<p>Test for the Console API and Service Workers</p> + +<script class="testbody" type="text/javascript;version=1.8"> +SimpleTest.waitForExplicitFinish(); + +let BASE_URL = "https://example.com/chrome/devtools/shared/webconsole/test/"; +let SERVICE_WORKER_URL = BASE_URL + "helper_serviceworker.js"; +let SCOPE = BASE_URL + "foo/"; +let NONSCOPE_FRAME_URL = BASE_URL + "sandboxed_iframe.html"; +let SCOPE_FRAME_URL = SCOPE + "fake.html"; +let SCOPE_FRAME_URL2 = SCOPE + "whatsit.html"; +let MESSAGE = 'Tic Tock'; + +let expectedConsoleCalls = [ + { + level: "log", + filename: /helper_serviceworker/, + arguments: ['script evaluation'], + }, + { + level: "log", + filename: /helper_serviceworker/, + arguments: ['install event'], + }, + { + level: "log", + filename: /helper_serviceworker/, + arguments: ['activate event'], + }, + { + level: "log", + filename: /helper_serviceworker/, + arguments: ['fetch event: ' + SCOPE_FRAME_URL], + }, + { + level: "log", + filename: /helper_serviceworker/, + arguments: ['fetch event: ' + SCOPE_FRAME_URL2], + }, + { + level: "log", + filename: /helper_serviceworker/, + arguments: ['message event: ' + MESSAGE], + }, +]; +let consoleCalls = []; + +let startTest = Task.async(function*() { + removeEventListener("load", startTest); + + yield new Promise(resolve => { + SpecialPowers.pushPrefEnv({"set": [ + ["dom.serviceWorkers.enabled", true], + ["devtools.webconsole.filter.serviceworkers", true] + ]}, resolve); + }); + + attachConsoleToTab(["ConsoleAPI"], onAttach); +}); +addEventListener("load", startTest); + +let onAttach = Task.async(function*(state, response) { + onConsoleAPICall = onConsoleAPICall.bind(null, state); + state.dbgClient.addListener("consoleAPICall", onConsoleAPICall); + + let currentFrame; + try { + // First, we need a frame from which to register our script. This + // will not trigger any console calls. + info("Loading a non-scope frame from which to register a service worker."); + currentFrame = yield withFrame(NONSCOPE_FRAME_URL); + + // Now register the service worker and wait for it to become + // activate. This should trigger 3 console calls; 1 for script + // evaluation, 1 for the install event, and 1 for the activate + // event. These console calls are received because we called + // register(), not because we are in scope for the worker. + info("Registering the service worker"); + yield withActiveServiceWorker(currentFrame.contentWindow, + SERVICE_WORKER_URL, SCOPE); + ok(!currentFrame.contentWindow.navigator.serviceWorker.controller, + 'current frame should not be controlled'); + + // Now that the service worker is activate, lets navigate our frame. + // This will trigger 1 more console call for the fetch event. + info("Service worker registered. Navigating frame."); + yield navigateFrame(currentFrame, SCOPE_FRAME_URL); + ok(currentFrame.contentWindow.navigator.serviceWorker.controller, + 'navigated frame should be controlled'); + + // We now have a controlled frame. Lets perform a non-navigation fetch. + // This should produce another console call for the fetch event. + info("Frame navigated. Calling fetch()."); + yield currentFrame.contentWindow.fetch(SCOPE_FRAME_URL2); + + // Now force refresh our controlled frame. This will cause the frame + // to bypass the service worker and become an uncontrolled frame. It + // also happens to make the frame display a 404 message because the URL + // does not resolve to a real resource. This is ok, as we really only + // care about the frame being non-controlled, but still having a location + // that matches our service worker scope so we can provide its not + // incorrectly getting console calls. + info("Completed fetch(). Force refreshing to get uncontrolled frame."); + yield forceReloadFrame(currentFrame); + ok(!currentFrame.contentWindow.navigator.serviceWorker.controller, + 'current frame should not be controlled after force refresh'); + is(currentFrame.contentWindow.location.toString(), SCOPE_FRAME_URL, + 'current frame should still have in-scope location URL even though it got 404'); + + // Now postMessage() the service worker to trigger its message event + // handler. This will generate 1 or 2 to console.log() statements + // depending on if the worker thread needs to spin up again. Although we + // don't have a controlled or registering document in both cases, we still + // could get console calls since we only flush reports when the channel is + // finally destroyed. + info("Completed force refresh. Messaging service worker."); + yield messageServiceWorker(currentFrame.contentWindow, SCOPE, MESSAGE); + + info("Done messaging service worker. Unregistering service worker."); + yield unregisterServiceWorker(currentFrame.contentWindow); + + info('Service worker unregistered. Checking console calls.'); + state.dbgClient.removeListener("consoleAPICall", onConsoleAPICall); + checkConsoleAPICalls(consoleCalls, expectedConsoleCalls); + } catch(error) { + ok(false, 'unexpected error: ' + error); + } finally { + if (currentFrame) { + currentFrame.remove(); + currentFrame = null; + } + consoleCalls = []; + closeDebugger(state, function() { + SimpleTest.finish(); + }); + } +}); + +function onConsoleAPICall(state, type, packet) { + info("received message level: " + packet.message.level); + is(packet.from, state.actor, "console API call actor"); + consoleCalls.push(packet.message); +} +</script> +</body> +</html> |