import test from 'node:test' import assert from 'node:assert/strict' import { readFileSync, writeFileSync, unlinkSync } from 'node:fs' import { join } from 'node:path' import { tmpdir } from 'node:os' import { pathToFileURL } from 'node:url' import ts from 'typescript' const src = readFileSync(new URL('../utils/promptSequences.ts', import.meta.url), 'utf8') const js = ts.transpileModule(src, { compilerOptions: { target: ts.ScriptTarget.ES2022, module: ts.ModuleKind.ESNext } }).outputText const tmp = join(tmpdir(), `prompt-sequences-${process.pid}.mjs`) writeFileSync(tmp, js) const { assembleSceneText, assembleSequenceText, formatCharacterLine, emptyScene, cloneSceneForNext } = await import(pathToFileURL(tmp).href) unlinkSync(tmp) test('formatCharacterLine covers name/description cases', () => { assert.equal(formatCharacterLine({ name: 'Ada', description: 'tall' }), 'Ada: tall') assert.equal(formatCharacterLine({ name: 'Ada', description: '' }), 'Ada') assert.equal(formatCharacterLine({ name: '', description: 'tall' }), 'tall') assert.equal(formatCharacterLine({ name: '', description: '' }), '') }) test('assembleSceneText joins non-empty boxes with a single blank line', () => { const text = assembleSceneText({ style: 'oil paint', settings: 'night', characters: [ { name: 'Ada', description: 'tall' }, { name: '', description: '' }, { name: 'Bo', description: 'hat' } ], prompt: 'walks' }) assert.equal(text, 'oil paint\n\nnight\n\nAda: tall\nBo: hat\n\nwalks') }) test('assembleSequenceText uses double blank line between scenes and skips empties', () => { const text = assembleSequenceText({ name: 'ignored', scenes: [ { style: 's1', settings: '', characters: [], prompt: 'p1' }, { style: '', settings: '', characters: [{ name: '', description: '' }], prompt: '' }, { style: 's2', settings: 'set2', characters: [{ name: 'C', description: 'd' }], prompt: 'p2' } ] }) assert.equal(text, 's1\n\np1\n\n\ns2\n\nset2\n\nC: d\n\np2') assert.ok(!text.includes('ignored')) }) test('example shape is two jobs for desktop Batch', () => { const text = assembleSequenceText({ scenes: [ { style: 'style scene 1', settings: 'settings scene 1', characters: [ { name: 'Character one', description: 'desc' }, { name: 'Character two', description: 'desc' } ], prompt: 'prompt scene 1' }, { style: 'style scene 2', settings: 'settings scene 2', characters: [{ name: 'Character one', description: 'desc' }], prompt: 'prompt scene 2' } ] }) assert.equal( text, [ 'style scene 1', '', 'settings scene 1', '', 'Character one: desc', 'Character two: desc', '', 'prompt scene 1', '', '', 'style scene 2', '', 'settings scene 2', '', 'Character one: desc', '', 'prompt scene 2' ].join('\n') ) }) test('cloneSceneForNext copies fields with new ids', () => { const first = emptyScene(1) first.style = 'a' first.characters[0].name = 'Ada' const next = cloneSceneForNext(first, 2) assert.equal(next.title, 'Scene 2') assert.equal(next.style, 'a') assert.equal(next.characters[0].name, 'Ada') assert.notEqual(next.id, first.id) assert.notEqual(next.characters[0].id, first.characters[0].id) })