From 6c1fb7047f573e6b9716abbcbaa8e41f04a3322c Mon Sep 17 00:00:00 2001 From: Federico Date: Fri, 22 Nov 2024 15:39:31 +0700 Subject: [PATCH 1/8] Upgrade testing extension to MV3 --- package-lock.json | 25 +++++++++++++++++++++---- package.json | 3 ++- source/test/background.ts | 8 ++++++++ source/test/background/api.test.ts | 2 +- source/test/background/testingApi.ts | 8 +++----- source/test/contentscript/api.test.ts | 17 +++++++++-------- source/test/iframe.html | 6 +----- source/test/manifest.json | 20 ++++++++++++-------- source/test/options.html | 4 +++- 9 files changed, 60 insertions(+), 33 deletions(-) create mode 100644 source/test/background.ts diff --git a/package-lock.json b/package-lock.json index e777fef..b8ea7a6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,7 +13,8 @@ "p-retry": "^6.2.0", "serialize-error": "^11.0.3", "type-fest": "^4.26.1", - "webext-detect": "^5.1.0" + "webext-detect": "^5.3.1", + "webext-events": "^3.1.1" }, "devDependencies": { "@parcel/config-webextension": "^2.11.0", @@ -21318,9 +21319,25 @@ } }, "node_modules/webext-detect": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/webext-detect/-/webext-detect-5.1.0.tgz", - "integrity": "sha512-nsTWw4xehwN5ztOctrK8WoREANGyFNemyE+8za8A7mBxHxpefQeCV/sIYL7JyT6aWclw3C6rqFU3FGHf4f0ASw==", + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/webext-detect/-/webext-detect-5.3.1.tgz", + "integrity": "sha512-vmVd7haZ+CW/n037KUCi7t5Xn+oMxxScsgTPXirnHxXhHLJsR+4je9glh6QrsptgUfkZN4dGcFTrBrZUah1RAg==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/fregante" + } + }, + "node_modules/webext-events": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/webext-events/-/webext-events-3.1.1.tgz", + "integrity": "sha512-/QlXfa8LHcPOwLIycLglnHbXLqBOGetNn4pOyVJhV5UA6RifcP1tfkp8DYj3R6CjnHbjpSqFWXyc6dD4aTUcXw==", + "license": "MIT", + "dependencies": { + "webext-detect": "^5.0.2" + }, "engines": { "node": ">=18" }, diff --git a/package.json b/package.json index fa95ac8..832ef2c 100644 --- a/package.json +++ b/package.json @@ -30,7 +30,8 @@ "p-retry": "^6.2.0", "serialize-error": "^11.0.3", "type-fest": "^4.26.1", - "webext-detect": "^5.1.0" + "webext-detect": "^5.3.1", + "webext-events": "^3.1.1" }, "@parcel/resolver-default": { "packageExports": true diff --git a/source/test/background.ts b/source/test/background.ts new file mode 100644 index 0000000..fa4f600 --- /dev/null +++ b/source/test/background.ts @@ -0,0 +1,8 @@ +import "./webextensionPolyfill.js"; +import "./background/registration.ts"; +import "./contentscript/api.test.ts"; +import { onExtensionStart } from "webext-events"; + +onExtensionStart.addListener(() => { + void browser.runtime.openOptionsPage(); +}); diff --git a/source/test/background/api.test.ts b/source/test/background/api.test.ts index 39a0276..e46df69 100644 --- a/source/test/background/api.test.ts +++ b/source/test/background/api.test.ts @@ -58,7 +58,7 @@ test("should receive error from a background handler", async (t) => { t.equal(error.message, "This my error"); t.true( - error.stack.includes("/background/registration.js"), + error.stack.includes("/background."), "The stacktrace must come from the background page" ); t.true( diff --git a/source/test/background/testingApi.ts b/source/test/background/testingApi.ts index 73040a5..b760b61 100644 --- a/source/test/background/testingApi.ts +++ b/source/test/background/testingApi.ts @@ -2,11 +2,9 @@ import { executeFunction } from "webext-content-scripts"; import { once } from "webext-messenger/shared.js"; export async function ensureScripts(tabId: number): Promise { - await browser.tabs.executeScript(tabId, { - file: "webextensionPolyfill.js", - }); - await browser.tabs.executeScript(tabId, { - file: "contentscript/registration.js", + await browser.scripting.executeScript({ + target: { tabId }, + files: ["webextensionPolyfill.js", "contentscript/registration.js"], }); } diff --git a/source/test/contentscript/api.test.ts b/source/test/contentscript/api.test.ts index 39b0c12..6e90ddc 100644 --- a/source/test/contentscript/api.test.ts +++ b/source/test/contentscript/api.test.ts @@ -48,7 +48,8 @@ function senderisBackground( t.true( sender?.origin === extensionUrl.origin || // Chrome sender?.origin === "null" || // Chrome, old - sender!.url?.endsWith("/_generated_background_page.html"), // Firefox + sender?.url?.includes("/background.") || + sender?.url?.endsWith("/_generated_background_page.html"), // Firefox message ); } @@ -146,18 +147,18 @@ function runOnTarget(target: Target | PageTarget, expectedTitle: string) { const originalSender = trace[0]; const directSender = trace.at(-1); - if (isContentScript() || !isBackground()) { - senderIsCurrentPage( - t, - originalSender, - "Messages should mention the current page in trace[0]" - ); - } else { + if (isBackground()) { senderisBackground( t, directSender, "Messages should mention the current page (background) in trace[0]" ); + } else { + senderIsCurrentPage( + t, + originalSender, + "Messages should mention the current page in trace[0]" + ); } if (!("page" in target && isContentScript())) { diff --git a/source/test/iframe.html b/source/test/iframe.html index 07c9101..4aec5b0 100644 --- a/source/test/iframe.html +++ b/source/test/iframe.html @@ -2,11 +2,6 @@ Extension frame +

