diff options
Diffstat (limited to '')
-rw-r--r-- | devtools/shared/commands/target/tests/browser_target_command_browser_workers.js | 246 |
1 files changed, 246 insertions, 0 deletions
diff --git a/devtools/shared/commands/target/tests/browser_target_command_browser_workers.js b/devtools/shared/commands/target/tests/browser_target_command_browser_workers.js new file mode 100644 index 0000000000..181cfa2614 --- /dev/null +++ b/devtools/shared/commands/target/tests/browser_target_command_browser_workers.js @@ -0,0 +1,246 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +// Test the TargetCommand API around workers + +const FISSION_TEST_URL = URL_ROOT_SSL + "fission_document.html"; +const WORKER_FILE = "test_worker.js"; +const CHROME_WORKER_URL = CHROME_URL_ROOT + WORKER_FILE; +const SERVICE_WORKER_URL = URL_ROOT_SSL + "test_service_worker.js"; + +add_task(async function () { + // Enabled fission's pref as the TargetCommand is almost disabled without it + await pushPref("devtools.browsertoolbox.scope", "everything"); + + // Disable the preloaded process as it creates processes intermittently + // which forces the emission of RDP requests we aren't correctly waiting for. + await pushPref("dom.ipc.processPrelaunch.enabled", false); + + const tab = await addTab(FISSION_TEST_URL); + + info("Test TargetCommand against workers via the parent process target"); + + // Instantiate a worker in the parent process + // eslint-disable-next-line no-unused-vars + const worker = new Worker(CHROME_WORKER_URL + "#simple-worker"); + // eslint-disable-next-line no-unused-vars + const sharedWorker = new SharedWorker(CHROME_WORKER_URL + "#shared-worker"); + + const commands = await CommandsFactory.forMainProcess(); + const targetCommand = commands.targetCommand; + const { TYPES } = targetCommand; + await targetCommand.startListening(); + + // Very naive sanity check against getAllTargets([workerType]) + info("Check that getAllTargets returned the expected targets"); + const workers = await targetCommand.getAllTargets([TYPES.WORKER]); + const hasWorker = workers.find(workerTarget => { + return workerTarget.url == CHROME_WORKER_URL + "#simple-worker"; + }); + ok(hasWorker, "retrieve the target for the worker"); + + const sharedWorkers = await targetCommand.getAllTargets([ + TYPES.SHARED_WORKER, + ]); + const hasSharedWorker = sharedWorkers.find(workerTarget => { + return workerTarget.url == CHROME_WORKER_URL + "#shared-worker"; + }); + ok(hasSharedWorker, "retrieve the target for the shared worker"); + + const serviceWorkers = await targetCommand.getAllTargets([ + TYPES.SERVICE_WORKER, + ]); + const hasServiceWorker = serviceWorkers.find(workerTarget => { + return workerTarget.url == SERVICE_WORKER_URL; + }); + ok(hasServiceWorker, "retrieve the target for the service worker"); + + info( + "Check that calling getAllTargets again return the same target instances" + ); + const workers2 = await targetCommand.getAllTargets([TYPES.WORKER]); + const sharedWorkers2 = await targetCommand.getAllTargets([ + TYPES.SHARED_WORKER, + ]); + const serviceWorkers2 = await targetCommand.getAllTargets([ + TYPES.SERVICE_WORKER, + ]); + is(workers2.length, workers.length, "retrieved the same number of workers"); + is( + sharedWorkers2.length, + sharedWorkers.length, + "retrieved the same number of shared workers" + ); + is( + serviceWorkers2.length, + serviceWorkers.length, + "retrieved the same number of service workers" + ); + + workers.sort(sortFronts); + workers2.sort(sortFronts); + sharedWorkers.sort(sortFronts); + sharedWorkers2.sort(sortFronts); + serviceWorkers.sort(sortFronts); + serviceWorkers2.sort(sortFronts); + + for (let i = 0; i < workers.length; i++) { + is(workers[i], workers2[i], `worker ${i} targets are the same`); + } + for (let i = 0; i < sharedWorkers2.length; i++) { + is( + sharedWorkers[i], + sharedWorkers2[i], + `shared worker ${i} targets are the same` + ); + } + for (let i = 0; i < serviceWorkers2.length; i++) { + is( + serviceWorkers[i], + serviceWorkers2[i], + `service worker ${i} targets are the same` + ); + } + + info( + "Check that watchTargets will call the create callback for all existing workers" + ); + const targets = []; + const topLevelTarget = await commands.targetCommand.targetFront; + const onAvailable = async ({ targetFront }) => { + ok( + targetFront.targetType === TYPES.WORKER || + targetFront.targetType === TYPES.SHARED_WORKER || + targetFront.targetType === TYPES.SERVICE_WORKER, + "We are only notified about worker targets" + ); + ok( + targetFront == topLevelTarget + ? targetFront.isTopLevel + : !targetFront.isTopLevel, + "isTopLevel property is correct" + ); + targets.push(targetFront); + }; + await targetCommand.watchTargets({ + types: [TYPES.WORKER, TYPES.SHARED_WORKER, TYPES.SERVICE_WORKER], + onAvailable, + }); + is( + targets.length, + workers.length + sharedWorkers.length + serviceWorkers.length, + "retrieved the same number of workers via watchTargets" + ); + + targets.sort(sortFronts); + const allWorkers = workers + .concat(sharedWorkers, serviceWorkers) + .sort(sortFronts); + + for (let i = 0; i < allWorkers.length; i++) { + is( + allWorkers[i], + targets[i], + `worker ${i} targets are the same via watchTargets` + ); + } + + targetCommand.unwatchTargets({ + types: [TYPES.WORKER, TYPES.SHARED_WORKER, TYPES.SERVICE_WORKER], + onAvailable, + }); + + // Create a new worker and see if the worker target is reported + const onWorkerCreated = new Promise(resolve => { + const onAvailable2 = async ({ targetFront }) => { + if (targets.includes(targetFront)) { + return; + } + targetCommand.unwatchTargets({ + types: [TYPES.WORKER], + onAvailable: onAvailable2, + }); + resolve(targetFront); + }; + targetCommand.watchTargets({ + types: [TYPES.WORKER], + onAvailable: onAvailable2, + }); + }); + // eslint-disable-next-line no-unused-vars + const worker2 = new Worker(CHROME_WORKER_URL + "#second"); + info("Wait for the second worker to be created"); + const workerTarget = await onWorkerCreated; + + is( + workerTarget.url, + CHROME_WORKER_URL + "#second", + "This worker target is about the new worker" + ); + is( + workerTarget.name, + "test_worker.js#second", + "The worker target has the expected name" + ); + + const workers3 = await targetCommand.getAllTargets([TYPES.WORKER]); + const hasWorker2 = workers3.find( + ({ url }) => url == `${CHROME_WORKER_URL}#second` + ); + ok(hasWorker2, "retrieve the target for tab via getAllTargets"); + + info( + "Check that terminating the worker does trigger the onDestroyed callback" + ); + const onWorkerDestroyed = new Promise(resolve => { + const emptyFn = () => {}; + const onDestroyed = ({ targetFront }) => { + targetCommand.unwatchTargets({ + types: [TYPES.WORKER], + onAvailable: emptyFn, + onDestroyed, + }); + resolve(targetFront); + }; + + targetCommand.watchTargets({ + types: [TYPES.WORKER], + onAvailable: emptyFn, + onDestroyed, + }); + }); + worker2.terminate(); + const workerTargetFront = await onWorkerDestroyed; + ok(true, "onDestroyed was called when the worker was terminated"); + + workerTargetFront.isTopLevel; + ok( + true, + "isTopLevel can be called on the target front after onDestroyed was called" + ); + + workerTargetFront.name; + ok( + true, + "name can be accessed on the target front after onDestroyed was called" + ); + + targetCommand.destroy(); + + info("Unregister service workers so they don't appear in other tests."); + await unregisterAllServiceWorkers(commands.client); + + await commands.destroy(); + + await SpecialPowers.spawn(tab.linkedBrowser, [], async () => { + // registrationPromise is set by the test page. + const registration = await content.wrappedJSObject.registrationPromise; + registration.unregister(); + }); +}); + +function sortFronts(f1, f2) { + return f1.actorID < f2.actorID; +} |