From 36d22d82aa202bb199967e9512281e9a53db42c9 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 21:33:14 +0200 Subject: Adding upstream version 115.7.0esr. Signed-off-by: Daniel Baumann --- .../client/application/test/browser/browser.ini | 80 ++++++++++++ ...owser_application_panel_debug-service-worker.js | 61 +++++++++ ...rowser_application_panel_list-domain-workers.js | 70 ++++++++++ ...anel_list-multiple-workers-same-registration.js | 64 +++++++++ ...owser_application_panel_list-several-workers.js | 54 ++++++++ ...browser_application_panel_list-single-worker.js | 64 +++++++++ .../browser_application_panel_list-unicode.js | 47 +++++++ ...browser_application_panel_list-workers-empty.js | 29 +++++ .../browser_application_panel_manifest-display.js | 145 +++++++++++++++++++++ .../browser_application_panel_manifest-load.js | 67 ++++++++++ ...browser_application_panel_manifest-open-json.js | 67 ++++++++++ .../browser_application_panel_manifest-reload.js | 51 ++++++++ .../browser_application_panel_open-links.js | 48 +++++++ .../browser/browser_application_panel_sidebar.js | 82 ++++++++++++ ...owser_application_panel_start-service-worker.js | 54 ++++++++ .../browser_application_panel_target-switching.js | 68 ++++++++++ ...ser_application_panel_telemetry-debug-worker.js | 49 +++++++ ...wser_application_panel_telemetry-select-page.js | 26 ++++ ...ser_application_panel_telemetry-start-worker.js | 45 +++++++ ...pplication_panel_telemetry-unregister-worker.js | 37 ++++++ .../browser_application_panel_unregister-worker.js | 36 +++++ ..._application_panel_viewsource-service-worker.js | 50 +++++++ .../browser_application_panel_worker-states.js | 62 +++++++++ devtools/client/application/test/browser/head.js | 134 +++++++++++++++++++ .../test/browser/resources/manifest/icon.svg | 4 + .../test/browser/resources/manifest/load-fail.html | 9 ++ .../resources/manifest/load-no-manifest.html | 8 ++ .../browser/resources/manifest/load-ok-icons.html | 9 ++ .../resources/manifest/load-ok-json-error.html | 10 ++ .../resources/manifest/load-ok-manifest-link.html | 9 ++ .../resources/manifest/load-ok-warnings.html | 10 ++ .../test/browser/resources/manifest/load-ok.html | 9 ++ .../test/browser/resources/manifest/manifest.json | 3 + .../service-workers/controlled-install-sw.js | 29 +++++ .../service-workers/controlled-install.html | 27 ++++ .../browser/resources/service-workers/debug-sw.js | 18 +++ .../browser/resources/service-workers/debug.html | 25 ++++ .../service-workers/dynamic-registration.html | 19 +++ .../browser/resources/service-workers/empty-sw.js | 4 + .../browser/resources/service-workers/empty.html | 11 ++ .../resources/service-workers/scope-page.html | 19 +++ .../resources/service-workers/simple-unicode.html | 15 +++ .../browser/resources/service-workers/simple.html | 32 +++++ 43 files changed, 1760 insertions(+) create mode 100644 devtools/client/application/test/browser/browser.ini create mode 100644 devtools/client/application/test/browser/browser_application_panel_debug-service-worker.js create mode 100644 devtools/client/application/test/browser/browser_application_panel_list-domain-workers.js create mode 100644 devtools/client/application/test/browser/browser_application_panel_list-multiple-workers-same-registration.js create mode 100644 devtools/client/application/test/browser/browser_application_panel_list-several-workers.js create mode 100644 devtools/client/application/test/browser/browser_application_panel_list-single-worker.js create mode 100644 devtools/client/application/test/browser/browser_application_panel_list-unicode.js create mode 100644 devtools/client/application/test/browser/browser_application_panel_list-workers-empty.js create mode 100644 devtools/client/application/test/browser/browser_application_panel_manifest-display.js create mode 100644 devtools/client/application/test/browser/browser_application_panel_manifest-load.js create mode 100644 devtools/client/application/test/browser/browser_application_panel_manifest-open-json.js create mode 100644 devtools/client/application/test/browser/browser_application_panel_manifest-reload.js create mode 100644 devtools/client/application/test/browser/browser_application_panel_open-links.js create mode 100644 devtools/client/application/test/browser/browser_application_panel_sidebar.js create mode 100644 devtools/client/application/test/browser/browser_application_panel_start-service-worker.js create mode 100644 devtools/client/application/test/browser/browser_application_panel_target-switching.js create mode 100644 devtools/client/application/test/browser/browser_application_panel_telemetry-debug-worker.js create mode 100644 devtools/client/application/test/browser/browser_application_panel_telemetry-select-page.js create mode 100644 devtools/client/application/test/browser/browser_application_panel_telemetry-start-worker.js create mode 100644 devtools/client/application/test/browser/browser_application_panel_telemetry-unregister-worker.js create mode 100644 devtools/client/application/test/browser/browser_application_panel_unregister-worker.js create mode 100644 devtools/client/application/test/browser/browser_application_panel_viewsource-service-worker.js create mode 100644 devtools/client/application/test/browser/browser_application_panel_worker-states.js create mode 100644 devtools/client/application/test/browser/head.js create mode 100644 devtools/client/application/test/browser/resources/manifest/icon.svg create mode 100644 devtools/client/application/test/browser/resources/manifest/load-fail.html create mode 100644 devtools/client/application/test/browser/resources/manifest/load-no-manifest.html create mode 100644 devtools/client/application/test/browser/resources/manifest/load-ok-icons.html create mode 100644 devtools/client/application/test/browser/resources/manifest/load-ok-json-error.html create mode 100644 devtools/client/application/test/browser/resources/manifest/load-ok-manifest-link.html create mode 100644 devtools/client/application/test/browser/resources/manifest/load-ok-warnings.html create mode 100644 devtools/client/application/test/browser/resources/manifest/load-ok.html create mode 100644 devtools/client/application/test/browser/resources/manifest/manifest.json create mode 100644 devtools/client/application/test/browser/resources/service-workers/controlled-install-sw.js create mode 100644 devtools/client/application/test/browser/resources/service-workers/controlled-install.html create mode 100644 devtools/client/application/test/browser/resources/service-workers/debug-sw.js create mode 100644 devtools/client/application/test/browser/resources/service-workers/debug.html create mode 100644 devtools/client/application/test/browser/resources/service-workers/dynamic-registration.html create mode 100644 devtools/client/application/test/browser/resources/service-workers/empty-sw.js create mode 100644 devtools/client/application/test/browser/resources/service-workers/empty.html create mode 100644 devtools/client/application/test/browser/resources/service-workers/scope-page.html create mode 100644 devtools/client/application/test/browser/resources/service-workers/simple-unicode.html create mode 100644 devtools/client/application/test/browser/resources/service-workers/simple.html (limited to 'devtools/client/application/test/browser') diff --git a/devtools/client/application/test/browser/browser.ini b/devtools/client/application/test/browser/browser.ini new file mode 100644 index 0000000000..4150959be4 --- /dev/null +++ b/devtools/client/application/test/browser/browser.ini @@ -0,0 +1,80 @@ +[DEFAULT] +tags = devtools +subsuite = devtools +support-files = + head.js + resources/manifest/icon.svg + resources/manifest/load-fail.html + resources/manifest/load-no-manifest.html + resources/manifest/load-ok-icons.html + resources/manifest/load-ok-json-error.html + resources/manifest/load-ok-manifest-link.html + resources/manifest/load-ok-warnings.html + resources/manifest/load-ok.html + resources/manifest/manifest.json + resources/service-workers/controlled-install-sw.js + resources/service-workers/controlled-install.html + resources/service-workers/debug-sw.js + resources/service-workers/debug.html + resources/service-workers/dynamic-registration.html + resources/service-workers/empty.html + resources/service-workers/empty-sw.js + resources/service-workers/scope-page.html + resources/service-workers/simple.html + resources/service-workers/simple-unicode.html + !/devtools/client/debugger/test/mochitest/shared-head.js + !/devtools/client/shared/test/shared-head.js + !/devtools/client/shared/test/telemetry-test-helpers.js + +# Worker-related tests +[browser_application_panel_debug-service-worker.js] +skip-if = debug || asan || !serviceworker_e10s # Bug 1559591, 1575578, 1588154 +[browser_application_panel_list-domain-workers.js] +https_first_disabled = true +skip-if = debug # Bug 1559591 +[browser_application_panel_list-multiple-workers-same-registration.js] +https_first_disabled = true +skip-if = debug # Bug 1559591 +[browser_application_panel_list-several-workers.js] +https_first_disabled = true +skip-if = debug # Bug 1559591 +[browser_application_panel_list-single-worker.js] +https_first_disabled = true +skip-if = debug # Bug 1559591 +[browser_application_panel_start-service-worker.js] +skip-if = asan || debug || !serviceworker_e10s || tsan # Bug 1559487, 1559591, 1608640 +[browser_application_panel_list-workers-empty.js] +[browser_application_panel_list-unicode.js] +skip-if = debug # Bug 1559591 +[browser_application_panel_unregister-worker.js] +skip-if = debug # Bug 1559591 +[browser_application_panel_viewsource-service-worker.js] +https_first_disabled = true +skip-if = debug || asan || !serviceworker_e10s # Bug 1559591, 1575578, 1588154 +[browser_application_panel_worker-states.js] +skip-if = asan || debug || !serviceworker_e10s # Bug 1559487, 1559591, 1608640 +# Manifest-related tests +[browser_application_panel_manifest-display.js] +[browser_application_panel_manifest-load.js] +[browser_application_panel_manifest-open-json.js] +https_first_disabled = true +[browser_application_panel_manifest-reload.js] +https_first_disabled = true +# Telemetry tests +[browser_application_panel_telemetry-debug-worker.js] +https_first_disabled = true +skip-if = + asan || debug || !serviceworker_e10s # Bug 1559487, 1559591, 1608640 + os == 'linux' && bits == 64 && !debug # Bug 1654354 +[browser_application_panel_telemetry-select-page.js] +[browser_application_panel_telemetry-start-worker.js] +skip-if = ccov || asan || debug || !serviceworker_e10s || tsan # Bug 1559487, 1559591, 1608640, 1654468 +[browser_application_panel_telemetry-unregister-worker.js] +skip-if = asan || debug || !serviceworker_e10s # Bug 1559487, 1559591, 1608640 +# Misc tests +[browser_application_panel_open-links.js] +skip-if = true # Bug 1467256, 1559591 +[browser_application_panel_sidebar.js] +[browser_application_panel_target-switching.js] +https_first_disabled = true +skip-if = (os == 'win') || (os == 'linux') # Bug 1640234 diff --git a/devtools/client/application/test/browser/browser_application_panel_debug-service-worker.js b/devtools/client/application/test/browser/browser_application_panel_debug-service-worker.js new file mode 100644 index 0000000000..57dd000edb --- /dev/null +++ b/devtools/client/application/test/browser/browser_application_panel_debug-service-worker.js @@ -0,0 +1,61 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +Services.scriptloader.loadSubScript( + "chrome://mochitests/content/browser/devtools/client/debugger/test/mochitest/shared-head.js", + this +); + +const TAB_URL = URL_ROOT + "resources/service-workers/debug.html"; + +add_task(async function () { + await enableApplicationPanel(); + + const { panel, tab, toolbox, commands } = await openNewTabAndApplicationPanel( + TAB_URL + ); + + const doc = panel.panelWin.document; + + selectPage(panel, "service-workers"); + + info("Wait until the service worker appears in the application panel"); + await waitUntil(() => getWorkerContainers(doc).length === 1); + + const container = getWorkerContainers(doc)[0]; + info("Wait until the inspect link is displayed"); + await waitUntil(() => { + return container.querySelector(".js-inspect-link"); + }); + + info("Click on the inspect link and wait for debugger to be ready"); + const debugLink = container.querySelector(".js-inspect-link"); + debugLink.click(); + await waitFor(() => toolbox.getPanel("jsdebugger")); + + // add a breakpoint at line 11 + const debuggerContext = createDebuggerContext(toolbox); + await waitForLoadedSource(debuggerContext, "debug-sw.js"); + await addBreakpoint(debuggerContext, "debug-sw.js", 11); + + // force a pause at the breakpoint + info("Invoke fetch, expect the service worker script to pause on line 11"); + await ContentTask.spawn(tab.linkedBrowser, {}, async function () { + content.wrappedJSObject.fetchFromWorker(); + }); + await waitForPaused(debuggerContext); + const workerScript = findSource(debuggerContext, "debug-sw.js"); + assertPausedAtSourceAndLine(debuggerContext, workerScript.id, 11); + await resume(debuggerContext); + + // remove breakpoint + await removeBreakpoint(debuggerContext, workerScript.id, 11); + + await unregisterAllWorkers(commands.client, doc); + + // close the tab + info("Closing the tab."); + await BrowserTestUtils.removeTab(tab); +}); diff --git a/devtools/client/application/test/browser/browser_application_panel_list-domain-workers.js b/devtools/client/application/test/browser/browser_application_panel_list-domain-workers.js new file mode 100644 index 0000000000..ccb0884d0e --- /dev/null +++ b/devtools/client/application/test/browser/browser_application_panel_list-domain-workers.js @@ -0,0 +1,70 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * Check that the application panel only displays service workers from the + * current domain. + */ + +const SIMPLE_URL = URL_ROOT + "resources/service-workers/simple.html"; +const OTHER_URL = SIMPLE_URL.replace("example.com", "test1.example.com"); +const EMPTY_URL = (URL_ROOT + "resources/service-workers/empty.html").replace( + "example.com", + "test2.example.com" +); + +add_task(async function () { + await enableApplicationPanel(); + + const { panel, commands, tab } = await openNewTabAndApplicationPanel( + SIMPLE_URL + ); + const doc = panel.panelWin.document; + + selectPage(panel, "service-workers"); + + info("Wait until the service worker appears in the application panel"); + await waitUntil(() => getWorkerContainers(doc).length === 1); + + let scopeEl = getWorkerContainers(doc)[0].querySelector(".js-sw-scope"); + ok( + scopeEl.textContent.startsWith("example.com"), + "First service worker registration is displayed for the correct domain" + ); + + info( + "Navigate to another page for a different domain with no service worker" + ); + + await navigateTo(EMPTY_URL); + info("Wait until the service worker list is updated"); + await waitUntil( + () => doc.querySelector(".js-registration-list-empty") !== null + ); + ok( + true, + "No service workers are shown for an empty page in a different domain." + ); + + info( + "Navigate to another page for a different domain with another service worker" + ); + await navigateTo(OTHER_URL); + + info("Wait until the service worker appears in the application panel"); + await waitUntil(() => getWorkerContainers(doc).length === 1); + + scopeEl = getWorkerContainers(doc)[0].querySelector(".js-sw-scope"); + ok( + scopeEl.textContent.startsWith("test1.example.com"), + "Second service worker registration is displayed for the correct domain" + ); + + await unregisterAllWorkers(commands.client, doc); + + // close the tab + info("Closing the tab."); + await BrowserTestUtils.removeTab(tab); +}); diff --git a/devtools/client/application/test/browser/browser_application_panel_list-multiple-workers-same-registration.js b/devtools/client/application/test/browser/browser_application_panel_list-multiple-workers-same-registration.js new file mode 100644 index 0000000000..8e117927d1 --- /dev/null +++ b/devtools/client/application/test/browser/browser_application_panel_list-multiple-workers-same-registration.js @@ -0,0 +1,64 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +const WORKER1_URL = URL_ROOT + "resources/service-workers/simple.html"; +const WORKER2_URL = URL_ROOT + "resources/service-workers/debug.html"; + +add_task(async function () { + await enableApplicationPanel(); + + await openTabAndWaitForWorker(WORKER1_URL); + const { panel, tab, commands } = await openTabAndWaitForWorker(WORKER2_URL); + + const doc = panel.panelWin.document; + + let registrationContainer = getWorkerContainers(doc)[0]; + + info("Wait until the unregister button is displayed for the registration"); + await waitUntil(() => { + registrationContainer = getWorkerContainers(doc)[0]; + return registrationContainer.querySelector(".js-unregister-button"); + }); + + const scopeEl = registrationContainer.querySelector(".js-sw-scope"); + const expectedScope = + "example.com/browser/devtools/client/application/test/" + + "browser/resources/service-workers"; + ok( + scopeEl.textContent.startsWith(expectedScope), + "Registration has the expected scope" + ); + + // check the workers data + // note that the worker from WORKER2_URL will appear second in the list with + // the "installed" state + info("Check the workers data for this registration"); + const workers = registrationContainer.querySelectorAll(".js-sw-worker"); + is(workers.length, 2, "Registration has two workers"); + // check url for worker from WORKER1_URL + const url1El = workers[0].querySelector(".js-source-url"); + is(url1El.textContent, "empty-sw.js", "First worker has correct URL"); + // check url for worker from WORKER2_URL + const url2El = workers[1].querySelector(".js-source-url"); + is(url2El.textContent, "debug-sw.js", "Second worker has correct URL"); + + await unregisterAllWorkers(commands.client, doc); + + // close the tab + info("Closing the tab."); + await BrowserTestUtils.removeTab(tab); +}); + +async function openTabAndWaitForWorker(url) { + const { panel, commands, tab } = await openNewTabAndApplicationPanel(url); + const doc = panel.panelWin.document; + + selectPage(panel, "service-workers"); + + info("Wait until the service worker appears in the application panel"); + await waitUntil(() => getWorkerContainers(doc).length === 1); + + return { panel, commands, tab }; +} diff --git a/devtools/client/application/test/browser/browser_application_panel_list-several-workers.js b/devtools/client/application/test/browser/browser_application_panel_list-several-workers.js new file mode 100644 index 0000000000..4e1295082e --- /dev/null +++ b/devtools/client/application/test/browser/browser_application_panel_list-several-workers.js @@ -0,0 +1,54 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * Check that the application panel can display several service workers applying to the + * same domain. + */ + +const SIMPLE_URL = URL_ROOT + "resources/service-workers/simple.html"; +const OTHER_SCOPE_URL = URL_ROOT + "resources/service-workers/scope-page.html"; + +add_task(async function () { + await enableApplicationPanel(); + + const { panel, commands, tab } = await openNewTabAndApplicationPanel( + SIMPLE_URL + ); + const doc = panel.panelWin.document; + + selectPage(panel, "service-workers"); + + info("Wait until the service worker appears in the application panel"); + await waitUntil(() => getWorkerContainers(doc).length === 1); + + info("Wait until the unregister button is displayed for the service worker"); + await waitUntil(() => + getWorkerContainers(doc)[0].querySelector(".js-unregister-button") + ); + + ok(true, "First service worker registration is displayed"); + + info( + "Navigate to another page for the same domain with another service worker" + ); + await navigateTo(OTHER_SCOPE_URL); + + info("Wait until the service worker appears in the application panel"); + await waitUntil(() => getWorkerContainers(doc).length === 2); + + info("Wait until the unregister button is displayed for the service worker"); + await waitUntil(() => + getWorkerContainers(doc)[1].querySelector(".js-unregister-button") + ); + + ok(true, "Second service worker registration is displayed"); + + await unregisterAllWorkers(commands.client, doc); + + // close the tab + info("Closing the tab."); + await BrowserTestUtils.removeTab(tab); +}); diff --git a/devtools/client/application/test/browser/browser_application_panel_list-single-worker.js b/devtools/client/application/test/browser/browser_application_panel_list-single-worker.js new file mode 100644 index 0000000000..74cab13bf6 --- /dev/null +++ b/devtools/client/application/test/browser/browser_application_panel_list-single-worker.js @@ -0,0 +1,64 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +const TAB_URL = + URL_ROOT + "resources/service-workers/dynamic-registration.html"; + +add_task(async function () { + await enableApplicationPanel(); + + const { panel, tab } = await openNewTabAndApplicationPanel(TAB_URL); + const doc = panel.panelWin.document; + + selectPage(panel, "service-workers"); + + info("Check for non-existing service worker"); + const isWorkerListEmpty = !!doc.querySelector(".js-registration-list-empty"); + ok(isWorkerListEmpty, "No Service Worker displayed"); + + info("Register a service worker in the page."); + await SpecialPowers.spawn(tab.linkedBrowser, [], async function () { + content.wrappedJSObject.registerServiceWorker(); + }); + + info("Wait until the service worker appears in the application panel"); + await waitUntil(() => !!getWorkerContainers(doc).length); + + let workerContainer = getWorkerContainers(doc)[0]; + + info("Wait until the unregister button is displayed for the service worker"); + await waitUntil(() => { + workerContainer = getWorkerContainers(doc)[0]; + return workerContainer.querySelector(".js-unregister-button"); + }); + + const scopeEl = workerContainer.querySelector(".js-sw-scope"); + const expectedScope = + "example.com/browser/devtools/client/application/test/" + + "browser/resources/service-workers"; + ok( + scopeEl.textContent.startsWith(expectedScope), + "Service worker has the expected scope" + ); + + const updatedEl = workerContainer.querySelector(".js-sw-updated"); + ok( + updatedEl.textContent.includes(`${new Date().getFullYear()}`), + "Service worker has a last updated time" + ); + + info("Unregister the service worker"); + await SpecialPowers.spawn(tab.linkedBrowser, [], async function () { + const registration = await content.wrappedJSObject.sw; + registration.unregister(); + }); + + info("Wait until the service worker is removed from the application panel"); + await waitUntil(() => getWorkerContainers(doc).length === 0); + + // close the tab + info("Closing the tab."); + await BrowserTestUtils.removeTab(tab); +}); diff --git a/devtools/client/application/test/browser/browser_application_panel_list-unicode.js b/devtools/client/application/test/browser/browser_application_panel_list-unicode.js new file mode 100644 index 0000000000..c747fa9ae3 --- /dev/null +++ b/devtools/client/application/test/browser/browser_application_panel_list-unicode.js @@ -0,0 +1,47 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +const TAB_URL = ( + URL_ROOT + "resources/service-workers/simple-unicode.html" +).replace("example.com", "xn--hxajbheg2az3al.xn--jxalpdlp"); + +/** + * Check that the application panel displays filenames and URL's in human-readable, + * Unicode characters, and not encoded URI's or punycode. + */ + +add_task(async function () { + await enableApplicationPanel(); + + const { panel, tab, commands } = await openNewTabAndApplicationPanel(TAB_URL); + const doc = panel.panelWin.document; + + selectPage(panel, "service-workers"); + + info("Wait until the service worker appears in the application panel"); + await waitUntil(() => getWorkerContainers(doc).length === 1); + + const workerContainer = getWorkerContainers(doc)[0]; + + const scopeEl = workerContainer.querySelector(".js-sw-scope"); + ok( + scopeEl.textContent.startsWith( + "\u03C0\u03B1\u03C1\u03AC\u03B4\u03B5\u03B9\u03B3\u03BC\u03B1." + + "\u03B4\u03BF\u03BA\u03B9\u03BC\u03AE" + ), + "Service worker has the expected Unicode scope" + ); + const urlEl = workerContainer.querySelector(".js-source-url"); + ok( + urlEl.textContent.endsWith("\u65E5\u672C"), + "Service worker has the expected Unicode url" + ); + + await unregisterAllWorkers(commands.client, doc); + + // close the tab + info("Closing the tab."); + await BrowserTestUtils.removeTab(tab); +}); diff --git a/devtools/client/application/test/browser/browser_application_panel_list-workers-empty.js b/devtools/client/application/test/browser/browser_application_panel_list-workers-empty.js new file mode 100644 index 0000000000..1bb75d2999 --- /dev/null +++ b/devtools/client/application/test/browser/browser_application_panel_list-workers-empty.js @@ -0,0 +1,29 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * Check that the application panel only displays service workers from the + * current domain. + */ + +const EMPTY_URL = URL_ROOT + "resources/service-workers/empty.html"; + +add_task(async function () { + await enableApplicationPanel(); + + const { panel, tab } = await openNewTabAndApplicationPanel(EMPTY_URL); + const doc = panel.panelWin.document; + + selectPage(panel, "service-workers"); + + await waitUntil( + () => doc.querySelector(".js-registration-list-empty") !== null + ); + ok(true, "No service workers are shown for an empty page"); + + // close the tab + info("Closing the tab."); + await BrowserTestUtils.removeTab(tab); +}); diff --git a/devtools/client/application/test/browser/browser_application_panel_manifest-display.js b/devtools/client/application/test/browser/browser_application_panel_manifest-display.js new file mode 100644 index 0000000000..714fcc276e --- /dev/null +++ b/devtools/client/application/test/browser/browser_application_panel_manifest-display.js @@ -0,0 +1,145 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * Check that the manifest is being properly shown + */ + +add_task(async function () { + info("Test that we are displaying correctly a valid manifest"); + const url = URL_ROOT + "resources/manifest/load-ok.html"; + + await enableApplicationPanel(); + const { panel, tab } = await openNewTabAndApplicationPanel(url); + const doc = panel.panelWin.document; + + selectPage(panel, "manifest"); + + info("Waiting for the manifest to be displayed"); + await waitUntil(() => doc.querySelector(".js-manifest") !== null); + ok(true, "Manifest is being displayed"); + + // assert manifest members are being properly displayed + checkManifestMember(doc, "name", "Foo"); + checkManifestMember(doc, "background_color", "#ff0000"); + + ok( + doc.querySelector(".js-manifest-issues") === null, + "No validation issues are being displayed" + ); + + // close the tab + info("Closing the tab."); + await BrowserTestUtils.removeTab(tab); +}); + +add_task(async function () { + info( + "Test that we are displaying correctly a manifest with validation warnings" + ); + const url = URL_ROOT + "resources/manifest/load-ok-warnings.html"; + + await enableApplicationPanel(); + const { panel, tab } = await openNewTabAndApplicationPanel(url); + const doc = panel.panelWin.document; + + selectPage(panel, "manifest"); + + info("Waiting for the manifest to be displayed"); + await waitUntil(() => doc.querySelector(".js-manifest") !== null); + ok(true, "Manifest is being displayed"); + + // assert manifest members are being properly displayed + checkManifestMember(doc, "name", "Foo"); + checkManifestMember(doc, "background_color", ""); + + const issuesEl = doc.querySelector(".js-manifest-issues"); + ok(issuesEl !== null, "Validation issues are displayed"); + + const warningEl = [...issuesEl.querySelectorAll(".js-manifest-issue")].find( + x => x.textContent.includes("background_color") + ); + ok(warningEl !== null, "A warning about background_color is displayed"); + + // close the tab + info("Closing the tab."); + await BrowserTestUtils.removeTab(tab); +}); + +add_task(async function () { + info("Test that we are displaying correctly a manifest with JSON errors"); + const url = URL_ROOT + "resources/manifest/load-ok-json-error.html"; + + await enableApplicationPanel(); + const { panel, tab } = await openNewTabAndApplicationPanel(url); + const doc = panel.panelWin.document; + + selectPage(panel, "manifest"); + + info("Waiting for the manifest to be displayed"); + await waitUntil(() => doc.querySelector(".js-manifest") !== null); + ok(true, "Manifest is being displayed"); + + const issuesEl = doc.querySelector(".js-manifest-issues"); + ok(issuesEl !== null, "Validation issues are displayed"); + + const errorEl = [...issuesEl.querySelectorAll(".js-manifest-issue")].find(x => + x.textContent.includes("JSON") + ); + ok(errorEl !== null, "An error about JSON parsing is displayed"); + + // close the tab + info("Closing the tab."); + await BrowserTestUtils.removeTab(tab); +}); + +add_task(async function () { + info("Test that we are displaying correctly a manifest with icons"); + const url = URL_ROOT + "resources/manifest/load-ok-icons.html"; + + await enableApplicationPanel(); + const { panel, tab } = await openNewTabAndApplicationPanel(url); + const doc = panel.panelWin.document; + + selectPage(panel, "manifest"); + + info("Waiting for the manifest to be displayed"); + await waitUntil(() => doc.querySelector(".js-manifest") !== null); + ok(true, "Manifest is being displayed"); + + // assert manifest icon is being displayed + const iconEl = findMemberByLabel(doc, "128x128image/svg"); + ok(iconEl !== null, "Icon label is being displayed with size and image type"); + const imgEl = iconEl.querySelector(".js-manifest-item-content img"); + ok(imgEl !== null, "An image is displayed for the icon"); + is( + imgEl.src, + URL_ROOT + "resources/manifest/icon.svg", + "The icon image has the the icon url as source" + ); + const iconTextContent = iconEl.querySelector( + ".js-manifest-item-content" + ).textContent; + ok(iconTextContent.includes("any"), "Purpose is being displayed"); + + // close the tab + info("Closing the tab."); + await BrowserTestUtils.removeTab(tab); +}); + +function findMemberByLabel(doc, member) { + return [...doc.querySelectorAll(".js-manifest-item")].find(x => + x.querySelector(".js-manifest-item-label").textContent.startsWith(member) + ); +} + +function checkManifestMember(doc, member, expectedValue) { + const itemEl = findMemberByLabel(doc, member); + is( + itemEl.querySelector(".js-manifest-item-content").textContent, + expectedValue, + `Manifest member ${member} displays the correct value` + ); +} diff --git a/devtools/client/application/test/browser/browser_application_panel_manifest-load.js b/devtools/client/application/test/browser/browser_application_panel_manifest-load.js new file mode 100644 index 0000000000..dd89fbc1a6 --- /dev/null +++ b/devtools/client/application/test/browser/browser_application_panel_manifest-load.js @@ -0,0 +1,67 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * Check that the application panel fetches a manifest when in the Manifest Page + */ + +add_task(async function () { + info("Test that manifest page loads the manifest successfully"); + const url = URL_ROOT + "resources/manifest/load-ok.html"; + + await enableApplicationPanel(); + const { panel, tab } = await openNewTabAndApplicationPanel(url); + const doc = panel.panelWin.document; + + selectPage(panel, "manifest"); + + info("Waiting for the manifest to load"); + await waitUntil(() => doc.querySelector(".js-manifest") !== null); + ok(true, "Manifest loaded successfully"); + + // close the tab + info("Closing the tab."); + await BrowserTestUtils.removeTab(tab); +}); + +add_task(async function () { + info("Test that manifest page shows an error when failing to load"); + const url = URL_ROOT + "resources/manifest/load-fail.html"; + + await enableApplicationPanel(); + const { panel, tab } = await openNewTabAndApplicationPanel(url); + const doc = panel.panelWin.document; + + selectPage(panel, "manifest"); + + info("Waiting for the manifest to fail to load"); + await waitUntil( + () => doc.querySelector(".js-manifest-loaded-error") !== null + ); + ok(true, "Manifest page displays loading error"); + + // close the tab + info("Closing the tab."); + await BrowserTestUtils.removeTab(tab); +}); + +add_task(async function () { + info("Test that manifest page shows a message when there is no manifest"); + const url = URL_ROOT + "resources/manifest/load-no-manifest.html"; + + await enableApplicationPanel(); + const { panel, tab } = await openNewTabAndApplicationPanel(url); + const doc = panel.panelWin.document; + + selectPage(panel, "manifest"); + + info("Waiting for the 'no manifest' message to appear"); + await waitUntil(() => doc.querySelector(".js-manifest-empty") !== null); + ok(true, "Manifest page displays a 'no manifest' message"); + + // close the tab + info("Closing the tab."); + await BrowserTestUtils.removeTab(tab); +}); diff --git a/devtools/client/application/test/browser/browser_application_panel_manifest-open-json.js b/devtools/client/application/test/browser/browser_application_panel_manifest-open-json.js new file mode 100644 index 0000000000..7869502d4b --- /dev/null +++ b/devtools/client/application/test/browser/browser_application_panel_manifest-open-json.js @@ -0,0 +1,67 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * Check that the application panel fetches a manifest when in the Manifest Page + */ + +add_task(async function () { + info("Test that manifest page has a link that opens the manifest JSON file"); + const url = URL_ROOT_SSL + "resources/manifest/load-ok-manifest-link.html"; + const manifestUrl = URL_ROOT_SSL + "resources/manifest/manifest.json"; + + await enableApplicationPanel(); + const { panel, tab } = await openNewTabAndApplicationPanel(url); + const doc = panel.panelWin.document; + + selectPage(panel, "manifest"); + + info("Waiting for the manifest JSON link"); + await waitUntil(() => doc.querySelector(".js-manifest-json-link") !== null); + ok(true, "Link to JSON is displayed"); + + info("Click on link and wait till the JSON is opened in a new tab"); + // click on the link and wait for the new tab to open + const onTabLoaded = BrowserTestUtils.waitForNewTab( + gBrowser, + `${manifestUrl}` + ); + const link = doc.querySelector(".js-manifest-json-link"); + link.click(); + const jsonTab = await onTabLoaded; + ok(jsonTab, "The manifest JSON was opened in a new tab"); + + // close the tabs + info("Closing the page tab."); + await BrowserTestUtils.removeTab(tab); + info("Closing the manifest JSON tab."); + await BrowserTestUtils.removeTab(jsonTab); +}); + +add_task(async function () { + info( + "Test that manifest page does not show a link for manifests embedded in a data url" + ); + const url = URL_ROOT_SSL + "resources/manifest/load-ok.html"; + + await enableApplicationPanel(); + const { panel, tab } = await openNewTabAndApplicationPanel(url); + const doc = panel.panelWin.document; + + selectPage(panel, "manifest"); + + info("Waiting for the manifest to load"); + await waitUntil(() => doc.querySelector(".js-manifest") !== null); + ok(true, "Manifest loaded successfully"); + is( + doc.querySelector(".js-manifest-json-link"), + null, + "No JSON link is shown" + ); + + // close tab + info("Closing the tab"); + await BrowserTestUtils.removeTab(tab); +}); diff --git a/devtools/client/application/test/browser/browser_application_panel_manifest-reload.js b/devtools/client/application/test/browser/browser_application_panel_manifest-reload.js new file mode 100644 index 0000000000..4b8ab50985 --- /dev/null +++ b/devtools/client/application/test/browser/browser_application_panel_manifest-reload.js @@ -0,0 +1,51 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * Check that the application panel refetches the page manifest when reloading + * or navigating to a new page + */ + +add_task(async function () { + await enableApplicationPanel(); + + info("Loading a page with no manifest"); + let url = URL_ROOT_SSL + "resources/manifest/load-no-manifest.html"; + const { panel, tab } = await openNewTabAndApplicationPanel(url); + const doc = panel.panelWin.document; + + selectPage(panel, "manifest"); + + info("Waiting for the 'no manifest' message to appear"); + await waitFor(() => doc.querySelector(".js-manifest-empty") !== null); + ok(true, "Manifest page displays a 'no manifest' message"); + + info("Navigating to a page with a manifest"); + url = URL_ROOT_SSL + "resources/manifest/load-ok.html"; + await navigateTo(url); + + info("Waiting for the manifest to show up"); + await waitFor(() => doc.querySelector(".js-manifest") !== null); + ok(true, "Manifest displayed successfully"); + + info("Navigating to a page with a manifest that fails to load"); + url = URL_ROOT_SSL + "resources/manifest/load-fail.html"; + await navigateTo(url); + + info("Waiting for the manifest to fail to load"); + await waitFor(() => doc.querySelector(".js-manifest-loaded-error") !== null); + ok(true, "Manifest page displays loading error"); + + info("Reloading"); + await navigateTo(url); + + info("Waiting for the manifest to fail to load"); + await waitFor(() => doc.querySelector(".js-manifest-loaded-error") !== null); + ok(true, "Manifest page displays loading error"); + + // close the tab + info("Closing the tab."); + await BrowserTestUtils.removeTab(tab); +}); diff --git a/devtools/client/application/test/browser/browser_application_panel_open-links.js b/devtools/client/application/test/browser/browser_application_panel_open-links.js new file mode 100644 index 0000000000..d654873827 --- /dev/null +++ b/devtools/client/application/test/browser/browser_application_panel_open-links.js @@ -0,0 +1,48 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +const { Toolbox } = require("resource://devtools/client/framework/toolbox.js"); + +/** + * Check that links work when the devtools are detached in a separate window. + */ + +const TAB_URL = URL_ROOT + "resources/service-workers/empty.html"; + +add_task(async function () { + await enableApplicationPanel(); + + const { panel, toolbox } = await openNewTabAndApplicationPanel(TAB_URL); + const doc = panel.panelWin.document; + + selectPage(panel, "service-workers"); + + // detach devtools in a separate window + await toolbox.switchHost(Toolbox.HostType.WINDOW); + + // click on the link and wait for the new tab to open + const onTabLoaded = BrowserTestUtils.waitForNewTab( + gBrowser, + "about:debugging#workers", + true + ); + doc.querySelector(".js-trusted-link").click(); + info("Opening link in a new tab."); + const newTab = await onTabLoaded; + + // We only need to check that newTab is truthy since + // BrowserTestUtils.waitForNewTab checks the URL. + ok(newTab, "The expected tab was opened."); + + info("Wait until the main about debugging container is available"); + await waitUntil(() => { + const aboutDebuggingDoc = newTab.linkedBrowser.contentDocument; + return aboutDebuggingDoc.querySelector(".app"); + }); + + // close the tab + info("Closing the tab."); + await BrowserTestUtils.removeTab(newTab); +}); diff --git a/devtools/client/application/test/browser/browser_application_panel_sidebar.js b/devtools/client/application/test/browser/browser_application_panel_sidebar.js new file mode 100644 index 0000000000..80b2fbfe09 --- /dev/null +++ b/devtools/client/application/test/browser/browser_application_panel_sidebar.js @@ -0,0 +1,82 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * Check that the manifest is being properly shown + */ + +add_task(async function () { + info("Test that we are displaying correctly the sidebar"); + + await enableApplicationPanel(); + const { panel, tab, commands } = await openNewTabAndApplicationPanel(); + const doc = panel.panelWin.document; + + info("Waiting for the sidebar to be displayed"); + await waitUntil(() => doc.querySelector(".js-sidebar") !== null); + ok(true, "Sidebar is being displayed"); + + await waitUntil(() => doc.querySelector(".js-service-workers-page") !== null); + ok(true, "Service Workers page was loaded per default."); + + // close the tab + info("Closing the tab."); + await commands.client.waitForRequestsToSettle(); + await BrowserTestUtils.removeTab(tab); +}); + +add_task(async function () { + info("Test that we are displaying correctly the selected page - manifest"); + + await enableApplicationPanel(); + const { panel, tab, commands } = await openNewTabAndApplicationPanel(); + const doc = panel.panelWin.document; + + info("Select service worker page"); + selectPage(panel, "service-workers"); + await waitUntil(() => doc.querySelector(".js-service-workers-page") !== null); + await unregisterAllWorkers(commands.client, doc); + + info("Select manifest page in the sidebar"); + const link = doc.querySelector(".js-sidebar-manifest"); + link.click(); + + await waitUntil(() => doc.querySelector(".js-manifest-page") !== null); + ok(true, "Manifest page was selected."); + + // close the tab + info("Closing the tab."); + await commands.client.waitForRequestsToSettle(); + await BrowserTestUtils.removeTab(tab); +}); + +add_task(async function () { + info( + "Test that we are displaying correctly the selected page - service workers" + ); + const url = URL_ROOT + "resources/manifest/load-ok.html"; + + await enableApplicationPanel(); + const { panel, tab, commands } = await openNewTabAndApplicationPanel(url); + const doc = panel.panelWin.document; + + selectPage(panel, "manifest"); + + info("Waiting for the manifest to load"); + await waitUntil(() => doc.querySelector(".js-manifest-page") !== null); + ok(true, "Manifest page was selected."); + + info("Select service worker page in the sidebar"); + const link = doc.querySelector(".js-sidebar-service-workers"); + link.click(); + + await waitUntil(() => doc.querySelector(".js-service-workers-page") !== null); + ok(true, "Service workers page was selected."); + + // close the tab + info("Closing the tab."); + await commands.client.waitForRequestsToSettle(); + await BrowserTestUtils.removeTab(tab); +}); diff --git a/devtools/client/application/test/browser/browser_application_panel_start-service-worker.js b/devtools/client/application/test/browser/browser_application_panel_start-service-worker.js new file mode 100644 index 0000000000..1070f0f5af --- /dev/null +++ b/devtools/client/application/test/browser/browser_application_panel_start-service-worker.js @@ -0,0 +1,54 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +const TAB_URL = URL_ROOT + "resources/service-workers/simple.html"; + +/** + * Tests that the Start button works for service workers who can be debugged + */ +add_task(async function () { + await enableApplicationPanel(); // this also enables SW debugging + + // Setting a low idle_timeout and idle_extended_timeout will allow the service worker + // to reach the STOPPED state quickly, which will allow us to test the start button. + // The default value is 30000 milliseconds. + info("Set a low service worker idle timeout"); + await pushPref("dom.serviceWorkers.idle_timeout", 1000); + await pushPref("dom.serviceWorkers.idle_extended_timeout", 1000); + + const { panel, tab, commands } = await openNewTabAndApplicationPanel(TAB_URL); + const doc = panel.panelWin.document; + + selectPage(panel, "service-workers"); + + await waitForWorkerRegistration(tab); + + info("Wait until the service worker appears in the application panel"); + await waitUntil(() => getWorkerContainers(doc).length === 1); + + info("Wait until the start button is displayed and enabled"); + const container = getWorkerContainers(doc)[0]; + await waitUntil(() => { + const button = container.querySelector(".js-start-button"); + return button && !button.disabled; + }); + + info("Click the button and wait for the worker to start"); + const button = container.querySelector(".js-start-button"); + button.click(); + + info("Wait until status 'Running' is displayed"); + await waitUntil(() => { + const statusEl = container.querySelector(".js-worker-status"); + return statusEl && statusEl.textContent === "Running"; + }); + ok(true, "Worker status is 'Running'"); + + await unregisterAllWorkers(commands.client, doc); + + // close the tab + info("Closing the tab."); + await BrowserTestUtils.removeTab(tab); +}); diff --git a/devtools/client/application/test/browser/browser_application_panel_target-switching.js b/devtools/client/application/test/browser/browser_application_panel_target-switching.js new file mode 100644 index 0000000000..ff8d521e30 --- /dev/null +++ b/devtools/client/application/test/browser/browser_application_panel_target-switching.js @@ -0,0 +1,68 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ +"use strict"; + +// Test switching for the top-level target. + +// We use about:robots, because this page will run in the parent process. +// Navigating from about:robots to a regular content page will always trigger +// a target switch, with or without fission. +const PARENT_PROCESS_URI = "about:robots"; +const CONTENT_PROCESS_URI_WORKERS = + URL_ROOT + "resources/service-workers/simple.html"; +const CONTENT_PROCESS_URI_MANIFEST = + URL_ROOT + "resources/manifest/load-ok.html"; + +// test workers when target switching +add_task(async function () { + await enableApplicationPanel(); + + info("Open a page that runs in the parent process"); + const { panel, commands, tab } = await openNewTabAndApplicationPanel( + PARENT_PROCESS_URI + ); + const doc = panel.panelWin.document; + + info("Check for non-existing service worker"); + selectPage(panel, "service-workers"); + const isWorkerListEmpty = !!doc.querySelector(".js-registration-list-empty"); + ok(isWorkerListEmpty, "No Service Worker displayed"); + + info("Navigate to a page that runs in the child process"); + await navigateTo(CONTENT_PROCESS_URI_WORKERS); + + info("Wait until the service worker appears in the application panel"); + await waitUntil(() => getWorkerContainers(doc).length === 1); + + // close the tab + info("Closing the tab."); + await unregisterAllWorkers(commands.client, doc); + await BrowserTestUtils.removeTab(tab); +}); + +// test manifest when target switching +add_task(async function () { + await enableApplicationPanel(); + + info("Open a page that runs in the parent process"); + const { panel, tab } = await openNewTabAndApplicationPanel( + PARENT_PROCESS_URI + ); + const doc = panel.panelWin.document; + + info("Waiting for the 'no manifest' message to appear"); + selectPage(panel, "manifest"); + await waitUntil(() => doc.querySelector(".js-manifest-empty") !== null); + + info("Navigate to a page that runs in the child process"); + await navigateTo(CONTENT_PROCESS_URI_MANIFEST); + + info("Waiting for the manifest to load"); + selectPage(panel, "manifest"); + await waitUntil(() => doc.querySelector(".js-manifest") !== null); + ok(true, "Manifest loaded successfully"); + + // close the tab + info("Closing the tab."); + await BrowserTestUtils.removeTab(tab); +}); diff --git a/devtools/client/application/test/browser/browser_application_panel_telemetry-debug-worker.js b/devtools/client/application/test/browser/browser_application_panel_telemetry-debug-worker.js new file mode 100644 index 0000000000..fe95dabd5e --- /dev/null +++ b/devtools/client/application/test/browser/browser_application_panel_telemetry-debug-worker.js @@ -0,0 +1,49 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +const TAB_URL = URL_ROOT + "resources/service-workers/simple.html"; + +// check telemetry for debugging a service worker +add_task(async function () { + await enableApplicationPanel(); + + const { panel, tab, toolbox, commands } = await openNewTabAndApplicationPanel( + TAB_URL + ); + + const doc = panel.panelWin.document; + + selectPage(panel, "service-workers"); + setupTelemetryTest(); + + info("Wait until the service worker appears in the application panel"); + await waitUntil(() => getWorkerContainers(doc).length === 1); + + const container = getWorkerContainers(doc)[0]; + info("Wait until the debug link is displayed"); + await waitUntil(() => { + return container.querySelector(".js-inspect-link"); + }); + + info("Click on the debug link and wait for debugger to be ready"); + const debugLink = container.querySelector(".js-inspect-link"); + debugLink.click(); + await waitUntil(() => toolbox.getPanel("jsdebugger")); + + const events = getTelemetryEvents("jsdebugger"); + const openToolboxEvent = events.find(event => event.method == "enter"); + ok(openToolboxEvent.session_id > 0, "Event has a valid session id"); + is( + openToolboxEvent.start_state, + "application", + "Event has the 'application' start state" + ); + + // clean up and close the tab + await unregisterAllWorkers(commands.client, doc); + info("Closing the tab."); + await commands.client.waitForRequestsToSettle(); + await BrowserTestUtils.removeTab(tab); +}); diff --git a/devtools/client/application/test/browser/browser_application_panel_telemetry-select-page.js b/devtools/client/application/test/browser/browser_application_panel_telemetry-select-page.js new file mode 100644 index 0000000000..c200c38c17 --- /dev/null +++ b/devtools/client/application/test/browser/browser_application_panel_telemetry-select-page.js @@ -0,0 +1,26 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +add_task(async function () { + await enableApplicationPanel(); + + const TAB_URL = URL_ROOT + "resources/service-workers/empty.html"; + const { panel, tab, commands } = await openNewTabAndApplicationPanel(TAB_URL); + const doc = panel.panelWin.document; + + setupTelemetryTest(); + + // make sure the default page is opened and then select a different one + await waitUntil(() => doc.querySelector(".js-service-workers-page") !== null); + ok(true, "Service Workers page was loaded per default."); + selectPage(panel, "manifest"); + + checkTelemetryEvent({ method: "select_page", page_type: "manifest" }); + + // close the tab + info("Closing the tab."); + await commands.client.waitForRequestsToSettle(); + await BrowserTestUtils.removeTab(tab); +}); diff --git a/devtools/client/application/test/browser/browser_application_panel_telemetry-start-worker.js b/devtools/client/application/test/browser/browser_application_panel_telemetry-start-worker.js new file mode 100644 index 0000000000..235ce3060d --- /dev/null +++ b/devtools/client/application/test/browser/browser_application_panel_telemetry-start-worker.js @@ -0,0 +1,45 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +const TAB_URL = URL_ROOT + "resources/service-workers/simple.html"; + +// check telemetry for starting a service worker +add_task(async function () { + info("Set a low service worker idle timeout"); + await pushPref("dom.serviceWorkers.idle_timeout", 1000); + await pushPref("dom.serviceWorkers.idle_extended_timeout", 1000); + + await enableApplicationPanel(); + + const { panel, tab, commands } = await openNewTabAndApplicationPanel(TAB_URL); + const doc = panel.panelWin.document; + + selectPage(panel, "service-workers"); + await waitForWorkerRegistration(tab); + + setupTelemetryTest(); + + info("Wait until the service worker appears in the application panel"); + await waitUntil(() => getWorkerContainers(doc).length === 1); + + info("Wait until the start button is displayed and enabled"); + const container = getWorkerContainers(doc)[0]; + await waitUntil(() => { + const button = container.querySelector(".js-start-button"); + return button && !button.disabled; + }); + + info("Click the start button"); + const button = container.querySelector(".js-start-button"); + button.click(); + + checkTelemetryEvent({ method: "start_worker" }); + + // clean up and close the tab + await unregisterAllWorkers(commands.client, doc); + info("Closing the tab."); + await commands.client.waitForRequestsToSettle(); + await BrowserTestUtils.removeTab(tab); +}); diff --git a/devtools/client/application/test/browser/browser_application_panel_telemetry-unregister-worker.js b/devtools/client/application/test/browser/browser_application_panel_telemetry-unregister-worker.js new file mode 100644 index 0000000000..aa6d35f946 --- /dev/null +++ b/devtools/client/application/test/browser/browser_application_panel_telemetry-unregister-worker.js @@ -0,0 +1,37 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +const TAB_URL = URL_ROOT + "resources/service-workers/simple.html"; + +// check telemetry for unregistering a service worker +add_task(async function () { + await enableApplicationPanel(); + + const { panel, tab, commands } = await openNewTabAndApplicationPanel(TAB_URL); + const doc = panel.panelWin.document; + + selectPage(panel, "service-workers"); + + setupTelemetryTest(); + + info("Wait until the service worker appears in the application panel"); + await waitUntil(() => getWorkerContainers(doc).length === 1); + + const workerContainer = getWorkerContainers(doc)[0]; + + info("Wait until the unregister button is displayed for the service worker"); + await waitUntil(() => workerContainer.querySelector(".js-unregister-button")); + info("Click the unregister button"); + const button = workerContainer.querySelector(".js-unregister-button"); + button.click(); + + checkTelemetryEvent({ method: "unregister_worker" }); + + // clean up and close the tab + await unregisterAllWorkers(commands.client, doc); + info("Closing the tab."); + await commands.client.waitForRequestsToSettle(); + await BrowserTestUtils.removeTab(tab); +}); diff --git a/devtools/client/application/test/browser/browser_application_panel_unregister-worker.js b/devtools/client/application/test/browser/browser_application_panel_unregister-worker.js new file mode 100644 index 0000000000..8f6c4a5793 --- /dev/null +++ b/devtools/client/application/test/browser/browser_application_panel_unregister-worker.js @@ -0,0 +1,36 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +const TAB_URL = URL_ROOT + "resources/service-workers/simple.html"; + +add_task(async function () { + await enableApplicationPanel(); + + const { panel, tab, commands } = await openNewTabAndApplicationPanel(TAB_URL); + const doc = panel.panelWin.document; + + selectPage(panel, "service-workers"); + + info("Wait until the service worker appears in the application panel"); + await waitUntil(() => getWorkerContainers(doc).length === 1); + + const workerContainer = getWorkerContainers(doc)[0]; + + info("Wait until the unregister button is displayed for the service worker"); + await waitUntil(() => workerContainer.querySelector(".js-unregister-button")); + info("Click the unregister button"); + const button = workerContainer.querySelector(".js-unregister-button"); + button.click(); + info("Wait until the service worker is removed from the application panel"); + await waitUntil(() => getWorkerContainers(doc).length === 0); + ok(true, "Service worker list is empty"); + + // just in case cleanup + await unregisterAllWorkers(commands.client, doc); + + // close the tab + info("Closing the tab."); + await BrowserTestUtils.removeTab(tab); +}); diff --git a/devtools/client/application/test/browser/browser_application_panel_viewsource-service-worker.js b/devtools/client/application/test/browser/browser_application_panel_viewsource-service-worker.js new file mode 100644 index 0000000000..fc6f0819b6 --- /dev/null +++ b/devtools/client/application/test/browser/browser_application_panel_viewsource-service-worker.js @@ -0,0 +1,50 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +const TAB_URL = URL_ROOT + "resources/service-workers/debug.html"; +const SW_URL = URL_ROOT + "resources/service-workers/debug-sw.js"; + +add_task(async function () { + await enableApplicationPanel(); + + // disable service worker debugging + await pushPref( + "devtools.debugger.features.windowless-service-workers", + false + ); + + const { panel, tab, commands } = await openNewTabAndApplicationPanel(TAB_URL); + const doc = panel.panelWin.document; + + selectPage(panel, "service-workers"); + + info("Wait until the service worker appears in the application panel"); + await waitUntil(() => getWorkerContainers(doc).length === 1); + + const container = getWorkerContainers(doc)[0]; + info("Wait until the inspect link is displayed"); + await waitUntil(() => { + return container.querySelector(".js-inspect-link"); + }); + + info("Click on the inspect link and wait for a new view-source: tab open"); + // click on the link and wait for the new tab to open + const onTabLoaded = BrowserTestUtils.waitForNewTab( + gBrowser, + `view-source:${SW_URL}` + ); + const inspectLink = container.querySelector(".js-inspect-link"); + inspectLink.click(); + + const sourceTab = await onTabLoaded; + ok(sourceTab, "The service worker source was opened in a new tab"); + + // clean up + await unregisterAllWorkers(commands.client, doc); + // close the tabs + info("Closing the tabs."); + await BrowserTestUtils.removeTab(sourceTab); + await BrowserTestUtils.removeTab(tab); +}); diff --git a/devtools/client/application/test/browser/browser_application_panel_worker-states.js b/devtools/client/application/test/browser/browser_application_panel_worker-states.js new file mode 100644 index 0000000000..54446506fa --- /dev/null +++ b/devtools/client/application/test/browser/browser_application_panel_worker-states.js @@ -0,0 +1,62 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +const TAB_URL = URL_ROOT + "resources/service-workers/controlled-install.html"; + +add_task(async function () { + await enableApplicationPanel(); + + const { panel, tab } = await openNewTabAndApplicationPanel(TAB_URL); + const doc = panel.panelWin.document; + + selectPage(panel, "service-workers"); + + info("Check for non-existing service worker"); + const isWorkerListEmpty = !!doc.querySelector(".js-registration-list-empty"); + ok(isWorkerListEmpty, "No Service Worker displayed"); + + info("Register a service worker with a controlled install in the page."); + await SpecialPowers.spawn(tab.linkedBrowser, [], async function () { + content.wrappedJSObject.registerServiceWorker(); + }); + + info("Wait until the service worker appears in the application panel"); + await waitUntil(() => !!getWorkerContainers(doc).length); + info("Wait until the 'Installing' state is displayed"); + await waitUntil(() => { + const containers = getWorkerContainers(doc); + if (containers.length === 0) { + return false; + } + + const stateEl = containers[0].querySelector(".js-worker-status"); + return stateEl.textContent.toLowerCase() === "installing"; + }); + + info("Allow the service worker to complete installation"); + await SpecialPowers.spawn(tab.linkedBrowser, [], async function () { + content.wrappedJSObject.installServiceWorker(); + }); + + info("Wait until the 'running' state is displayed"); + await waitUntil(() => { + const workerContainer = getWorkerContainers(doc)[0]; + const stateEl = workerContainer.querySelector(".js-worker-status"); + return stateEl.textContent.toLowerCase() === "running"; + }); + + info("Unregister the service worker"); + await SpecialPowers.spawn(tab.linkedBrowser, [], async function () { + const registration = await content.wrappedJSObject.sw; + registration.unregister(); + }); + + info("Wait until the service worker is removed from the application panel"); + await waitUntil(() => getWorkerContainers(doc).length === 0); + + // close the tab + info("Closing the tab."); + await BrowserTestUtils.removeTab(tab); +}); diff --git a/devtools/client/application/test/browser/head.js b/devtools/client/application/test/browser/head.js new file mode 100644 index 0000000000..6b7e67ff8d --- /dev/null +++ b/devtools/client/application/test/browser/head.js @@ -0,0 +1,134 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +/* eslint-env browser */ +/* eslint no-unused-vars: [2, {"vars": "local"}] */ + +"use strict"; + +// Load the shared-head file first. +Services.scriptloader.loadSubScript( + "chrome://mochitests/content/browser/devtools/client/shared/test/shared-head.js", + this +); + +/** + * Set all preferences needed to enable service worker debugging and testing. + */ +async function enableServiceWorkerDebugging() { + // Enable service workers. + await pushPref("dom.serviceWorkers.enabled", true); + // Accept workers from mochitest's http. + await pushPref("dom.serviceWorkers.testing.enabled", true); + // Force single content process, see Bug 1231208 for the SW refactor that should enable + // SW debugging in multi-e10s. + await pushPref("dom.ipc.processCount", 1); + + // Enable service workers in the debugger + await pushPref("devtools.debugger.features.windowless-service-workers", true); + // Disable randomly spawning processes during tests + await pushPref("dom.ipc.processPrelaunch.enabled", false); + + // Wait for dom.ipc.processCount to be updated before releasing processes. + Services.ppmm.releaseCachedProcesses(); +} + +async function enableApplicationPanel() { + // FIXME bug 1575427 this rejection is very common. + const { PromiseTestUtils } = ChromeUtils.importESModule( + "resource://testing-common/PromiseTestUtils.sys.mjs" + ); + PromiseTestUtils.allowMatchingRejectionsGlobally( + /this._frontCreationListeners is null/ + ); + + // Enable all preferences related to service worker debugging. + await enableServiceWorkerDebugging(); + + // Enable web manifest processing. + Services.prefs.setBoolPref("dom.manifest.enabled", true); + + // Enable application panel in DevTools. + await pushPref("devtools.application.enabled", true); +} + +function setupTelemetryTest() { + // Reset all the counts + Services.telemetry.clearEvents(); + + // Ensure no events have been logged + const ALL_CHANNELS = Ci.nsITelemetry.DATASET_ALL_CHANNELS; + const snapshot = Services.telemetry.snapshotEvents(ALL_CHANNELS, true); + ok(!snapshot.parent, "No events have been logged for the main process"); +} + +function getTelemetryEvents(objectName) { + // read the requested events only + const ALL_CHANNELS = Ci.nsITelemetry.DATASET_ALL_CHANNELS; + const snapshot = Services.telemetry.snapshotEvents(ALL_CHANNELS, true); + // filter and transform the event data so the relevant info is in a single object: + // { method: "...", extraField: "...", anotherExtraField: "...", ... } + const events = snapshot.parent + .filter(event => event[1] === "devtools.main" && event[3] === objectName) + .map(event => ({ method: event[2], ...event[5] })); + + return events; +} + +function checkTelemetryEvent(expectedEvent, objectName = "application") { + info("Check telemetry event"); + const events = getTelemetryEvents(objectName); + + // assert we only got 1 event with a valid session ID + is(events.length, 1, "There was only 1 event logged"); + const [event] = events; + ok(event.session_id > 0, "There is a valid session_id in the event"); + + // assert expected data + Assert.deepEqual(event, { ...expectedEvent, session_id: event.session_id }); +} + +function getWorkerContainers(doc) { + return doc.querySelectorAll(".js-sw-container"); +} + +async function openNewTabAndApplicationPanel(url) { + const tab = await addTab(url); + + const toolbox = await gDevTools.showToolboxForTab(tab, { + toolId: "application", + }); + const panel = toolbox.getCurrentPanel(); + const target = toolbox.target; + const commands = toolbox.commands; + return { panel, tab, target, toolbox, commands }; +} + +async function unregisterAllWorkers(client, doc) { + // This method is declared in shared-head.js + await unregisterAllServiceWorkers(client); + + info("Wait for service workers to disappear from the UI"); + waitUntil(() => getWorkerContainers(doc).length === 0); +} + +async function waitForWorkerRegistration(swTab) { + info("Wait until the registration appears on the window"); + const swBrowser = swTab.linkedBrowser; + await asyncWaitUntil(async () => + SpecialPowers.spawn(swBrowser, [], function () { + return !!content.wrappedJSObject.getRegistration(); + }) + ); +} + +function selectPage(panel, page) { + /** + * Select a page by simulating a user click in the sidebar. + * @param {string} page The page we want to select (see `PAGE_TYPES`) + **/ + info(`Selecting application page: ${page}`); + const doc = panel.panelWin.document; + const navItem = doc.querySelector(`.js-sidebar-${page}`); + navItem.click(); +} diff --git a/devtools/client/application/test/browser/resources/manifest/icon.svg b/devtools/client/application/test/browser/resources/manifest/icon.svg new file mode 100644 index 0000000000..bfed2982bc --- /dev/null +++ b/devtools/client/application/test/browser/resources/manifest/icon.svg @@ -0,0 +1,4 @@ + +firefox-logo-nightly diff --git a/devtools/client/application/test/browser/resources/manifest/load-fail.html b/devtools/client/application/test/browser/resources/manifest/load-fail.html new file mode 100644 index 0000000000..180c42a7b5 --- /dev/null +++ b/devtools/client/application/test/browser/resources/manifest/load-fail.html @@ -0,0 +1,9 @@ + + + + Manifest 404 not found + + + +

