gecko-dev/devtools/shared/webconsole/test/test_console_serviceworker.html

152 lines
5.8 KiB
HTML

<!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],
},
];
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. In either
// case, though, we should not get any console calls because we don't
// have a controlled or registering document.
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>