// Screenshots of an area plugin's in-page side: the built X runtime (src-tauri/x-runtime.js) in a // static x.com fixture, with the given flags on, optionally after running one palette command (an // area's settings dialog). Run `node scripts/build-inject.mjs` first. Not a live X test. // // node scripts/area-plugins-shots.mjs 'name|path|flags|command|lang'... // node scripts/area-plugins-shots.mjs ../../verification/area-plugins/phase1 \ // 'navigation-settings|/home|navigation.focusMode,navigation.keyboardPlus|bt-navigation-plus.plugin.js:settings' // // `flags` are turned on over the defaults (comma separated); `command` is `:`. // Console errors and "[wayBetter for X] … failed" lines are printed and make the script exit 1. import { readFile } from 'node:fs/promises'; import { fileURLToPath } from 'node:url'; import { join } from 'node:path'; import { chromium } from 'playwright'; import { fixtureHtml } from './theme-matrix/fixtures.mjs'; const root = fileURLToPath(new URL('../', import.meta.url)); const runtime = await readFile(join(root, 'src-tauri/x-runtime.js'), 'utf8'); const [, , out, ...shots] = process.argv; if (!out || !shots.length) { console.error("usage: node scripts/area-plugins-shots.mjs 'name|path|flags|command'..."); process.exit(1); } const cellOf = path => (path.startsWith('/notifications') ? 'notifications' : /^\/(i\/chat|messages)/.test(path) ? 'chat' : path === '/home' ? 'home' : 'profile'); const browser = await chromium.launch(); let failed = 0; for (const spec of shots) { const [name, path = '/home', flags = '', command = ''] = spec.split('|'); const page = await browser.newPage({ viewport: { width: 1280, height: 860 }, deviceScaleFactor: 2, colorScheme: 'dark' }); const errors = []; page.on('pageerror', error => errors.push(error.message)); page.on('console', message => { if (message.type() === 'error') errors.push(message.text()); }); await page.route('https://x.com/**', route => route.fulfill({ contentType: 'text/html', body: fixtureHtml(cellOf(path), 'dark') })); await page.addInitScript(runtime); await page.goto(`https://x.com${path}`); await page.evaluate(list => { window.BetterTwttr.features.apply(Object.fromEntries(list.map(flag => [flag, true]))); }, flags.split(',').filter(Boolean)); await page.waitForTimeout(400); if (command) { const ran = await page.evaluate(id => window.BetterTwttr.api.commands.run(id), command); if (!ran) errors.push(`no command ${command} (registered: ${await page.evaluate(() => window.BetterTwttr.api.commands.list().map(item => item.id).join(', '))})`); await page.waitForTimeout(500); } await page.screenshot({ path: `${out}/${name}.png` }); console.log(name, errors.length ? `ERRORS: ${errors.join(' | ')}` : 'ok'); failed += errors.length ? 1 : 0; await page.close(); } await browser.close(); process.exit(failed ? 1 : 0);