Manifest error 404 not found

+ diff --git a/devtools/client/application/test/browser/resources/manifest/load-no-manifest.html b/devtools/client/application/test/browser/resources/manifest/load-no-manifest.html new file mode 100644 index 0000000000..aeabc8a0cb --- /dev/null +++ b/devtools/client/application/test/browser/resources/manifest/load-no-manifest.html @@ -0,0 +1,8 @@ + + + + No manifest link + + +

No manifest link tag.

+ diff --git a/devtools/client/application/test/browser/resources/manifest/load-ok-icons.html b/devtools/client/application/test/browser/resources/manifest/load-ok-icons.html new file mode 100644 index 0000000000..539e5d2247 --- /dev/null +++ b/devtools/client/application/test/browser/resources/manifest/load-ok-icons.html @@ -0,0 +1,9 @@ + + + + Manifest successful load (with icons) + + + +

Manifest OK (with icons)

+ diff --git a/devtools/client/application/test/browser/resources/manifest/load-ok-json-error.html b/devtools/client/application/test/browser/resources/manifest/load-ok-json-error.html new file mode 100644 index 0000000000..95ad22b609 --- /dev/null +++ b/devtools/client/application/test/browser/resources/manifest/load-ok-json-error.html @@ -0,0 +1,10 @@ + + + + Manifest successful load with a warning + + + +

