99 lines
4.2 KiB
JavaScript
99 lines
4.2 KiB
JavaScript
import { readFile } from 'node:fs/promises'
|
|
import path from 'node:path'
|
|
import { fileURLToPath } from 'node:url'
|
|
import { describe, expect, it } from 'vitest'
|
|
import { DEFAULT_PORT } from '../server/index.mjs'
|
|
|
|
const projectRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..')
|
|
|
|
async function readProjectFile(relativePath) {
|
|
return readFile(path.join(projectRoot, relativePath), 'utf8')
|
|
}
|
|
|
|
describe('deployment configuration', () => {
|
|
it('keeps the release version synchronized across project and deployment metadata', async () => {
|
|
const [packageText, lockText, compose, readme, changelog] = await Promise.all([
|
|
readProjectFile('package.json'),
|
|
readProjectFile('package-lock.json'),
|
|
readProjectFile('docker-compose.yml'),
|
|
readProjectFile('README.zh-CN.md'),
|
|
readProjectFile('CHANGELOG.md'),
|
|
])
|
|
const packageJson = JSON.parse(packageText)
|
|
const packageLock = JSON.parse(lockText)
|
|
const version = packageJson.version
|
|
|
|
expect(version).toMatch(/^\d+\.\d+\.\d+$/)
|
|
expect(packageLock.version).toBe(version)
|
|
expect(packageLock.packages[''].version).toBe(version)
|
|
expect(compose.match(/^\s*image:\s*personal-web-tools:(\S+)$/m)?.[1]).toBe(version)
|
|
expect(readme).toContain(`当前应用版本:\`${version}\`。`)
|
|
expect(readme).toContain(`personal-web-tools-${version}-amd64.tar`)
|
|
expect(changelog.match(/^## (\d+\.\d+\.\d+) - /m)?.[1]).toBe(version)
|
|
})
|
|
|
|
it('keeps the default production port synchronized', async () => {
|
|
const [dockerfile, compose, environment, script, readme] = await Promise.all([
|
|
readProjectFile('Dockerfile'),
|
|
readProjectFile('docker-compose.yml'),
|
|
readProjectFile('.env.example'),
|
|
readProjectFile('web-tools.ps1'),
|
|
readProjectFile('README.zh-CN.md'),
|
|
])
|
|
|
|
expect(DEFAULT_PORT).toBe(9000)
|
|
expect(dockerfile).toContain('PORT=9000')
|
|
expect(dockerfile).toContain('EXPOSE 9000')
|
|
expect(dockerfile).toContain('http://127.0.0.1:9000/healthz')
|
|
expect(compose).toContain('${WEB_TOOLS_PORT:-9000}:9000')
|
|
expect(environment.trim()).toBe('WEB_TOOLS_PORT=9000')
|
|
expect(script).toMatch(/\[int\]\$Port = 9000/)
|
|
expect(readme).toContain('默认访问地址:`http://服务器地址:9000`')
|
|
expect(readme).toContain('生产服务默认监听 `0.0.0.0:9000`')
|
|
})
|
|
|
|
it('preserves the Windows and container production safeguards', async () => {
|
|
const [dockerfile, compose, dockerignore, script] = await Promise.all([
|
|
readProjectFile('Dockerfile'),
|
|
readProjectFile('docker-compose.yml'),
|
|
readProjectFile('.dockerignore'),
|
|
readProjectFile('web-tools.ps1'),
|
|
])
|
|
|
|
expect(dockerfile).toContain('USER node')
|
|
expect(compose).toContain('read_only: true')
|
|
expect(compose).toContain('no-new-privileges:true')
|
|
expect(compose).toContain('cap_drop:')
|
|
expect(dockerignore).toContain('node_modules')
|
|
expect(dockerignore).toContain('data')
|
|
expect(script).toContain('#Requires -Version 5.1')
|
|
expect(script).toContain("@('pull', '--ff-only', $Remote, $Branch)")
|
|
expect(script).toContain("@('ci', '--include=dev')")
|
|
})
|
|
|
|
it('offers an interactive Windows action menu without changing explicit automation actions', async () => {
|
|
const script = await readProjectFile('web-tools.ps1')
|
|
|
|
expect(script).toContain('function Select-InteractiveAction')
|
|
expect(script).toContain("[2] Update from Git, rebuild, and start")
|
|
expect(script).toContain("[3] Update from Git and rebuild only")
|
|
expect(script).toContain("$PSBoundParameters.ContainsKey('Action')")
|
|
expect(script).toContain("[ValidateSet('start', 'update')]")
|
|
expect(script).not.toContain("[string]$Action = 'start'")
|
|
})
|
|
|
|
it('provides standard entry points for a new AI session', async () => {
|
|
const [entryReadme, agentGuide, completeReadme] = await Promise.all([
|
|
readProjectFile('README.md'),
|
|
readProjectFile('AGENTS.md'),
|
|
readProjectFile('README.zh-CN.md'),
|
|
])
|
|
|
|
expect(entryReadme).toContain('[README.zh-CN.md](README.zh-CN.md)')
|
|
expect(entryReadme).toContain('[AGENTS.md](AGENTS.md)')
|
|
expect(agentGuide).toContain('## First actions in a new session')
|
|
expect(agentGuide).toContain('git status --short --branch')
|
|
expect(completeReadme).toContain('## AI 接手清单')
|
|
})
|
|
})
|