Extension frame

diff --git a/source/test/manifest.json b/source/test/manifest.json index ed283b7..31b197c 100644 --- a/source/test/manifest.json +++ b/source/test/manifest.json @@ -1,14 +1,13 @@ { + "$schema": "https://json.schemastore.org/chrome-manifest", "name": "webext-messenger", "version": "0.0.0", - "manifest_version": 2, - "permissions": ["webNavigation", "https://fregante.github.io/*"], + "manifest_version": 3, + "permissions": ["webNavigation", "scripting", "storage"], + "host_permissions": ["https://fregante.github.io/*"], "background": { - "scripts": [ - "webextensionPolyfill.ts", - "background/registration.ts", - "contentscript/api.test.ts" - ] + "type": "module", + "service_worker": "background.ts" }, "options_ui": { "page": "options.html", @@ -53,5 +52,10 @@ "js": ["webextensionPolyfill.ts", "contentscript/missedRegistration.ts"] } ], - "web_accessible_resources": ["*.html", "**/*.ts"] + "web_accessible_resources": [ + { + "resources": ["*.html", "**/*.ts"], + "matches": [""] + } + ] } diff --git a/source/test/options.html b/source/test/options.html index f9df11d..966da58 100644 --- a/source/test/options.html +++ b/source/test/options.html @@ -1,5 +1,7 @@ - + Options +

Options page

+

Will call background methods

