import { test, expect } from '@playwright/test';
import * as fs from 'fs';
import * as os from 'os';
import * as path from 'path';
// Form mode is hosted by the unified tables.html bundle — same bytes the
// server returns for /
/form.html and //.yaml.html. Loading
// tables/dist/tables.html via file:// (named form.html in the temp dir
// so the URL pathname triggers form-mode in the dispatcher) is the
// closest offline mirror of what online callers actually receive.
const HTML_PATH = path.resolve('tables/dist/tables.html');
const HTML_RAW = fs.readFileSync(HTML_PATH, 'utf8');
const SAFETY_SCHEMA = {
type: 'object',
required: ['date', 'location'],
additionalProperties: false,
properties: {
date: { type: 'string', format: 'date' },
location: { type: 'string', enum: ['Site A', 'Site B', 'Site C'] },
hazards: {
type: 'array',
items: {
type: 'object',
required: ['kind', 'severity'],
properties: {
kind: { type: 'string' },
severity: { type: 'integer', minimum: 1, maximum: 5 },
notes: { type: 'string' },
},
},
},
additionalNotes: { type: 'string' },
},
};
const SAFETY_UI = {
location: { 'ui:widget': 'radio' },
hazards: { 'ui:options': { addable: true, removable: true } },
additionalNotes: { 'ui:widget': 'textarea' },
};
// Inject a complete form-context into the page before form bootstraps.
// Writes a patched copy of form.html to a temp file and navigates via
// file:// — page.setContent's about:blank origin doesn't expose
// localStorage, which trips up shared/theme.js. page.route can't intercept
// file://, so this is the cleanest path. The form is fully self-contained,
// so the temp file works without relative-resource resolution.
async function loadFormWithContext(page, context) {
const ctxJson = JSON.stringify(context).replace(/<\//g, '<\\/');
const replacement = ``;
const patched = HTML_RAW.replace(
/