Manifest OK with validation errors

+

The manifest has invalid JSON

+ diff --git a/devtools/client/application/test/browser/resources/manifest/load-ok-manifest-link.html b/devtools/client/application/test/browser/resources/manifest/load-ok-manifest-link.html new file mode 100644 index 0000000000..f336f409e3 --- /dev/null +++ b/devtools/client/application/test/browser/resources/manifest/load-ok-manifest-link.html @@ -0,0 +1,9 @@ + + + + Successful load for a linked manifest + + + +

Manifest OK (linked manifest)

+ diff --git a/devtools/client/application/test/browser/resources/manifest/load-ok-warnings.html b/devtools/client/application/test/browser/resources/manifest/load-ok-warnings.html new file mode 100644 index 0000000000..467d6c3e70 --- /dev/null +++ b/devtools/client/application/test/browser/resources/manifest/load-ok-warnings.html @@ -0,0 +1,10 @@ + + + + Manifest successful load with a warning + + + +

Manifest OK with validation warnings

+

background_color does not contain a valid CSS color.

+ diff --git a/devtools/client/application/test/browser/resources/manifest/load-ok.html b/devtools/client/application/test/browser/resources/manifest/load-ok.html new file mode 100644 index 0000000000..1e6f5de59e --- /dev/null +++ b/devtools/client/application/test/browser/resources/manifest/load-ok.html @@ -0,0 +1,9 @@ + + + + Manifest successful load + + + +

