77 lines
4.2 KiB
JavaScript
77 lines
4.2 KiB
JavaScript
import test from 'node:test'
|
|
import assert from 'node:assert/strict'
|
|
import { readFileSync } from 'node:fs'
|
|
import ts from 'typescript'
|
|
|
|
const vue = readFileSync(new URL('../pages/index.vue', import.meta.url), 'utf8')
|
|
const script = vue.split('<script setup lang="ts">')[1].split('</script>')[0]
|
|
const tree = ts.createSourceFile('index.ts', script, ts.ScriptTarget.Latest, true)
|
|
function action(name, scope) {
|
|
const node = tree.statements.find(n => ts.isFunctionDeclaration(n) && n.name?.text === name)
|
|
assert.ok(node, `${name} exists`)
|
|
const code = ts.transpileModule(node.getText(tree), { compilerOptions: { target: ts.ScriptTarget.ES2022 } }).outputText
|
|
return new Function(...Object.keys(scope), `${code}; return ${name}`)(...Object.values(scope))
|
|
}
|
|
function fixture() {
|
|
const current = { id: 'displayed', settings: { steps: 24 } }
|
|
const state = { input: 'existing input', reference: 'existing reference', prompt: 'current prompt', steps: 19, engine: 'flux', mode: 'generate' }
|
|
const calls = []
|
|
return { state, calls, current, scope: {
|
|
editResultUrl: { value: '/api/library/stills/displayed' }, lastV2StillId: { value: 'older-generation' }, editDownloadName: { value: 'displayed' },
|
|
stillIdFromLibraryUrl: () => 'displayed', stills: { value: [current, { id: 'older-generation' }] },
|
|
usingReferenceBusy: { value: false }, usingInputSettingsBusy: { value: false },
|
|
$fetch: async () => new Blob(['pixels'], { type: 'image/png' }), File,
|
|
readFile: (file, options) => { state.input = file; calls.push(options) },
|
|
setEditRef: file => { state.reference = file },
|
|
useStillAsInput: async still => { calls.push(still.id) },
|
|
loadLibrary: async () => {}, scrollToStudioInput: () => {}, toast: () => {},
|
|
selectStudioKind: () => { throw new Error('Must not change workspace') },
|
|
setV2Engine: () => { throw new Error('Must not change engine') },
|
|
resetImage: () => { throw new Error('Must not clear input') }
|
|
} }
|
|
}
|
|
test('input-still action loads only pixels and preserves current settings', async () => {
|
|
const f = fixture()
|
|
await action('useEditAsInput', f.scope)()
|
|
assert.ok(f.state.input instanceof File)
|
|
assert.deepEqual(f.calls, [{ stillId: 'displayed', keepThumbnailPref: true }])
|
|
assert.equal(f.state.prompt, 'current prompt'); assert.equal(f.state.steps, 19)
|
|
assert.equal(f.state.reference, 'existing reference')
|
|
})
|
|
test('reference action changes only the reference, preserving input, prompt, engine and mode', async () => {
|
|
const f = fixture()
|
|
await action('useOutputAsFluxReference', f.scope)()
|
|
assert.ok(f.state.reference instanceof File)
|
|
assert.deepEqual({ ...f.state, reference: null }, { input: 'existing input', reference: null, prompt: 'current prompt', steps: 19, engine: 'flux', mode: 'generate' })
|
|
})
|
|
test('full input action restores the displayed image settings instead of the previous generation', async () => {
|
|
const f = fixture()
|
|
await action('useOutputWithSettings', f.scope)()
|
|
assert.deepEqual(f.calls, ['displayed'])
|
|
})
|
|
|
|
for (const from of ['edit', 'video']) {
|
|
for (const kind of ['still', 'clip']) {
|
|
for (const covered of [false, true]) {
|
|
test(`output navigation carries ${covered ? 'covered' : 'revealed'} state from ${from} to ${kind}`, () => {
|
|
const target = { id: 'next', hideInput: true, hideThumbnail: true }
|
|
const ref = value => ({ value })
|
|
const scope = {
|
|
outputNavigationItems: ref([{ kind, item: { id: 'first' } }, { kind, item: target }]),
|
|
outputNavigationIndex: ref(0), outputPreviewKind: ref(from),
|
|
editAwaitingReveal: ref(covered), awaitingReveal: ref(covered),
|
|
concealEditOutput: ref(false), concealOutput: ref(false),
|
|
lastV2StillId: ref('first'), editBusy: ref(false), videoBusy: ref(false),
|
|
editStatusMessage: ref(''), statusMessage: ref(''), player: ref({ pause() {} }),
|
|
openStill(item) { assert.equal(item, target); scope.editAwaitingReveal.value = true },
|
|
openClip(item) { assert.equal(item, target); scope.awaitingReveal.value = true }
|
|
}
|
|
action('stepOutput', scope)(-1)
|
|
assert.equal(kind === 'still' ? scope.editAwaitingReveal.value : scope.awaitingReveal.value, covered)
|
|
assert.equal(target.hideInput, true)
|
|
assert.equal(target.hideThumbnail, true)
|
|
})
|
|
}
|
|
}
|
|
}
|