| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061 |
- import { test } from 'node:test'
- import assert from 'node:assert/strict'
- import path from 'node:path'
- import { promises as fs } from 'node:fs'
- import { run as finalizeCmd } from '../../src/commands/finalize.js'
- import { tempBookCtx } from './_helper.js'
- // R2:批次进行中的手动 finalize 必须被拒——放行会让 overlay 双计总章数,
- // 且 finalize-batch 再转正同章时撞「条目已存在」整批卡死。守卫在读 payload 之前,
- // 故测试无需构造定稿包。
- async function injectBatch(root, nums) {
- const rows = []
- for (const n of nums) {
- const dirName = `${String(n).padStart(4, '0')}-批内章`
- await fs.mkdir(path.join(root, '工作区', '待定稿', dirName), { recursive: true })
- rows.push({ 章号: n, 标题: '批内章', 状态: '待审收', 目录: dirName })
- }
- await fs.writeFile(
- path.join(root, '工作区', '待定稿', '批次.json'),
- JSON.stringify({ 章列表: rows }),
- 'utf8'
- )
- }
- test('R2:目标章在批内 → 手动 finalize 被拒,指向 finalize-batch', async () => {
- const { ctx, cleanup } = await tempBookCtx()
- try {
- await injectBatch(ctx.repoPath, [3, 4])
- const r = await finalizeCmd(['3'], {}, ctx)
- assert.equal(r.ok, false)
- assert.match(r.error, /已在待定稿批次/)
- assert.match(r.error, /finalize-batch/)
- } finally {
- await cleanup()
- }
- })
- test('R2:批次在场但目标章不在批内 → 同样被拒(防章号错位)', async () => {
- const { ctx, cleanup } = await tempBookCtx()
- try {
- await injectBatch(ctx.repoPath, [3, 4])
- const r = await finalizeCmd(['9'], {}, ctx)
- assert.equal(r.ok, false)
- assert.match(r.error, /待定稿批次/)
- assert.match(r.error, /batch-discard/)
- } finally {
- await cleanup()
- }
- })
- test('无批次时 finalize 不受守卫影响(走正常校验路径)', async () => {
- const { ctx, cleanup } = await tempBookCtx()
- try {
- const r = await finalizeCmd(['3'], {}, ctx)
- // 没给 payload:应报缺 payload 而不是批次守卫错
- assert.equal(r.ok, false)
- assert.doesNotMatch(r.error, /批次/)
- } finally {
- await cleanup()
- }
- })
|