Manifest OK

+ diff --git a/devtools/client/application/test/browser/resources/manifest/manifest.json b/devtools/client/application/test/browser/resources/manifest/manifest.json new file mode 100644 index 0000000000..0bc7bb50a3 --- /dev/null +++ b/devtools/client/application/test/browser/resources/manifest/manifest.json @@ -0,0 +1,3 @@ +{ + "name": "Foo" +} diff --git a/devtools/client/application/test/browser/resources/service-workers/controlled-install-sw.js b/devtools/client/application/test/browser/resources/service-workers/controlled-install-sw.js new file mode 100644 index 0000000000..d0a70a5312 --- /dev/null +++ b/devtools/client/application/test/browser/resources/service-workers/controlled-install-sw.js @@ -0,0 +1,29 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +// Copied from shared-head.js +function waitUntil(predicate, interval = 10) { + if (predicate()) { + return Promise.resolve(true); + } + return new Promise(resolve => { + setTimeout(function () { + waitUntil(predicate, interval).then(() => resolve(true)); + }, interval); + }); +} + +// this flag will be flipped externally from controlled-install.html +// by sending a message event to the worker +let canInstall = false; +self.addEventListener("message", event => { + if (event.data === "install-service-worker") { + canInstall = true; + } +}); + +self.addEventListener("install", event => { + event.waitUntil(waitUntil(() => canInstall)); +}); diff --git a/devtools/client/application/test/browser/resources/service-workers/controlled-install.html b/devtools/client/application/test/browser/resources/service-workers/controlled-install.html new file mode 100644 index 0000000000..300ee1fde7 --- /dev/null +++ b/devtools/client/application/test/browser/resources/service-workers/controlled-install.html @@ -0,0 +1,27 @@ + + + + + + Service worker test + + + + + diff --git a/devtools/client/application/test/browser/resources/service-workers/debug-sw.js b/devtools/client/application/test/browser/resources/service-workers/debug-sw.js new file mode 100644 index 0000000000..31f0b1bdd2 --- /dev/null +++ b/devtools/client/application/test/browser/resources/service-workers/debug-sw.js @@ -0,0 +1,18 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +self.addEventListener("activate", event => { + event.waitUntil(self.clients.claim()); +}); + +self.onfetch = function (event) { + const url = event.request.url; + + const response = url.endsWith("test") + ? new Response("lorem ipsum", { statusText: "OK" }) + : fetch(event.request); + + event.respondWith(response); +}; diff --git a/devtools/client/application/test/browser/resources/service-workers/debug.html b/devtools/client/application/test/browser/resources/service-workers/debug.html new file mode 100644 index 0000000000..f0f16858fd --- /dev/null +++ b/devtools/client/application/test/browser/resources/service-workers/debug.html @@ -0,0 +1,25 @@ + + + + + + + Service worker test + + + + +