From 7fcb705a50ca7f22e4dc7cf232078f0815e83216 Mon Sep 17 00:00:00 2001 From: Federico Date: Fri, 22 Nov 2024 16:06:22 +0700 Subject: [PATCH 2/8] Lint --- source/test/contentscript/api.test.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/source/test/contentscript/api.test.ts b/source/test/contentscript/api.test.ts index 6e90ddc..ab3fa35 100644 --- a/source/test/contentscript/api.test.ts +++ b/source/test/contentscript/api.test.ts @@ -45,6 +45,7 @@ function senderisBackground( sender: Sender | undefined, message: string ) { + /* eslint-disable @typescript-eslint/prefer-nullish-coalescing -- It's an OR on falsy values */ t.true( sender?.origin === extensionUrl.origin || // Chrome sender?.origin === "null" || // Chrome, old From d79889ca17feb83110d87eddf0453474e71f0b48 Mon Sep 17 00:00:00 2001 From: Federico Date: Fri, 22 Nov 2024 15:11:12 +0700 Subject: [PATCH 3/8] Start offscreen --- package.json | 3 ++- source/test/background.ts | 7 +++++++ source/test/manifest.json | 9 ++++++++- source/test/offscreen.html | 5 +++++ source/test/offscreen/addFrame.ts | 5 +++++ source/test/offscreen/api.test.ts | 8 ++++++++ source/test/offscreen/api.ts | 7 +++++++ source/test/offscreen/eval.ts | 4 ++++ source/test/offscreen/getLocation.ts | 3 +++ source/test/offscreen/getTrace.ts | 5 +++++ source/test/offscreen/registration.ts | 29 +++++++++++++++++++++++++++ source/thisTarget.ts | 7 +++++-- 12 files changed, 88 insertions(+), 4 deletions(-) create mode 100644 source/test/offscreen.html create mode 100644 source/test/offscreen/addFrame.ts create mode 100644 source/test/offscreen/api.test.ts create mode 100644 source/test/offscreen/api.ts create mode 100644 source/test/offscreen/eval.ts create mode 100644 source/test/offscreen/getLocation.ts create mode 100644 source/test/offscreen/getTrace.ts create mode 100644 source/test/offscreen/registration.ts diff --git a/package.json b/package.json index 832ef2c..b50d701 100644 --- a/package.json +++ b/package.json @@ -74,7 +74,8 @@ "run": { "startUrl": [ "https://fregante.github.io/pixiebrix-testing-ground/Will-call-background-methods", - "https://fregante.github.io/pixiebrix-testing-ground/Will-call-other-CS-via-background" + "https://fregante.github.io/pixiebrix-testing-ground/Will-call-other-CS-via-background", + "https://fregante.github.io/pixiebrix-testing-ground/Will-offscreen-methods" ] } } diff --git a/source/test/background.ts b/source/test/background.ts index fa4f600..9620171 100644 --- a/source/test/background.ts +++ b/source/test/background.ts @@ -5,4 +5,11 @@ import { onExtensionStart } from "webext-events"; onExtensionStart.addListener(() => { void browser.runtime.openOptionsPage(); + + void chrome.offscreen.createDocument({ + url: 'offscreen.html', + // @ts-expect-error wrong? + reasons: ['DOM_PARSER'], + justification: 'testing' + }); }); diff --git a/source/test/manifest.json b/source/test/manifest.json index 31b197c..e8c5e38 100644 --- a/source/test/manifest.json +++ b/source/test/manifest.json @@ -3,7 +3,7 @@ "name": "webext-messenger", "version": "0.0.0", "manifest_version": 3, - "permissions": ["webNavigation", "scripting", "storage"], + "permissions": ["webNavigation", "scripting", "storage", "offscreen"], "host_permissions": ["https://fregante.github.io/*"], "background": { "type": "module", @@ -21,6 +21,13 @@ ], "js": ["webextensionPolyfill.ts", "background/api.test.ts"] }, + { + "all_frames": true, + "matches": [ + "https://fregante.github.io/pixiebrix-testing-ground/Will-offscreen-methods" + ], + "js": ["webextensionPolyfill.ts", "offscreen/api.test.ts"] + }, { "all_frames": true, "matches": [ diff --git a/source/test/offscreen.html b/source/test/offscreen.html new file mode 100644 index 0000000..08c96c6 --- /dev/null +++ b/source/test/offscreen.html @@ -0,0 +1,5 @@ + + +Offscreen page + + diff --git a/source/test/offscreen/addFrame.ts b/source/test/offscreen/addFrame.ts new file mode 100644 index 0000000..0369ae1 --- /dev/null +++ b/source/test/offscreen/addFrame.ts @@ -0,0 +1,5 @@ +export function addFrame(): void { + const frame = document.createElement("iframe"); + frame.src = "https://example.com"; + document.body.append(frame); +} diff --git a/source/test/offscreen/api.test.ts b/source/test/offscreen/api.test.ts new file mode 100644 index 0000000..1507801 --- /dev/null +++ b/source/test/offscreen/api.test.ts @@ -0,0 +1,8 @@ +import test from "tape"; +import { + getLocation, +} from "./api.js"; + +test("can get a value from the offscreen document", async (t) => { + t.equal(await getLocation(), "offscreen.html"); +}); diff --git a/source/test/offscreen/api.ts b/source/test/offscreen/api.ts new file mode 100644 index 0000000..127bc01 --- /dev/null +++ b/source/test/offscreen/api.ts @@ -0,0 +1,7 @@ +import { getNotifier, getMethod } from "webext-messenger"; + +const target = {page: "offscreen"}; + +export const getLocation = getMethod("getLocation", target); +export const addFrame = getNotifier("addFrame", target); +export const getTrace = getMethod("getTrace", target); diff --git a/source/test/offscreen/eval.ts b/source/test/offscreen/eval.ts new file mode 100644 index 0000000..e9774c5 --- /dev/null +++ b/source/test/offscreen/eval.ts @@ -0,0 +1,4 @@ +export function evalScript(script: string): unknown { + // eslint-disable-next-line no-eval + return eval(script); +} diff --git a/source/test/offscreen/getLocation.ts b/source/test/offscreen/getLocation.ts new file mode 100644 index 0000000..55ffa37 --- /dev/null +++ b/source/test/offscreen/getLocation.ts @@ -0,0 +1,3 @@ +export function getLocation(): string { + return location.href; +} diff --git a/source/test/offscreen/getTrace.ts b/source/test/offscreen/getTrace.ts new file mode 100644 index 0000000..a23a5f4 --- /dev/null +++ b/source/test/offscreen/getTrace.ts @@ -0,0 +1,5 @@ +import { type MessengerMeta, type Sender } from "webext-messenger"; + +export async function getTrace(this: MessengerMeta): Promise { + return this.trace; +} diff --git a/source/test/offscreen/registration.ts b/source/test/offscreen/registration.ts new file mode 100644 index 0000000..e8d8c53 --- /dev/null +++ b/source/test/offscreen/registration.ts @@ -0,0 +1,29 @@ +import { isOffscreenDocument } from "webext-detect"; +import { registerMethods } from "webext-messenger"; + +import { addFrame } from "./addFrame.js"; +import { getLocation } from "./getLocation.js"; +import { getTrace } from "./getTrace.js"; +import { evalScript } from "./eval.js"; + +declare global { + interface MessengerMethods { + addFrame: typeof addFrame; + getLocation: typeof getLocation; + getTrace: typeof getTrace; + eval: typeof evalScript; + } +} + +if (!isOffscreenDocument()) { + throw new Error( + "This file must only be run in the offscreen document, which is the receiving end" + ); +} + +registerMethods({ + addFrame, + getLocation, + getTrace, + eval: evalScript, +}); diff --git a/source/thisTarget.ts b/source/thisTarget.ts index a680155..7114280 100644 --- a/source/thisTarget.ts +++ b/source/thisTarget.ts @@ -2,6 +2,7 @@ import { getContextName, isBackground, isExtensionContext, + isOffscreenDocument, } from "webext-detect"; import { messenger } from "./sender.js"; import { registerMethods } from "./receiver.js"; @@ -41,6 +42,8 @@ import { pEvent } from "p-event"; // If a message is received before this is ready, it will just have to be ignored. export const thisTarget: KnownTarget = isBackground() ? { page: "background" } + : (isOffscreenDocument() + ? { page: "offscreen" } : { get page(): string { // Extension pages have relative URLs to simplify comparison @@ -51,11 +54,11 @@ export const thisTarget: KnownTarget = isBackground() // Don't use the hash return origin + location.pathname + location.search; }, - }; + }); let tabDataStatus: "needed" | "pending" | "received" | "not-needed" | "error" = // The background page doesn't have a tab - isBackground() ? "not-needed" : "needed"; + isBackground() || isOffscreenDocument() ? "not-needed" : "needed"; export function getTabDataStatus(): typeof tabDataStatus { return tabDataStatus; From 672e856fdff1fcf586059a6621a460a35b0cb97a Mon Sep 17 00:00:00 2001 From: Federico Date: Fri, 22 Nov 2024 16:38:11 +0700 Subject: [PATCH 4/8] Finalize offscreen --- package.json | 2 +- source/test/background.ts | 15 +++++--------- source/test/contentscript/api.test.ts | 29 +++------------------------ source/test/helpers.ts | 27 +++++++++++++++++++++++++ source/test/manifest.json | 3 +-- source/test/offscreen/api.test.ts | 28 ++++++++++++++++++++++++-- source/test/offscreen/eval.ts | 4 ---- source/test/offscreen/registration.ts | 3 --- 8 files changed, 63 insertions(+), 48 deletions(-) delete mode 100644 source/test/offscreen/eval.ts diff --git a/package.json b/package.json index b50d701..5669c48 100644 --- a/package.json +++ b/package.json @@ -75,7 +75,7 @@ "startUrl": [ "https://fregante.github.io/pixiebrix-testing-ground/Will-call-background-methods", "https://fregante.github.io/pixiebrix-testing-ground/Will-call-other-CS-via-background", - "https://fregante.github.io/pixiebrix-testing-ground/Will-offscreen-methods" + "https://fregante.github.io/pixiebrix-testing-ground/Will-call-offscreen-methods" ] } } diff --git a/source/test/background.ts b/source/test/background.ts index 9620171..abf69ee 100644 --- a/source/test/background.ts +++ b/source/test/background.ts @@ -1,15 +1,10 @@ import "./webextensionPolyfill.js"; import "./background/registration.ts"; import "./contentscript/api.test.ts"; -import { onExtensionStart } from "webext-events"; -onExtensionStart.addListener(() => { - void browser.runtime.openOptionsPage(); - - void chrome.offscreen.createDocument({ - url: 'offscreen.html', - // @ts-expect-error wrong? - reasons: ['DOM_PARSER'], - justification: 'testing' - }); +void chrome.offscreen.createDocument({ + url: 'offscreen.html', + // @ts-expect-error wrong? + reasons: ['DOM_PARSER'], + justification: 'testing' }); diff --git a/source/test/contentscript/api.test.ts b/source/test/contentscript/api.test.ts index ab3fa35..57ac8f2 100644 --- a/source/test/contentscript/api.test.ts +++ b/source/test/contentscript/api.test.ts @@ -1,6 +1,6 @@ import test from "tape"; import { isBackground, isContentScript, isWebPage } from "webext-detect"; -import { type PageTarget, type Sender, type Target } from "webext-messenger"; +import { type PageTarget, type Target } from "webext-messenger"; import { errorTabDoesntExist, errorTargetClosedEarly, @@ -12,6 +12,8 @@ import { sleep, trackSettleTime, expectDuration, + senderisBackground, + senderIsCurrentPage, } from "../helpers.js"; import * as backgroundContext from "../background/api.js"; import * as localContext from "../background/testingApi.js"; @@ -30,31 +32,6 @@ import { } from "./api.js"; import { MessengerError } from "../../shared.js"; -const extensionUrl = new URL(chrome.runtime.getURL("")); - -function senderIsCurrentPage( - t: test.Test, - sender: Sender | undefined, - message: string -) { - t.equal(sender?.url, location.href, message); -} - -function senderisBackground( - t: test.Test, - sender: Sender | undefined, - message: string -) { - /* eslint-disable @typescript-eslint/prefer-nullish-coalescing -- It's an OR on falsy values */ - t.true( - sender?.origin === extensionUrl.origin || // Chrome - sender?.origin === "null" || // Chrome, old - sender?.url?.includes("/background.") || - sender?.url?.endsWith("/_generated_background_page.html"), // Firefox - message - ); -} - const { openTab, createTargets, ensureScripts, closeTab } = isBackground() ? localContext : backgroundContext; diff --git a/source/test/helpers.ts b/source/test/helpers.ts index cef484a..3239cce 100644 --- a/source/test/helpers.ts +++ b/source/test/helpers.ts @@ -1,4 +1,6 @@ import type test from "tape"; +import { type Sender } from "webext-messenger"; + export async function expectRejection( t: test.Test, @@ -65,3 +67,28 @@ export function expectDuration( ); } } + +const extensionUrl = new URL(chrome.runtime.getURL("")); + +export function senderIsCurrentPage( + t: test.Test, + sender: Sender | undefined, + message: string +) { + t.equal(sender?.url, location.href, message); +} + +export function senderisBackground( + t: test.Test, + sender: Sender | undefined, + message: string +) { + /* eslint-disable @typescript-eslint/prefer-nullish-coalescing -- It's an OR on falsy values */ + t.true( + sender?.origin === extensionUrl.origin || // Chrome + sender?.origin === "null" || // Chrome, old + sender?.url?.includes("/background.") || + sender?.url?.endsWith("/_generated_background_page.html"), // Firefox + message + ); +} diff --git a/source/test/manifest.json b/source/test/manifest.json index e8c5e38..fed14c1 100644 --- a/source/test/manifest.json +++ b/source/test/manifest.json @@ -22,9 +22,8 @@ "js": ["webextensionPolyfill.ts", "background/api.test.ts"] }, { - "all_frames": true, "matches": [ - "https://fregante.github.io/pixiebrix-testing-ground/Will-offscreen-methods" + "https://fregante.github.io/pixiebrix-testing-ground/Will-call-offscreen-methods" ], "js": ["webextensionPolyfill.ts", "offscreen/api.test.ts"] }, diff --git a/source/test/offscreen/api.test.ts b/source/test/offscreen/api.test.ts index 1507801..03f76f0 100644 --- a/source/test/offscreen/api.test.ts +++ b/source/test/offscreen/api.test.ts @@ -1,8 +1,32 @@ import test from "tape"; import { getLocation, + addFrame, + getTrace, } from "./api.js"; +import { senderIsCurrentPage } from "../helpers.js"; -test("can get a value from the offscreen document", async (t) => { - t.equal(await getLocation(), "offscreen.html"); +test("should get a value from the offscreen document", async (t) => { + t.equal(await getLocation(), chrome.runtime.getURL( "offscreen.html")); +}); + +test("notification should return undefined", async (t) => { + // eslint-disable-next-line @typescript-eslint/no-confusing-void-expression -- Testing for this specifically + t.equals(addFrame(), undefined); +}); + +test("should receive trace", async (t) => { + const trace = await getTrace(); + t.true(Array.isArray(trace)); + + const originalSender = trace[0]; + + + senderIsCurrentPage( + t, + originalSender, + "Messages should mention the current page in trace[0]" + ); + + t.equal(trace.length, 1, "The offscreen page can and should only be messaged directly"); }); diff --git a/source/test/offscreen/eval.ts b/source/test/offscreen/eval.ts deleted file mode 100644 index e9774c5..0000000 --- a/source/test/offscreen/eval.ts +++ /dev/null @@ -1,4 +0,0 @@ -export function evalScript(script: string): unknown { - // eslint-disable-next-line no-eval - return eval(script); -} diff --git a/source/test/offscreen/registration.ts b/source/test/offscreen/registration.ts index e8d8c53..35e00eb 100644 --- a/source/test/offscreen/registration.ts +++ b/source/test/offscreen/registration.ts @@ -4,14 +4,12 @@ import { registerMethods } from "webext-messenger"; import { addFrame } from "./addFrame.js"; import { getLocation } from "./getLocation.js"; import { getTrace } from "./getTrace.js"; -import { evalScript } from "./eval.js"; declare global { interface MessengerMethods { addFrame: typeof addFrame; getLocation: typeof getLocation; getTrace: typeof getTrace; - eval: typeof evalScript; } } @@ -25,5 +23,4 @@ registerMethods({ addFrame, getLocation, getTrace, - eval: evalScript, }); From ec40e28208cd3057932ba83a307d43be4c833a86 Mon Sep 17 00:00:00 2001 From: Federico Date: Thu, 28 Nov 2024 12:34:39 +0700 Subject: [PATCH 5/8] Prettier --- source/test/background.ts | 8 ++++---- source/test/helpers.ts | 7 +++---- source/test/offscreen.html | 2 +- source/test/offscreen/addFrame.ts | 6 +++--- source/test/offscreen/api.test.ts | 17 ++++++++--------- source/test/offscreen/api.ts | 2 +- source/test/offscreen/getLocation.ts | 2 +- source/test/offscreen/registration.ts | 2 +- source/thisTarget.ts | 26 +++++++++++++------------- 9 files changed, 35 insertions(+), 37 deletions(-) diff --git a/source/test/background.ts b/source/test/background.ts index abf69ee..983811d 100644 --- a/source/test/background.ts +++ b/source/test/background.ts @@ -3,8 +3,8 @@ import "./background/registration.ts"; import "./contentscript/api.test.ts"; void chrome.offscreen.createDocument({ - url: 'offscreen.html', - // @ts-expect-error wrong? - reasons: ['DOM_PARSER'], - justification: 'testing' + url: "offscreen.html", + // @ts-expect-error wrong? + reasons: ["DOM_PARSER"], + justification: "testing", }); diff --git a/source/test/helpers.ts b/source/test/helpers.ts index c7ad210..ab23c71 100644 --- a/source/test/helpers.ts +++ b/source/test/helpers.ts @@ -1,7 +1,6 @@ import type test from "tape"; import { type Sender } from "webext-messenger"; - export async function expectRejection( t: test.Test, promise: Promise, @@ -73,7 +72,7 @@ const extensionUrl = new URL(chrome.runtime.getURL("")); export function senderIsCurrentPage( t: test.Test, sender: Sender | undefined, - message: string + message: string, ) { t.equal(sender?.url, location.href, message); } @@ -81,7 +80,7 @@ export function senderIsCurrentPage( export function senderisBackground( t: test.Test, sender: Sender | undefined, - message: string + message: string, ) { /* eslint-disable @typescript-eslint/prefer-nullish-coalescing -- It's an OR on falsy values */ t.true( @@ -89,6 +88,6 @@ export function senderisBackground( sender?.origin === "null" || // Chrome, old sender?.url?.includes("/background.") || sender?.url?.endsWith("/_generated_background_page.html"), // Firefox - message + message, ); } diff --git a/source/test/offscreen.html b/source/test/offscreen.html index 08c96c6..4281c34 100644 --- a/source/test/offscreen.html +++ b/source/test/offscreen.html @@ -1,4 +1,4 @@ - + Offscreen page diff --git a/source/test/offscreen/addFrame.ts b/source/test/offscreen/addFrame.ts index 0369ae1..364c597 100644 --- a/source/test/offscreen/addFrame.ts +++ b/source/test/offscreen/addFrame.ts @@ -1,5 +1,5 @@ export function addFrame(): void { - const frame = document.createElement("iframe"); - frame.src = "https://example.com"; - document.body.append(frame); + const frame = document.createElement("iframe"); + frame.src = "https://example.com"; + document.body.append(frame); } diff --git a/source/test/offscreen/api.test.ts b/source/test/offscreen/api.test.ts index 03f76f0..a36b818 100644 --- a/source/test/offscreen/api.test.ts +++ b/source/test/offscreen/api.test.ts @@ -1,13 +1,9 @@ import test from "tape"; -import { - getLocation, - addFrame, - getTrace, -} from "./api.js"; +import { getLocation, addFrame, getTrace } from "./api.js"; import { senderIsCurrentPage } from "../helpers.js"; test("should get a value from the offscreen document", async (t) => { - t.equal(await getLocation(), chrome.runtime.getURL( "offscreen.html")); + t.equal(await getLocation(), chrome.runtime.getURL("offscreen.html")); }); test("notification should return undefined", async (t) => { @@ -21,12 +17,15 @@ test("should receive trace", async (t) => { const originalSender = trace[0]; - senderIsCurrentPage( t, originalSender, - "Messages should mention the current page in trace[0]" + "Messages should mention the current page in trace[0]", ); - t.equal(trace.length, 1, "The offscreen page can and should only be messaged directly"); + t.equal( + trace.length, + 1, + "The offscreen page can and should only be messaged directly", + ); }); diff --git a/source/test/offscreen/api.ts b/source/test/offscreen/api.ts index 127bc01..6563481 100644 --- a/source/test/offscreen/api.ts +++ b/source/test/offscreen/api.ts @@ -1,6 +1,6 @@ import { getNotifier, getMethod } from "webext-messenger"; -const target = {page: "offscreen"}; +const target = { page: "offscreen" }; export const getLocation = getMethod("getLocation", target); export const addFrame = getNotifier("addFrame", target); diff --git a/source/test/offscreen/getLocation.ts b/source/test/offscreen/getLocation.ts index 55ffa37..6ce6ddd 100644 --- a/source/test/offscreen/getLocation.ts +++ b/source/test/offscreen/getLocation.ts @@ -1,3 +1,3 @@ export function getLocation(): string { - return location.href; + return location.href; } diff --git a/source/test/offscreen/registration.ts b/source/test/offscreen/registration.ts index 35e00eb..b2fe14c 100644 --- a/source/test/offscreen/registration.ts +++ b/source/test/offscreen/registration.ts @@ -15,7 +15,7 @@ declare global { if (!isOffscreenDocument()) { throw new Error( - "This file must only be run in the offscreen document, which is the receiving end" + "This file must only be run in the offscreen document, which is the receiving end", ); } diff --git a/source/thisTarget.ts b/source/thisTarget.ts index 12b0683..826ca2d 100644 --- a/source/thisTarget.ts +++ b/source/thisTarget.ts @@ -42,19 +42,19 @@ import { pEvent } from "p-event"; // If a message is received before this is ready, it will just have to be ignored. export const thisTarget: KnownTarget = isBackground() ? { page: "background" } - : (isOffscreenDocument() - ? { page: "offscreen" } - : { - get page(): string { - // Extension pages have relative URLs to simplify comparison - const origin = location.protocol.startsWith("http") - ? location.origin - : ""; - - // Don't use the hash - return origin + location.pathname + location.search; - }, - }); + : isOffscreenDocument() + ? { page: "offscreen" } + : { + get page(): string { + // Extension pages have relative URLs to simplify comparison + const origin = location.protocol.startsWith("http") + ? location.origin + : ""; + + // Don't use the hash + return origin + location.pathname + location.search; + }, + }; let tabDataStatus: "needed" | "pending" | "received" | "not-needed" | "error" = // The background page doesn't have a tab From 465b7a0205023678820c65f0bfd4a3617891b6f9 Mon Sep 17 00:00:00 2001 From: Federico Date: Thu, 28 Nov 2024 13:00:38 +0700 Subject: [PATCH 6/8] Silence `offscreen.createDocument` --- source/test/background.ts | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/source/test/background.ts b/source/test/background.ts index 983811d..1233cb6 100644 --- a/source/test/background.ts +++ b/source/test/background.ts @@ -2,9 +2,20 @@ import "./webextensionPolyfill.js"; import "./background/registration.ts"; import "./contentscript/api.test.ts"; -void chrome.offscreen.createDocument({ - url: "offscreen.html", - // @ts-expect-error wrong? - reasons: ["DOM_PARSER"], - justification: "testing", -}); +async function init() { + try { + await chrome.offscreen.createDocument({ + url: "offscreen.html", + // @ts-expect-error wrong? + reasons: ["DOM_PARSER"], + justification: "testing", + }); + } catch (error) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-explicit-any + if (!(error as any).message.includes("Only a single offscreen")) { + throw error; + } + } +} + +void init(); From 1c21875840e24542bc092ac336532bcb8c73fa9d Mon Sep 17 00:00:00 2001 From: Federico Date: Thu, 28 Nov 2024 15:02:18 +0700 Subject: [PATCH 7/8] Lint --- .eslintrc | 1 + 1 file changed, 1 insertion(+) diff --git a/.eslintrc b/.eslintrc index 7dd2ffe..7ef4a4c 100644 --- a/.eslintrc +++ b/.eslintrc @@ -50,6 +50,7 @@ } } ], + "unicorn/no-nested-ternary": "off", // Prettier conflict "@typescript-eslint/consistent-type-definitions": "off" // Unconvinced by its utility; may be counterproductive }, "overrides": [ From be8bbb20a04455adf9fe5997a56854997a9bd678 Mon Sep 17 00:00:00 2001 From: Federico Date: Mon, 2 Dec 2024 21:08:50 +0700 Subject: [PATCH 8/8] PR review --- source/test/contentscript/api.test.ts | 6 ++--- source/test/helpers.ts | 2 +- source/thisTarget.ts | 32 +++++++++++++-------------- 3 files changed, 20 insertions(+), 20 deletions(-) diff --git a/source/test/contentscript/api.test.ts b/source/test/contentscript/api.test.ts index 7f39c28..62d7320 100644 --- a/source/test/contentscript/api.test.ts +++ b/source/test/contentscript/api.test.ts @@ -12,7 +12,7 @@ import { sleep, trackSettleTime, expectDuration, - senderisBackground, + senderIsBackground, senderIsCurrentPage, } from "../helpers.js"; import * as backgroundContext from "../background/api.js"; @@ -126,7 +126,7 @@ function runOnTarget(target: Target | PageTarget, expectedTitle: string) { const directSender = trace.at(-1); if (isBackground()) { - senderisBackground( + senderIsBackground( t, originalSender, "Messages should mention the current page (background) in trace[0]", @@ -140,7 +140,7 @@ function runOnTarget(target: Target | PageTarget, expectedTitle: string) { } if (!("page" in target && isContentScript())) { - senderisBackground( + senderIsBackground( t, directSender, "Messages originated in content scripts or background pages must come directly from the background page", diff --git a/source/test/helpers.ts b/source/test/helpers.ts index ab23c71..e4d2da8 100644 --- a/source/test/helpers.ts +++ b/source/test/helpers.ts @@ -77,7 +77,7 @@ export function senderIsCurrentPage( t.equal(sender?.url, location.href, message); } -export function senderisBackground( +export function senderIsBackground( t: test.Test, sender: Sender | undefined, message: string, diff --git a/source/thisTarget.ts b/source/thisTarget.ts index 826ca2d..3b2d69c 100644 --- a/source/thisTarget.ts +++ b/source/thisTarget.ts @@ -40,24 +40,24 @@ import { pEvent } from "p-event"; // Soft warning: Race conditions are possible. // This CANNOT be awaited because waiting for it means "I will handle the message." // If a message is received before this is ready, it will just have to be ignored. -export const thisTarget: KnownTarget = isBackground() - ? { page: "background" } - : isOffscreenDocument() - ? { page: "offscreen" } - : { - get page(): string { - // Extension pages have relative URLs to simplify comparison - const origin = location.protocol.startsWith("http") - ? location.origin - : ""; - - // Don't use the hash - return origin + location.pathname + location.search; - }, - }; +export const thisTarget: KnownTarget = (() => { + if (isBackground()) return { page: "background" }; + if (isOffscreenDocument()) return { page: "offscreen" }; + return { + get page(): string { + // Extension pages have relative URLs to simplify comparison + const origin = location.protocol.startsWith("http") + ? location.origin + : ""; + + // Don't use the hash + return origin + location.pathname + location.search; + }, + }; +})(); let tabDataStatus: "needed" | "pending" | "received" | "not-needed" | "error" = - // The background page doesn't have a tab + // Exclude contexts that don't have a tab associated to them isBackground() || isOffscreenDocument() ? "not-needed" : "needed"; export function getTabDataStatus(): typeof tabDataStatus {