with one click
extension-real-browser-testing
// Test browser extensions in real browsers using built artifacts, Edge + Playwright automation, runtime-message triggering, DOM debugging, and truthful screenshot capture.
// Test browser extensions in real browsers using built artifacts, Edge + Playwright automation, runtime-message triggering, DOM debugging, and truthful screenshot capture.
Create a pull request, optionally for the issue provided as argument
Prepare all work before creating a pull request, optionally for the issue provided as argument
Use when writing or reviewing database/config migration scripts or migration registries. Enforces frozen-snapshot migrations, safe registration, and lean import boundaries.
| name | extension-real-browser-testing |
| description | Test browser extensions in real browsers using built artifacts, Edge + Playwright automation, runtime-message triggering, DOM debugging, and truthful screenshot capture. |
| metadata | {"author":"read-frog","version":"1.1.0"} |
Use this skill when you need to validate extension behavior in a real browser instead of guessing from unit tests, jsdom, or static screenshots.
Apply this skill when:
build, zip, or unpacked installation| Topic | Reference |
|---|---|
| Browser discovery, Edge launch patterns, unpacked extension loading | references/launching.md |
| Real-browser verification workflow, debugging heuristics, read-frog capture recipe | references/workflow.md |
dev behavior proves anything about build..output/<browser>-mv3 or the equivalent build directory.For this repository and machine, Edge + local Playwright was the most reliable path for unpacked-extension automation.
Important environment lessons:
launchPersistentContext and a fresh profile.chrome.storage.local from the Playwright service-worker target was unreliable here.chrome.* there was reliable.If Chrome behaves strangely, switch to Edge instead of continuing to guess.
For read-frog page translation, a reliable automation path was:
chrome-extension://<id>/popup.html.chrome.storage.local instead of assuming defaults..read-frog-spinner nodes and record live DOM evidence.Example setup from the popup page:
const setup = await popup.evaluate(async ({ targetUrl }) => {
const tab = (await chrome.tabs.query({})).find(item => item.url === targetUrl);
if (!tab?.id) throw new Error(`Could not find tab for ${targetUrl}`);
const current = await chrome.storage.local.get('config');
const config = current.config ?? {};
config.language = {
...(config.language ?? {}),
sourceCode: 'auto',
targetCode: 'cmn',
};
config.translate = {
...(config.translate ?? {}),
providerId: 'microsoft-translate-default',
mode: 'bilingual',
page: {
...(config.translate?.page ?? {}),
range: 'all',
},
requestQueueConfig: {
...(config.translate?.requestQueueConfig ?? {}),
rate: 1,
capacity: 1,
},
batchQueueConfig: {
...(config.translate?.batchQueueConfig ?? {}),
maxItemsPerBatch: 1,
maxCharactersPerBatch: 160,
},
};
await chrome.storage.local.set({ config });
await chrome.runtime.sendMessage({
id: Date.now(),
type: 'tryToSetEnablePageTranslationByTabId',
data: { tabId: tab.id, enabled: true },
timestamp: Date.now(),
});
return {
tabId: tab.id,
targetCode: config.language.targetCode,
};
}, { targetUrl: page.url() });
Good loading-time evidence for read-frog:
await page.waitForFunction(
() => document.querySelectorAll('.read-frog-spinner').length >= 4,
null,
{ timeout: 45000 },
);
const loadingEvidence = await page.evaluate(() => ({
spinnerCount: document.querySelectorAll('.read-frog-spinner').length,
sampleSpinnerStyles: Array.from(document.querySelectorAll('.read-frog-spinner'))
.slice(0, 3)
.map(node => node.getAttribute('style')),
}));
Good completion-time evidence for read-frog:
await page.waitForFunction(
() => {
const wrappers = Array.from(document.querySelectorAll('.read-frog-translated-content-wrapper'));
return wrappers.some(node => /[\u3400-\u9FFF]/.test(node.textContent || ''));
},
null,
{ timeout: 120000 },
);
For UI PRs:
Important note from this workflow:
For reproducible browser bugs, collect at least:
dev, build, unpacked install, or store installreferences/launching.md for exact Edge launch patterns.references/workflow.md for the real-browser checklist, debugging heuristics, and read-frog capture recipe.