Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 7 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -57,11 +57,11 @@
"@types/chrome": "^0.3.4",
"@types/node": "^26.6.4",
"@vitest/coverage-v8": "^5.0.3",
"@wdio/cli": "^9.32.0",
"@wdio/globals": "^9.31.3",
"@wdio/local-runner": "^9.32.0",
"@wdio/mocha-framework": "^9.32.0",
"@wdio/spec-reporter": "^9.32.0",
"@wdio/cli": "^10.0.0",
"@wdio/globals": "^10.0.0",
"@wdio/local-runner": "^10.0.0",
"@wdio/mocha-framework": "^10.0.0",
"@wdio/spec-reporter": "^10.0.0",
"Coloris": "github:mdbassit/Coloris#v0.25.0",
"acorn": "8.19.0",
"dashjs": "5.2.1",
Expand All @@ -80,6 +80,7 @@
"sortablejs": "1.15.7",
"typescript": "^7.0.2",
"vitest": "^5.0.3",
"web-ext": "^10.7.0"
"web-ext": "^10.7.0",
"webdriverio": "^10.0.0"
}
}
1,202 changes: 440 additions & 762 deletions pnpm-lock.yaml

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion tests/e2e/bidi.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
// own realm. WebdriverIO connects to BiDi when the session starts and gives up after 10 s
// ("Could not connect to Bidi protocol of any candidate url in time", seen on the Windows
// runner). It then carries on over WebDriver classic without failing: browser.isBidi is
// false, and execute() and executeAsync() go to /execute/sync and /execute/async (9.32.0;
// false, and execute() goes to /execute/sync or /execute/async (9.32.0 and 10;
// only that connect, again on reloadSession(), decides isBidi). There a script runs in a sandbox,
// so its import() gets a module instance of its own (subtitle-search.e2e.mjs stubbed a
// RequestUtils the player never used, and saw no request), an ArrayBuffer made in it is
Expand Down
14 changes: 13 additions & 1 deletion tests/e2e/classic-helpers.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,18 @@ import {browser} from '@wdio/globals';

import {EXTENSION_ID} from './wdio.extension.conf.mjs';

/**
* Runs a function that reports through a callback, fn(...args, done), and gives what it
* passed to done: WebdriverIO 10 has no executeAsync. A script string, as execute() sends
* every function: over BiDi and over classic, it awaits the promise the script returns.
* @param {Function} fn - Called as fn(...args, done).
* @param {...*} args - Serialisable arguments.
* @return {Promise<*>}
*/
export function executeWithDone(fn, ...args) {
return browser.execute(`return new Promise((done) => (${fn.toString()}).apply(null, [...arguments, done]));`, ...args);
}

