65 lines
3.7 KiB
JavaScript
65 lines
3.7 KiB
JavaScript
import test from 'node:test'
|
|
import assert from 'node:assert/strict'
|
|
import { createRequire } from 'node:module'
|
|
import { mkdtempSync, mkdirSync, writeFileSync, readFileSync, rmSync } from 'node:fs'
|
|
import { tmpdir } from 'node:os'
|
|
import { join } from 'node:path'
|
|
import ts from 'typescript'
|
|
|
|
const require = createRequire(import.meta.url)
|
|
function load(path, resolve = require) {
|
|
const source = readFileSync(new URL(path, import.meta.url), 'utf8')
|
|
const code = ts.transpileModule(source, { compilerOptions: { target: ts.ScriptTarget.ES2022, module: ts.ModuleKind.CommonJS } }).outputText
|
|
const exports = {}
|
|
new Function('require', 'exports', code)(resolve, exports)
|
|
return exports
|
|
}
|
|
const sources = load('../server/utils/videoSources.ts')
|
|
const { buildSourceAssembly } = load('../server/utils/ffmpeg.ts')
|
|
|
|
test('eight extensions retain original bytes, not previously encoded assemblies, including after parent deletion', () => {
|
|
const root = mkdtempSync(join(tmpdir(), 'aigen-sources-'))
|
|
try {
|
|
let previous
|
|
for (let i = 0; i < 9; i++) {
|
|
const dir = join(root, String(i)); mkdirSync(dir)
|
|
const video = join(dir, 'video.mp4')
|
|
writeFileSync(video, `lossy-assembly-${i}`)
|
|
sources.preserveVideoSources(video, previous ? sources.videoSourcePaths(previous) : [], Buffer.from(`original-${i}`))
|
|
previous = video
|
|
}
|
|
rmSync(join(root, '0'), { recursive: true })
|
|
assert.deepEqual(sources.videoSourcePaths(previous).map(path => readFileSync(path, 'utf8')), Array.from({ length: 9 }, (_, i) => `original-${i}`))
|
|
} finally { rmSync(root, { recursive: true, force: true }) }
|
|
})
|
|
|
|
test('legacy video is a fixed baseline and assembly reads each original source once', () => {
|
|
assert.deepEqual(sources.videoSourcePaths(join(tmpdir(), 'legacy-video.mp4')), [join(tmpdir(), 'legacy-video.mp4')])
|
|
const graph = buildSourceAssembly(Array(7).fill(5), 512, 512, 24, true, true)
|
|
assert.equal((graph.filter.match(/xfade=transition/g) || []).length, 6)
|
|
assert.equal((graph.filter.match(/acrossfade=/g) || []).length, 6)
|
|
for (let i = 0; i < 7; i++) assert.equal(graph.filter.split(`[${i}:v]`).length - 1, 1)
|
|
assert.equal(graph.video, 'joinv6')
|
|
assert.ok(Math.abs(graph.duration - (35 - 6 * (0.12 + 1 / 24))) < 0.00001)
|
|
const fallback = buildSourceAssembly([5, 5, 5], 512, 512, 24, false, false)
|
|
assert.equal((fallback.filter.match(/concat=n=2/g) || []).length, 2)
|
|
})
|
|
|
|
test('refinement uses available standard nodes, and an unrelated saved image is never mistaken for a last frame', () => {
|
|
const graph = JSON.parse(readFileSync(new URL('../server/assets/extension_frame_refine.json', import.meta.url)))
|
|
assert.equal(Object.values(graph).some(node => node.class_type === 'BilateralFilterImage'), false)
|
|
assert.equal(graph['6'].inputs.lora_name, 'klein-consistency-V2.safetensors')
|
|
assert.deepEqual(graph['10'].inputs.pixels, ['1', 0])
|
|
assert.ok(graph['19'].inputs.blend_factor < 0.5)
|
|
const helpers = load('../server/utils/extensionFrame.ts', id => id.endsWith('.json') ? { default: graph } : id.startsWith('node:') ? require(id) : {})
|
|
assert.equal(helpers.extractAnchorImageFromHistory({ job: { outputs: { preview: { images: [{ filename: 'wrong.png' }] } } } }, 'job'), null)
|
|
assert.equal(helpers.extractAnchorImageFromHistory({ job: { outputs: { aigen_anchor_save: { images: [{ filename: 'last.png' }] } } } }, 'job').filename, 'last.png')
|
|
})
|
|
|
|
test('lossless handoff defaults on while explicit opt-out is preserved', () => {
|
|
const { parseSaveLosslessAnchor } = load('../utils/extensionFrame.ts')
|
|
assert.equal(parseSaveLosslessAnchor(undefined), true)
|
|
assert.equal(parseSaveLosslessAnchor(false), false)
|
|
assert.equal(parseSaveLosslessAnchor('false'), false)
|
|
})
|