gongxiangp2/scripts/desktop-template-pack-context.test.mjs
WuYongJie 93fc28f1bb feat(client): add native template slots and safe cloud version restore
Support explicit current-output A/B fill, protected edited drafts, scoped cloud update offers and atomic native restore with stale-open CAS. Preserve original unknown requests, improve Pi conversation continuity and native DPI/navigation reads, and publish the authenticated template metadata contract.

Validated: native backend 172 passed/5 environment tests ignored, UI 110, Pi 53, template/rule API 24 and native cloud contract 6; strict Clippy, layering and wasm. Real S01 selected B, edited/undo-redo, PCraft reopen and layered PSD roundtrip pass with exact pixels. Full nine-output generation and Photoshop acceptance remain open.
2026-10-23 21:27:06 +08:00

61 lines
3.2 KiB
JavaScript

import assert from 'node:assert/strict'
import { promises as fs } from 'node:fs'
import path from 'node:path'
import { fileURLToPath } from 'node:url'
import { createRequire } from 'node:module'
import test from 'node:test'
const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..')
const require = createRequire(path.join(root, 'package.json'))
// Reuse the existing TypeScript parser and ignore matcher. This is a source-input gate for
// the repository's current literal/glob rules, not a replacement for a real Docker build.
const ts = require('typescript')
const ignore = require('ignore')
const expected = [
'lib/desktop-client/template-packs/gj-desk-dnz0385-native-v1.json',
'lib/desktop-client/template-packs/yjd-desk-dnz0385-native-v1.json',
]
const policy = await fs.readFile(path.join(root, '.dockerignore'), 'utf8')
const sourcePath = 'lib/desktop-client/template-packs.ts'
const source = ts.createSourceFile(sourcePath, await fs.readFile(path.join(root, sourcePath), 'utf8'), ts.ScriptTarget.Latest, true)
const imports = source.statements
.filter(item => ts.isImportDeclaration(item) && ts.isStringLiteral(item.moduleSpecifier) && item.moduleSpecifier.text.endsWith('.json'))
.map(item => path.posix.normalize(path.posix.join(path.posix.dirname(sourcePath), item.moduleSpecifier.text)))
.sort()
const matcher = ignore().add(policy)
test('each statically imported template package exists and survives the build-context rules', async () => {
assert.deepEqual(imports, expected, 'Review any new template import and add only its precise build input')
for (const file of imports) {
assert.equal(matcher.ignores(file), false, `Template import excluded from build context: ${file}`)
const info = await fs.stat(path.join(root, file))
assert.ok(info.isFile() && info.size > 0 && info.size <= 600_000, `Invalid template input: ${file}`)
assert.equal(JSON.parse(await fs.readFile(path.join(root, file), 'utf8')).schemaVersion, 1)
}
})
test('the package exceptions name exact files instead of opening the template directory', () => {
const exceptions = policy.split(/\r?\n/).map(line => line.trim())
.filter(line => line.startsWith('!') && line.includes('template-packs'))
assert.deepEqual(exceptions, expected.map(file => '!' + file))
})
test('other JSON, local authorization, uploads and private task data stay excluded', () => {
for (const file of [
'lib/desktop-client/template-packs/unreviewed-template.json',
'lib/desktop-client/template-packs/customer-session.json',
'lib/desktop-client/private-credentials.json',
'output/template-slots-20261023/profile-local-qa/jiansun/settings.json',
'.private/connection.json',
'detail-generator-private/project/request.json',
'uploads/product/source.json',
'.env.production',
'apps/detail-photocraft/local-settings.json',
]) assert.equal(matcher.ignores(file), true, `Sensitive or unrelated input reopened: ${file}`)
})
test('removing these exact exceptions reproduces the missing-package build input failure', () => {
const before = ignore().add(policy.split(/\r?\n/).filter(line => !expected.some(file => line.trim() === '!' + file)).join('\n'))
for (const file of imports) assert.equal(before.ignores(file), true)
})