123/**4 * Regression check for a valid local import arriving during an invalid import's5 * INDEX -> Workshop error transition.6 *7 * Usage:8 * PLAYWRIGHT_MODULE=/path/to/playwright node tests/browser/import-transition-race.mjs9 * MIAU_URL=http://127.0.0.1:5192/ ... node tests/browser/import-transition-race.mjs10 */1112import assert from 'node:assert/strict';13import { mkdtemp, rm, writeFile } from 'node:fs/promises';14import { tmpdir } from 'node:os';15import { resolve } from 'node:path';1617const configuredPlaywright = process.env.PLAYWRIGHT_MODULE || 'playwright';18const playwrightModule = configuredPlaywright.startsWith('/')19 ? `${configuredPlaywright.replace(/\/$/, '')}${configuredPlaywright.endsWith('.js') ? '' : '/index.js'}`20 : configuredPlaywright;21const playwright = await import(playwrightModule);22const { chromium } = playwright.default || playwright;2324const projectRoot = resolve(new URL('..', import.meta.url).pathname, '..');25const baseUrl = process.env.MIAU_URL || 'http://127.0.0.1:5173/';26const timeout = Number(process.env.BROWSER_TIMEOUT || 8000);27const tempDir = await mkdtemp(`${tmpdir()}/miau-import-transition-`);28const invalidPath = resolve(tempDir, 'invalid.cjs');29const validPath = resolve(projectRoot, 'mods/example.cjs');30await writeFile(invalidPath, 'module.exports = null;\n');3132const browser = await chromium.launch({ headless: true });33const context = await browser.newContext({ viewport: { width: 1280, height: 800 } });34const page = await context.newPage();35const errors = [];36page.on('console', message => {37 if (message.type() === 'error') errors.push(`console: ${message.text()}`);38});39page.on('pageerror', error => errors.push(`page: ${error.message}`));4041try {42 await page.goto(`${baseUrl.replace(/\/$/, '')}/?dev=1`, { waitUntil: 'networkidle' });43 const scene = () => page.locator('.stage-shell').getAttribute('data-scene');44 await page.keyboard.press('Enter');45 await page.waitForFunction(() => document.querySelector('.stage-shell')?.dataset.scene === 'index', null, { timeout });46 await page.waitForTimeout(500);4748 const input = page.locator('#mod-input');49 await input.setInputFiles(invalidPath);50 // Deliberately dispatch the valid import before the invalid error transition51 // has finished. The valid pack must become the pending destination.52 await input.setInputFiles(validPath);53 await page.waitForFunction(() => document.querySelector('.stage-shell')?.dataset.scene === 'gift', null, { timeout });5455 assert.equal(await scene(), 'gift', 'valid import should win over the pending Workshop error transition');56 assert.match(await page.locator('#gift-title, body').first().textContent(), /Moon Cat|Gift/i);57 assert.deepEqual(errors, [], 'import transition should not emit browser errors');58 console.log('✓ invalid → valid local import resolves to Gift with no browser errors');59} finally {60 await context.close();61 await browser.close();62 await rm(tempDir, { recursive: true, force: true });63}