Files
pbakaus_impeccable/tests/oracle/cases/live-accept.mjs
T

166 lines
9.9 KiB
JavaScript

/**
* `live-accept` corpus: argument paths, HTML and JSX accept/discard
* (carbonize output, param baking inputs), receipts, lock contention,
* generated-file fallback, buffer scrub, and the Svelte component path
* (wrap with the linked compiler, then accept/discard the stub variant).
*/
import fs from 'node:fs';
import path from 'node:path';
import {
LIVE_FILES, linkSvelte, lockPathFor, stageWrappedHtml, stageWrappedJsx, write, writeBuffer,
} from '../live-helpers.mjs';
const F = LIVE_FILES;
const HTML = [...F, 'index.html'];
const JSX = [...F, 'src/**'];
const A = (id, workspace, args, extra = {}) => ({ id, verb: 'live-accept', workspace, args, files: [...F, ...(extra.snap || [])], ...extra });
const ID = 'ab12cd34';
export default [
A('live-accept-help', 'live-html', ['--help']),
A('live-accept-missing-id', 'live-html', ['--variant', '1']),
A('live-accept-invalid-id', 'live-html', ['--id', '../etc', '--variant', '1']),
A('live-accept-need-mode', 'live-html', ['--id', ID]),
A('live-accept-invalid-variant', 'live-html', ['--id', ID, '--variant', '1a']),
A('live-accept-invalid-variant-regex', 'live-html', ['--id', ID, '--variant', '.*']),
A('live-accept-markers-not-found', 'live-html', ['--id', 'nothere1', '--variant', '1']),
A('live-accept-target-missing-value', 'live-html', ['--id', ID, '--variant', '1', '--target']),
// --- HTML source-preview accept / discard ---
A('live-accept-html-variant-1-range', 'live-html', ['--id', ID, '--variant', '1', '--param-values', '{"lightness":0.65}'], { snap: ['index.html'], setup: stageWrappedHtml }),
A('live-accept-html-variant-2-steps', 'live-html', ['--id', ID, '--variant', '2', '--param-values', '{"face":"serif"}'], { snap: ['index.html'], setup: stageWrappedHtml }),
A('live-accept-html-variant-3-toggle', 'live-html', ['--id', ID, '--variant', '3', '--param-values', '{"italic":true}'], { snap: ['index.html'], setup: stageWrappedHtml }),
A('live-accept-html-no-params', 'live-html', ['--id', ID, '--variant', '2'], { snap: ['index.html'], setup: stageWrappedHtml }),
A('live-accept-html-malformed-params', 'live-html', ['--id', ID, '--variant', '1', '--param-values', '{bad'], { snap: ['index.html'], setup: stageWrappedHtml }),
A('live-accept-html-variant-missing', 'live-html', ['--id', ID, '--variant', '9'], { snap: ['index.html'], setup: stageWrappedHtml }),
A('live-accept-html-discard', 'live-html', ['--id', ID, '--discard'], { snap: ['index.html'], setup: stageWrappedHtml }),
A('live-accept-html-receipt-replay', 'live-html', ['--id', ID, '--variant', '1'], { snap: ['index.html'], setup: stageWrappedHtml, steps: [{}, {}] }),
A('live-accept-html-receipt-conflict', 'live-html', [], { snap: ['index.html'], setup: stageWrappedHtml, steps: [{ args: ['--id', ID, '--variant', '1'] }, { args: ['--id', ID, '--variant', '2'] }, { args: ['--id', ID, '--discard'] }] }),
A('live-accept-html-discard-then-accept', 'live-html', [], { snap: ['index.html'], setup: stageWrappedHtml, steps: [{ args: ['--id', ID, '--discard'] }, { args: ['--id', ID, '--variant', '1'] }] }),
A('live-accept-html-no-css-block', 'live-html', ['--id', ID, '--variant', '2'], {
snap: ['index.html'],
setup: (ws) => {
stageWrappedHtml(ws);
const p = path.join(ws, 'index.html');
fs.writeFileSync(p, fs.readFileSync(p, 'utf8').replace(/ {8}<style data-impeccable-css="ab12cd34">[\s\S]*?<\/style>\n/, ''));
},
}),
A('live-accept-generated-file', 'live-html', ['--id', ID, '--variant', '1'], {
snap: ['dist/**'],
setup: (ws) => {
stageWrappedHtml(ws);
const wrapped = fs.readFileSync(path.join(ws, 'index.html'), 'utf8');
fs.writeFileSync(path.join(ws, 'index.html'), '<html></html>\n');
write(ws, 'dist/generated.html', '<!-- @generated by build.js. DO NOT EDIT. -->\n' + wrapped);
},
}),
A('live-accept-source-locked', 'live-html', ['--id', ID, '--variant', '1'], {
// Lock file names hash the absolute source path, so they are not snapshotted.
files: ['index.html', '.impeccable/live/accept-receipts/**'],
setup: (ws) => {
stageWrappedHtml(ws);
// The recording process itself owns the lock, so it is alive for the whole run.
write(ws, lockPathFor(ws, 'index.html'), JSON.stringify({ owner: 'oracle', token: 'x', pid: process.pid, at: 1, file: path.join(ws, 'index.html') }));
},
}),
A('live-accept-stale-lock-dead-pid', 'live-html', ['--id', ID, '--variant', '1'], {
files: ['index.html', '.impeccable/live/accept-receipts/**'],
setup: (ws) => {
stageWrappedHtml(ws);
write(ws, lockPathFor(ws, 'index.html'), JSON.stringify({ owner: 'oracle', token: 'x', pid: 2147483646, at: 1, file: path.join(ws, 'index.html') }));
},
}),
A('live-accept-scrubs-buffer-for-page', 'live-html', ['--id', ID, '--variant', '1', '--page-url', '/'], {
snap: ['index.html'],
setup: (ws) => {
stageWrappedHtml(ws);
writeBuffer(ws, [
{ id: 'e1', pageUrl: '/', element: { tagName: 'h1' }, ops: [{ ref: 'h1', tag: 'h1', originalText: 'Oracle Fixture', newText: 'Renamed' }], stagedAt: '2026-08-01T00:00:00.000Z' },
{ id: 'e2', pageUrl: '/', element: { tagName: 'p' }, ops: [{ ref: 'p', tag: 'p', originalText: 'Unrelated copy', newText: 'Other' }], stagedAt: '2026-08-01T00:00:00.000Z' },
{ id: 'e3', pageUrl: '/about', element: { tagName: 'h1' }, ops: [{ ref: 'h1', tag: 'h1', originalText: 'Oracle Fixture', newText: 'Renamed' }], stagedAt: '2026-08-01T00:00:00.000Z' },
]);
},
}),
A('live-accept-no-page-url-keeps-buffer', 'live-html', ['--id', ID, '--variant', '1'], {
snap: ['index.html'],
setup: (ws) => {
stageWrappedHtml(ws);
writeBuffer(ws, [{ id: 'e1', pageUrl: '/', element: { tagName: 'h1' }, ops: [{ ref: 'h1', tag: 'h1', originalText: 'Oracle Fixture', newText: 'Renamed' }], stagedAt: '2026-08-01T00:00:00.000Z' }]);
},
}),
A('live-accept-source-shadow-deprecated', 'live-html', ['--id', ID, '--variant', '1'], {
snap: ['index.html'],
setup: (ws) => {
stageWrappedHtml(ws);
const p = path.join(ws, 'index.html');
fs.writeFileSync(p, fs.readFileSync(p, 'utf8').replace('data-impeccable-variant-count="3"', 'data-impeccable-variant-count="3" data-impeccable-preview="source-shadow"'));
},
}),
// --- JSX source-preview accept / discard ---
A('live-accept-jsx-variant-1', 'live-vite', ['--id', ID, '--variant', '1', '--param-values', '{"lightness":0.4}'], { snap: ['src/**'], setup: stageWrappedJsx }),
A('live-accept-jsx-variant-3-toggle-off', 'live-vite', ['--id', ID, '--variant', '3', '--param-values', '{"italic":false}'], { snap: ['src/**'], setup: stageWrappedJsx }),
A('live-accept-jsx-discard', 'live-vite', ['--id', ID, '--discard'], { snap: ['src/**'], setup: stageWrappedJsx }),
A('live-accept-jsx-from-subdir', 'live-vite', ['--id', ID, '--variant', '2'], { snap: ['src/**'], setup: stageWrappedJsx, cwd: 'src' }),
// --- Svelte component preview: wrap (linked compiler), then accept / discard ---
{
id: 'live-accept-svelte-component-accept', workspace: 'live-sveltekit', files: [...F, 'src/**'], setup: linkSvelte,
steps: [
{ verb: 'live-wrap', args: ['--id', ID, '--classes', 'hero-title', '--tag', 'h1'] },
{ verb: 'live-accept', args: ['--id', ID, '--variant', '1'] },
],
},
{
id: 'live-accept-svelte-component-styled-variant', workspace: 'live-sveltekit', files: [...F, 'src/**'], setup: linkSvelte,
steps: [
{ verb: 'live-wrap', args: ['--id', ID, '--classes', 'hero-title', '--tag', 'h1'] },
{
verb: 'live-accept', args: ['--id', ID, '--variant', '2', '--param-values', '{"lead":1.8,"density":"snug"}'],
// The agent's variant: the stub's script/markup kept, a new style block
// with param hooks, and params.json declaring them.
setup: (ws) => {
const dir = path.join(ws, 'node_modules/.impeccable-live', ID);
const stub = fs.readFileSync(path.join(dir, 'v2.svelte'), 'utf8');
const head = stub.slice(0, stub.indexOf('<style>'));
fs.writeFileSync(path.join(dir, 'v2.svelte'), head + '<style>\n .hero-title {\n font-weight: 900;\n line-height: var(--p-lead, 1.2);\n letter-spacing: 0.14em;\n }\n :global([data-p-density="snug"]) .hero-title { letter-spacing: 0; }\n</style>\n');
fs.writeFileSync(path.join(dir, 'params.json'), JSON.stringify({ 2: [
{ id: 'lead', kind: 'range', min: 1, max: 2, step: 0.1, default: 1.2, label: 'Lead' },
{ id: 'density', kind: 'steps', default: 'airy', label: 'Density', options: [{ value: 'airy', label: 'Airy' }, { value: 'snug', label: 'Snug' }] },
] }, null, 2));
},
},
],
},
{
id: 'live-accept-svelte-component-discard', workspace: 'live-sveltekit', files: [...F, 'src/**'], setup: linkSvelte,
steps: [
{ verb: 'live-wrap', args: ['--id', ID, '--classes', 'expense-list', '--tag', 'ul'] },
{ verb: 'live-accept', args: ['--id', ID, '--discard'] },
{ verb: 'live-accept', args: ['--id', ID, '--discard'] },
],
},
{
id: 'live-accept-svelte-component-variant-missing', workspace: 'live-sveltekit', files: [...F, 'src/**'], setup: linkSvelte,
steps: [
{ verb: 'live-wrap', args: ['--id', ID, '--classes', 'hero-title', '--tag', 'h1'] },
{ verb: 'live-accept', args: ['--id', ID, '--variant', '7'] },
],
},
{
id: 'live-accept-svelte-insert-empty-variant', workspace: 'live-sveltekit', files: [...F, 'src/**'],
steps: [
{ verb: 'live-insert', args: ['--id', ID, '--position', 'after', '--element-id', 'features'] },
{ verb: 'live-accept', args: ['--id', ID, '--variant', '1'] },
],
},
{
id: 'live-accept-svelte-fallback-source-wrapper', workspace: 'live-sveltekit', files: [...F, 'src/**'],
// No compiler: wrap wrote a plain source wrapper into the .svelte route.
steps: [
{ verb: 'live-wrap', args: ['--id', ID, '--classes', 'hero-title', '--tag', 'h1'] },
{ verb: 'live-accept', args: ['--id', ID, '--discard'] },
],
},
];