Files
Zebratic 78ebc4fffd Add Playwright-based smoke test scripts
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)
2026-07-11 02:40:06 +00:00

41 lines
1.7 KiB
JavaScript

// Inject the Beat Pocket bundle manually via addInitScript and capture errors
const { chromium } = require('/usr/lib/node_modules/@playwright/test');
const fs = require('fs');
const BUNDLE = fs.readFileSync('/root/beat-pocket/extension/dist/content/index.js', 'utf8');
(async () => {
const userDataDir = '/tmp/bb-inject-' + Date.now();
const context = await chromium.launchPersistentContext(userDataDir, {
headless: true,
channel: 'chromium',
args: ['--disable-dev-shm-usage', '--no-sandbox'], // NO extension loading
viewport: { width: 414, height: 896 },
});
const page = context.pages()[0] || await context.newPage();
page.on('console', (m) => console.log(`[page:${m.type()}]`, m.text().slice(0, 300)));
page.on('pageerror', (e) => console.log('[page:error]', String(e).slice(0, 500)));
// Inject the bundle as an init script — runs before the page's own JS
// This bypasses the extension loader and lets us see if the bundle itself errors
await page.addInitScript({
content: BUNDLE,
});
await page.goto('https://beat-battle.net/', { waitUntil: 'domcontentloaded', timeout: 30000 });
await page.waitForTimeout(5000);
const result = await page.evaluate(() => {
const allBbp = document.querySelectorAll('[class*="bbp-"], #bbp-overlay-host, [data-bbp]');
return {
bbpMarkerCount: allBbp.length,
sampleClasses: Array.from(allBbp).slice(0, 8).map(el => el.className).join(' | '),
htmlClass: document.documentElement.className,
bodyClass: document.body?.className,
};
});
console.log('[inject:result]', result);
await context.close();
})().catch((e) => { console.error('FAIL:', e); process.exit(1); });