Smail/test/frontend/output-paths.test.mjs
smail 882171915c
Some checks are pending
Security Checks / security (push) Waiting to run
优化开发启动权限并减小前端首屏体积
2026-09-06 23:26:55 +08:00

92 lines
4.9 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import assert from 'node:assert/strict'
import { readFile } from 'node:fs/promises'
import path from 'node:path'
import { fileURLToPath } from 'node:url'
import test from 'node:test'
import { buildPlan, hostTarget, plugins, targets } from '../../deploy/build-plugins.mjs'
import { packagePlan } from '../../deploy/package.mjs'
const root = fileURLToPath(new URL('../../', import.meta.url))
const read = relative => readFile(path.join(root, relative), 'utf8')
test('跨平台构建输出不得越过项目 out 目录', async () => {
const content = await read('Makefile')
const commands = [...content.matchAll(/cd ([^\s]+) && [^\n]*go build [^\n]* -o ([^\s]+) /g)]
assert.equal(commands.length, 12)
for (const [, directory, output] of commands) {
const relative = path.relative(path.join(root, 'out'), path.resolve(root, directory, output))
assert.ok(relative && !relative.startsWith('..') && !path.isAbsolute(relative), output)
}
})
test('前端构建必须自动同步 Go 嵌入资源', async () => {
const frontend = JSON.parse(await read('frontend/package.json'))
const telegram = JSON.parse(await read('plugins/pmail_telegram_push/package.json'))
assert.equal(frontend.scripts.postbuild, 'node ../deploy/prepare-frontend.mjs')
assert.equal(telegram.scripts['postbuild-only'], 'node ../../deploy/prepare-frontend.mjs telegram')
assert.match(await read('frontend/vite.config.js'), /\.\.\/out\/frontend/)
assert.match(await read('plugins/pmail_telegram_push/vite.config.ts'), /\.\.\/\.\.\/out\/plugins\/telegram-ui/)
})
test('前端入口按需加载 Element Plus,并延迟设置页和写信编辑器', async () => {
const main = await read('frontend/src/main.js')
const vite = await read('frontend/vite.config.js')
const header = await read('frontend/src/views/components/HomeHeader/HomeHeader.js')
assert.doesNotMatch(main, /app\.use\(ElementPlus\)/)
assert.doesNotMatch(main, /element-plus\/dist\/index\.css/)
assert.match(main, /element-services\.css/)
assert.match(vite, /manualChunks\(id\)/)
assert.match(header, /defineAsyncComponent/)
assert.match(header, /import\('\.\.\/ConfigSettings\/ConfigSettings\.vue'\)/)
})
test('开发启动必须固定运行配置根目录并集中保存日志', async () => {
const content = await read('deploy/start-dev.ps1')
assert.match(content, /\$env:SMAIL_ROOT = \$root\r?\n/)
assert.match(content, /\$legacyConfig = Join-Path \$root 'backend\\config'/)
assert.match(content, /Test-Path -LiteralPath \(Join-Path \$legacyConfig \$name\)/)
assert.match(content, /\$workingDirectory = Join-Path \$root 'out'/)
for (const name of ['spam_block.exe', 'pmail_telegram_push.exe', 'wechat_push.exe']) assert.ok(content.includes(name))
assert.match(content, /out\\backend\\smail-dev\.exe/)
assert.match(content, /test-log\\runtime/)
assert.match(content, /-WindowStyle Hidden/)
assert.match(content, /\[switch\]\$SkipBuild/)
assert.match(content, /--dev-disable-admin-reset/)
assert.match(content, /默认先编译当前工作区/)
assert.ok(content.charCodeAt(0) === 0xfeff, 'Windows PowerShell 5 脚本应有 UTF-8 BOM')
})
test('六个平台默认包含三个插件,构建和发布名称与后端目录完全匹配', async () => {
const catalog = await read('backend/plugins/catalog/catalog.go')
for (const target of targets) {
const plan = buildPlan({ target })
assert.equal(plan.length, 3)
assert.deepEqual(plan.map(item => item.id), plugins.map(item => item.id))
for (const item of plan) {
assert.equal(path.dirname(item.output), path.join(root, 'out', 'plugins', target))
assert.ok(catalog.includes(`"${path.basename(item.output)}"`))
}
const files = packagePlan(target)
assert.equal(files.length, 6)
assert.equal(files.filter(file => path.basename(path.dirname(file.target)) === 'plugins').length, 3)
assert.ok(files.every(file => file.target.startsWith(path.join(root, 'out', 'package', target))))
}
assert.ok(buildPlan({ development: true }).every(item => path.dirname(item.output) === path.join(root, 'out', 'plugins')))
assert.throws(() => buildPlan({ target: '../invalid' }))
assert.throws(() => buildPlan({ plugin: 'unknown' }))
assert.throws(() => buildPlan({ development: true, target: targets.find(target => target !== hostTarget()) }))
assert.match(await read('deploy/build.ps1'), /build-plugins\.mjs'\) --dev/)
assert.match(await read('Makefile'), /package: build_server plugin/)
assert.match(await read('.github/workflows/release.yml'), /node deploy\/build-plugins\.mjs --target=/)
})
test('安全工作流必须先构建嵌入资源再执行 Go 测试', async () => {
for (const file of ['.github/workflows/release.yml', '.github/workflows/security.yml']) {
const content = (await read(file)).split(' security:')[1]
assert.ok(content)
const prepare = content.indexOf('yarn build')
const goTest = content.indexOf('node test/run.mjs backend')
assert.ok(prepare >= 0 && goTest > prepare, file)
}
})