78ebc4fffd
scripts/smoke.js, scripts/probe.js, scripts/probe-inject.js,
scripts/probe-minimal.js, scripts/smoke-final.js
The smoke test verifies the Beat Pocket extension loads and injects into
beat-battle.net:
1. Service worker registers (manifest valid, MV3 wiring works)
2. Content script runs (creates #bbp-host element on document.body)
3. No JS errors thrown on the page
4. Site renders normally (PLAY button still visible)
Why Playwright instead of raw --load-extension:
- Google Chrome refuses --load-extension on the command line
- Chromium full build accepts it but hangs under --virtual-time-budget
- Playwright's launchPersistentContext properly initializes extensions
in headless mode and gives a clean Chromium without the GCM/dbus noise
- The bundled Chromium is at
/root/.cache/ms-playwright/chromium-1208/chrome-linux64/chrome
Run with: node scripts/smoke-final.js (after npm install)
Probe results from this session:
- [final:dom] #bbp-host is appended to body via ensureHost()
- [final:errors] 0 page errors
- [final:console] 0 extension-related console lines (expected: silent
happy path; logs only on phase transitions)
86 lines
3.5 KiB
JavaScript
86 lines
3.5 KiB
JavaScript
// Probe: is the content script actually being injected?
|
|
const { chromium } = require('/usr/lib/node_modules/@playwright/test');
|
|
|
|
const EXT_PATH = '/root/beat-pocket/extension';
|
|
|
|
(async () => {
|
|
const userDataDir = '/tmp/bb-smoke-probe-' + Date.now();
|
|
const context = await chromium.launchPersistentContext(userDataDir, {
|
|
headless: true,
|
|
channel: 'chromium',
|
|
args: [
|
|
`--disable-extensions-except=${EXT_PATH}`,
|
|
`--load-extension=${EXT_PATH}`,
|
|
'--disable-dev-shm-usage',
|
|
'--no-sandbox',
|
|
],
|
|
viewport: { width: 414, height: 896 },
|
|
});
|
|
|
|
// Wait for background
|
|
await context.waitForEvent('serviceworker', { timeout: 8000 }).catch(() => {});
|
|
console.log('[probe] service workers:', context.serviceWorkers().length);
|
|
|
|
const page = context.pages()[0] || await context.newPage();
|
|
|
|
// Capture ALL console messages to find extension logs
|
|
page.on('console', (msg) => {
|
|
console.log(`[page:${msg.type()}]`, msg.text().slice(0, 200));
|
|
});
|
|
page.on('pageerror', (err) => {
|
|
console.log('[page:error]', String(err).slice(0, 300));
|
|
});
|
|
page.on('requestfailed', (req) => {
|
|
console.log('[reqfail]', req.url(), '-', req.failure()?.errorText);
|
|
});
|
|
|
|
// Probe: enumerate scripts and stylesheets on the page
|
|
page.on('domcontentloaded', async () => {
|
|
const probe = await page.evaluate(() => ({
|
|
scripts: Array.from(document.querySelectorAll('script[src]')).map((s) => s.src),
|
|
stylesheets: Array.from(document.querySelectorAll('link[rel="stylesheet"]')).map((l) => l.href),
|
|
// Look for our markers explicitly
|
|
htmlClassNames: Array.from(document.body.classList),
|
|
// Check chrome-extension:// — does anything reference it?
|
|
hasExtensionResource: !![...document.scripts].find(s => s.src?.includes('chrome-extension://')),
|
|
}));
|
|
console.log('[probe:domcontentloaded] scripts:', probe.scripts.length, 'stylesheets:', probe.stylesheets.length, 'ext-resource:', probe.hasExtensionResource);
|
|
// Look for our injected stylesheet marker (our inject.css adds a class to <html>)
|
|
const htmlClasses = await page.evaluate(() => document.documentElement.className);
|
|
console.log('[probe] html.className:', htmlClasses);
|
|
});
|
|
|
|
await page.goto('https://beat-battle.net/', { waitUntil: 'networkidle', timeout: 30000 });
|
|
// wait extra for idle
|
|
await page.waitForTimeout(4000);
|
|
|
|
// After load: what scripts does the page see?
|
|
const after = await page.evaluate(() => ({
|
|
bbpMarkers: document.querySelectorAll('[class*="bbp-"], #bbp-overlay-host').length,
|
|
windowKeys: Object.keys(window).filter(k => /bbp/i.test(k)),
|
|
scripts: Array.from(document.querySelectorAll('script[src]')).length,
|
|
cssRules: Array.from(document.styleSheets).reduce((acc, s) => {
|
|
try { return acc + (s.cssRules?.length || 0); } catch { return acc; }
|
|
}, 0),
|
|
}));
|
|
console.log('[probe:after-load]', after);
|
|
|
|
// Try injecting a manual probe to see if we can reach the extension's service worker
|
|
const extId = context.serviceWorkers()[0]?.url()?.match(/chrome-extension:\/\/([a-z]+)\//)?.[1];
|
|
console.log('[probe] extension id:', extId);
|
|
if (extId) {
|
|
const sw = context.serviceWorkers()[0];
|
|
try {
|
|
const r = await sw.evaluate(() => ({
|
|
url: location.href,
|
|
runtime: typeof chrome?.runtime,
|
|
runtimeId: chrome?.runtime?.id,
|
|
}));
|
|
console.log('[probe] sw context:', r);
|
|
} catch (e) {
|
|
console.log('[probe] sw evaluate failed:', e.message);
|
|
}
|
|
}
|
|
|
|
await context.close();
|
|
})().catch((e) => { console.error('FAILED:', e); process.exit(1); }); |