Smail/test/frontend/runtime-deployment.test.mjs
smail d7837de561
Some checks are pending
Security Checks / security (push) Waiting to run
保存模拟部署迁移与最新构建校验阶段成果
2026-09-08 18:33:21 +08:00

62 lines
3.3 KiB
JavaScript

import assert from 'node:assert/strict'
import { mkdtemp, mkdir, readFile, writeFile } from 'node:fs/promises'
import os from 'node:os'
import path from 'node:path'
import test from 'node:test'
import { readDevelopmentRuntime, resolveRuntimeFile, runtimeRoot, sourceRoot } from '../../deploy/runtime-config.mjs'
import { fileDigest, sourceFingerprint } from '../../deploy/build-state.mjs'
test('开发配置只从模拟部署目录读取且不返回凭据字段', async () => {
const root = await mkdtemp(path.join(os.tmpdir(), 'smail-runtime-config-'))
await mkdir(path.join(root, 'config'))
await mkdir(path.join(root, 'ssl'))
await writeFile(path.join(root, 'config/config.json'), JSON.stringify({
generation: 9, domains: { web: 'mail.example.test' }, database: { password: 'not-exported' }
}))
await writeFile(path.join(root, 'config/ssl.json'), JSON.stringify({
tls: { certificateRef: 'ssl/public.crt', privateKeyRef: 'ssl/private.key' }
}))
await writeFile(path.join(root, 'ssl/public.crt'), 'certificate')
await writeFile(path.join(root, 'ssl/private.key'), 'key')
const runtime = readDevelopmentRuntime(root)
assert.equal(runtime.origin, 'https://mail.example.test')
assert.equal(runtime.generation, 9)
assert.equal(runtime.privateKeyPath, path.join(root, 'ssl/private.key'))
assert.equal(JSON.stringify(runtime).includes('not-exported'), false)
assert.equal(runtimeRoot, path.join(sourceRoot, 'yunx-test'))
assert.throws(() => resolveRuntimeFile(root, '../outside.key'))
assert.throws(() => resolveRuntimeFile(root, path.join(root, 'ssl/private.key')))
})
test('源码指纹检测编辑且忽略编译嵌入目录', async () => {
const root = await mkdtemp(path.join(os.tmpdir(), 'smail-build-state-'))
for (const name of ['backend', 'frontend', 'plugins/pmail_telegram_push', 'deploy']) {
await mkdir(path.join(root, name), { recursive: true })
}
await writeFile(path.join(root, 'backend/main.go'), 'package main')
const before = await sourceFingerprint(root)
await mkdir(path.join(root, 'backend/dist'))
await writeFile(path.join(root, 'backend/dist/index.html'), 'generated')
assert.equal(await sourceFingerprint(root), before)
await writeFile(path.join(root, 'backend/main.go'), 'package main\n')
assert.notEqual(await sourceFingerprint(root), before)
assert.equal((await fileDigest(path.join(root, 'backend/main.go'))).length, 64)
await writeFile(path.join(root, 'empty.exe'), '')
await assert.rejects(fileDigest(path.join(root, 'empty.exe')))
})
test('部署和启动必须完整构建、验证产物且不覆盖运行配置', async () => {
const read = name => readFile(path.join(sourceRoot, name), 'utf8')
const deploy = await read('deploy/deploy-runtime.ps1')
const start = await read('deploy/start-dev.ps1')
assert.ok(deploy.indexOf("'build.ps1'") < deploy.indexOf('Copy-Item'))
assert.match(deploy, /verify --deployed/)
assert.match(deploy, /deployment-history/)
assert.doesNotMatch(deploy, /Copy-Item[^\n]*(config|data|ssl)/)
assert.doesNotMatch(start, /SkipBuild|SkipFrontend/)
assert.match(start, /\$env:SMAIL_ROOT = \$runtime/)
assert.match(start, /\$workingDirectory = \$runtime/)
assert.match(start, /build-state\.mjs'\) verify --deployed/)
assert.match(await read('.gitignore'), /^\/yunx-test\/$/m)
})