/**
* Runs an async function in Firefox's chrome context.
* @param {Function} fn - Called as fn(...args, done).
Expand All @@ -16,7 +28,7 @@ import {EXTENSION_ID} from './wdio.extension.conf.mjs';
export async function inChrome(fn, ...args) {
await browser.setMozContext('chrome');
try {
return await browser.executeAsync(fn, ...args);
return await executeWithDone(fn, ...args);
} finally {
await browser.setMozContext('content');
}
Expand Down
8 changes: 4 additions & 4 deletions tests/e2e/classic-specs/auto-enable-list.e2e.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -36,14 +36,14 @@ let siteHandle;
*/
async function setOptions(options) {
await browser.switchToWindow(extHandle);
await browser.executeAsync((json, done) => {
await browser.execute((json) => new Promise((done) => {
chrome.storage.local.set({options: json}, () => {
chrome.runtime.sendMessage({type: 'LOAD_OPTIONS'}, () => {
void chrome.runtime.lastError;
done(true);
});
});
}, JSON.stringify(options));
}), JSON.stringify(options));
// loadOptions rebuilds the redirect rule after it answers.
await browser.pause(1000);
}
Expand All @@ -55,7 +55,7 @@ async function setOptions(options) {
*/
async function tabMode(prefix) {
await browser.switchToWindow(extHandle);
return await browser.executeAsync((prefix, done) => {
return await browser.execute((prefix) => new Promise((done) => {
chrome.tabs.query({}, (tabs) => {
const tab = tabs.find((t) => t.url && t.url.startsWith(prefix));
if (!tab) {
Expand All @@ -64,7 +64,7 @@ async function tabMode(prefix) {
}
chrome.action.getBadgeText({tabId: tab.id}, (badge) => done(badge === 'On' ? 'on' : 'off'));
});
}, prefix);
}), prefix);
}

/**
Expand Down
12 changes: 6 additions & 6 deletions tests/e2e/classic-specs/content-cleanup.e2e.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -332,21 +332,21 @@ const clickToolbar = () => clickToolbarIn(siteHandle);
/** @return {Promise<?number>} The site tab's id. */
async function siteTabId() {
await browser.switchToWindow(extHandle);
return await browser.executeAsync((site, done) => {
return await browser.execute((site) => new Promise((done) => {
chrome.tabs.query({}, (tabs) => {
const tab = tabs.find((t) => t.url && t.url.startsWith(site + '/'));
done(tab ? tab.id : null);
});
}, SITE);
}), SITE);
}

/** @return {Promise<string>} The site tab's mode, 'on' or 'off'. */
async function tabMode() {
const tabId = await siteTabId();
await browser.switchToWindow(extHandle);
return await browser.executeAsync((tabId, done) => {
return await browser.execute((tabId) => new Promise((done) => {
chrome.action.getBadgeText({tabId}, (badge) => done(badge === 'On' ? 'on' : 'off'));
}, tabId);
}), tabId);
}

/**
Expand All @@ -359,14 +359,14 @@ async function tabMode() {
async function sendToPage(message, within = 0) {
const tabId = await siteTabId();
await browser.switchToWindow(extHandle);
return await browser.executeAsync((tabId, message, within, done) => {
return await browser.execute((tabId, message, within) => new Promise((done) => {
if (within) {
setTimeout(() => done({error: 'no answer'}), within);
}
chrome.tabs.sendMessage(tabId, message, {frameId: 0}, (response) => {
done(chrome.runtime.lastError ? {error: chrome.runtime.lastError.message} : response);
});
}, tabId, message, within);
}), tabId, message, within);
}

/**
Expand Down
4 changes: 2 additions & 2 deletions tests/e2e/classic-specs/content-overlays.e2e.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -217,13 +217,13 @@ const clickToolbar = () => clickToolbarIn(siteHandle);
/** @return {Promise<string>} The site tab's mode, 'on' or 'off'. */
async function tabMode() {
await browser.switchToWindow(extHandle);
const mode = await browser.executeAsync((site, done) => {
const mode = await browser.execute((site) => new Promise((done) => {
chrome.tabs.query({}, (tabs) => {
const tab = tabs.find((t) => t.url && t.url.startsWith(site + '/'));
if (!tab) return done('none');
chrome.action.getBadgeText({tabId: tab.id}, (badge) => done(badge === 'On' ? 'on' : 'off'));
});
}, SITE);
}), SITE);
await browser.switchToWindow(siteHandle);
return mode;
}
Expand Down
24 changes: 12 additions & 12 deletions tests/e2e/classic-specs/mpv-shortcut.e2e.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -157,12 +157,12 @@ async function tabMode(prefix = SITE + '/') {
*/
async function tabIdOf(prefix) {
await browser.switchToWindow(extHandle);
return await browser.executeAsync((site, done) => {
return await browser.execute((site) => new Promise((done) => {
chrome.tabs.query({}, (tabs) => {
const tab = tabs.find((t) => t.url && t.url.startsWith(site));
done(tab ? tab.id : null);
});
}, prefix);
}), prefix);
}

/**
Expand All @@ -172,15 +172,15 @@ async function tabIdOf(prefix) {
*/
async function modeOfTab(tabId) {
await browser.switchToWindow(extHandle);
return await browser.executeAsync((tabId, done) => {
return await browser.execute((tabId) => new Promise((done) => {
chrome.action.getTitle({tabId}, (title) => {
chrome.action.getBadgeText({tabId}, (badge) => {
if (title.includes('MPV')) done('mpv');
else if (badge === 'On') done('on');
else done('off');
});
});
}, tabId);
}), tabId);
}

/**
Expand All @@ -189,9 +189,9 @@ async function modeOfTab(tabId) {
*/
async function urlOfTab(tabId) {
await browser.switchToWindow(extHandle);
return await browser.executeAsync((tabId, done) => {
return await browser.execute((tabId) => new Promise((done) => {
chrome.tabs.get(tabId, (tab) => done(tab.url || ''));
}, tabId);
}), tabId);
}

/**
Expand Down Expand Up @@ -328,14 +328,14 @@ async function mainPlaying() {
*/
async function setOptions(options) {
await browser.switchToWindow(extHandle);
await browser.executeAsync((json, done) => {
await browser.execute((json) => new Promise((done) => {
chrome.storage.local.set({options: json}, () => {
chrome.runtime.sendMessage({type: 'LOAD_OPTIONS'}, () => {
void chrome.runtime.lastError;
done(true);
});
});
}, JSON.stringify(options));
}), JSON.stringify(options));
await browser.pause(500);
}

Expand Down Expand Up @@ -631,7 +631,7 @@ describe('The MPV keyboard shortcut (Alt+F)', function() {

// MPV mode on, allowlist empty: nothing here auto-starts MPV, so every
// switch below is the shortcut's doing.
await browser.executeAsync((done) => {
await browser.execute(() => new Promise((done) => {
chrome.storage.local.set({
options: JSON.stringify({mpvMode: true, mpvAllowlist: []}),
}, () => {
Expand All @@ -640,7 +640,7 @@ describe('The MPV keyboard shortcut (Alt+F)', function() {
done(true);
});
});
});
}));
await browser.pause(1000);

siteHandle = (await browser.getWindowHandles()).find((h) => h !== extHandle);
Expand Down Expand Up @@ -779,9 +779,9 @@ describe('The MPV keyboard shortcut (Alt+F)', function() {
// took a second press. Each key now has its own command.
it('binds Ctrl+Shift+F to the player\'s own command, not the toolbar button', async function() {
await browser.switchToWindow(extHandle);
const commands = await browser.executeAsync((done) => {
const commands = await browser.execute(() => new Promise((done) => {
chrome.commands.getAll().then((all) => done(all.map((c) => [c.name, c.shortcut || ''])));
});
}));
expect(Object.fromEntries(commands)).toEqual({
toggle_player: 'Ctrl+Shift+F',
toggle_mpv: 'Alt+F',
Expand Down
4 changes: 2 additions & 2 deletions tests/e2e/classic-specs/mpv-suspend.e2e.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ describe('MPV mode across a suspended background', function() {
return false;
}, {timeout: 20000, timeoutMsg: 'the extension page never opened'});

await browser.executeAsync((site, done) => {
await browser.execute((site) => new Promise((done) => {
chrome.storage.local.set({
options: JSON.stringify({mpvMode: true, mpvAllowlist: [site]}),
}, () => {
Expand All @@ -121,7 +121,7 @@ describe('MPV mode across a suspended background', function() {
done(true);
});
});
}, SITE);
}), SITE);
await browser.pause(1000);
await browser.closeWindow();
await browser.switchToWindow((await browser.getWindowHandles())[0]);
Expand Down
12 changes: 6 additions & 6 deletions tests/e2e/classic-specs/shortcut-page-cancels.e2e.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ async function pageKeys() {
*/
async function tabMode() {
await browser.switchToWindow(extHandle);
return await browser.executeAsync((site, done) => {
return await browser.execute((site) => new Promise((done) => {
chrome.tabs.query({}, (tabs) => {
const tab = tabs.find((t) => t.url && t.url.startsWith(site));
if (!tab) {
Expand All @@ -216,7 +216,7 @@ async function tabMode() {
});
});
});
}, SITE + '/');
}), SITE + '/');
}

/**
Expand Down Expand Up @@ -262,12 +262,12 @@ async function expectModeKept(expected, when) {
*/
async function rebind(name, shortcut) {
await browser.switchToWindow(extHandle);
await browser.executeAsync((name, shortcut, done) => {
await browser.execute((name, shortcut) => new Promise((done) => {
const p = shortcut === null ?
chrome.commands.reset(name) :
chrome.commands.update({name, shortcut});
p.then(() => done(true), (e) => done(String(e)));
}, name, shortcut);
}), name, shortcut);
}

describe('FastStream shortcuts on a page that cancels them', function() {
Expand Down Expand Up @@ -308,7 +308,7 @@ describe('FastStream shortcuts on a page that cancels them', function() {
}, {timeout: 20000, timeoutMsg: 'the extension page never opened'});

// MPV mode on, allowlist empty: every switch below is a shortcut's doing.
await browser.executeAsync((done) => {
await browser.execute(() => new Promise((done) => {
chrome.storage.local.set({
options: JSON.stringify({mpvMode: true, mpvAllowlist: []}),
}, () => {
Expand All @@ -317,7 +317,7 @@ describe('FastStream shortcuts on a page that cancels them', function() {
done(true);
});
});
});
}));
await browser.pause(1000);

siteHandle = (await browser.getWindowHandles()).find((h) => h !== extHandle);
Expand Down
8 changes: 4 additions & 4 deletions tests/e2e/classic-specs/toolbar-cycle-mpv.e2e.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ const clickToolbar = () => clickToolbarIn(siteHandle);
*/
async function tabMode() {
await browser.switchToWindow(extHandle);
return await browser.executeAsync((site, done) => {
return await browser.execute((site) => new Promise((done) => {
chrome.tabs.query({}, (tabs) => {
const tab = tabs.find((t) => t.url && t.url.startsWith(site + '/'));
if (!tab) {
Expand All @@ -76,7 +76,7 @@ async function tabMode() {
});
});
});
}, SITE);
}), SITE);
}

/**
Expand Down Expand Up @@ -172,7 +172,7 @@ describe('The MPV toolbar cycle (MPV -> Off -> On -> MPV)', function() {
return false;
}, {timeout: 20000, timeoutMsg: 'the extension page never opened'});

await browser.executeAsync((site, done) => {
await browser.execute((site) => new Promise((done) => {
chrome.storage.local.set({
options: JSON.stringify({mpvMode: true, mpvAllowlist: [site]}),
}, () => {
Expand All @@ -181,7 +181,7 @@ describe('The MPV toolbar cycle (MPV -> Off -> On -> MPV)', function() {
done(true);
});
});
}, SITE);
}), SITE);
await browser.pause(1000);

siteHandle = (await browser.getWindowHandles()).find((h) => h !== extHandle);
Expand Down
4 changes: 2 additions & 2 deletions tests/e2e/classic-specs/toolbar-off-race.e2e.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ const clickToolbar = (times) => clickToolbarIn(siteHandle, times);
*/
async function tabMode() {
await browser.switchToWindow(extHandle);
return await browser.executeAsync((site, done) => {
return await browser.execute((site) => new Promise((done) => {
chrome.tabs.query({}, (tabs) => {
const tab = tabs.find((t) => t.url && t.url.startsWith(site + '/'));
if (!tab) {
Expand All @@ -56,7 +56,7 @@ async function tabMode() {
}
chrome.action.getBadgeText({tabId: tab.id}, (badge) => done(badge === 'On' ? 'on' : 'off'));
});
}, SITE);
}), SITE);
}

/**
Expand Down
Loading
Loading