This page has a fetchFromWorker() function.

+ + diff --git a/devtools/client/application/test/browser/resources/service-workers/dynamic-registration.html b/devtools/client/application/test/browser/resources/service-workers/dynamic-registration.html new file mode 100644 index 0000000000..def300da65 --- /dev/null +++ b/devtools/client/application/test/browser/resources/service-workers/dynamic-registration.html @@ -0,0 +1,19 @@ + + + + + + Service worker test + + + + + diff --git a/devtools/client/application/test/browser/resources/service-workers/empty-sw.js b/devtools/client/application/test/browser/resources/service-workers/empty-sw.js new file mode 100644 index 0000000000..5d33297056 --- /dev/null +++ b/devtools/client/application/test/browser/resources/service-workers/empty-sw.js @@ -0,0 +1,4 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +// Empty, just test registering. diff --git a/devtools/client/application/test/browser/resources/service-workers/empty.html b/devtools/client/application/test/browser/resources/service-workers/empty.html new file mode 100644 index 0000000000..02373ca02e --- /dev/null +++ b/devtools/client/application/test/browser/resources/service-workers/empty.html @@ -0,0 +1,11 @@ + + + + + + + Service worker test (no worker, empty page) + + + diff --git a/devtools/client/application/test/browser/resources/service-workers/scope-page.html b/devtools/client/application/test/browser/resources/service-workers/scope-page.html new file mode 100644 index 0000000000..eed5bc82ed --- /dev/null +++ b/devtools/client/application/test/browser/resources/service-workers/scope-page.html @@ -0,0 +1,19 @@ + + + + + + Service worker test + + + + + diff --git a/devtools/client/application/test/browser/resources/service-workers/simple-unicode.html b/devtools/client/application/test/browser/resources/service-workers/simple-unicode.html new file mode 100644 index 0000000000..51e17b7fec --- /dev/null +++ b/devtools/client/application/test/browser/resources/service-workers/simple-unicode.html @@ -0,0 +1,15 @@ + + + + + + Service worker test + + + + + diff --git a/devtools/client/application/test/browser/resources/service-workers/simple.html b/devtools/client/application/test/browser/resources/service-workers/simple.html new file mode 100644 index 0000000000..88dc00aff0 --- /dev/null +++ b/devtools/client/application/test/browser/resources/service-workers/simple.html @@ -0,0 +1,32 @@ + + + + + + Service worker test + + + + + -- cgit v1.2.3