| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144 |
- import { test } from 'node:test'
- import assert from 'node:assert/strict'
- import os from 'node:os'
- import path from 'node:path'
- import { promises as fs } from 'node:fs'
- import {
- registerBook,
- setCurrentBook,
- touchLastOpened,
- readBooksRegistry,
- loadBooks,
- } from '../../src/session/index.js'
- async function tmpWorkdir() {
- const root = await fs.mkdtemp(path.join(os.tmpdir(), 'wnw-reg-'))
- return { root, cleanup: () => fs.rm(root, { recursive: true, force: true }) }
- }
- async function writeRegistry(root, lines) {
- await fs.mkdir(path.join(root, '.webnovel'), { recursive: true })
- await fs.writeFile(path.join(root, '.webnovel', 'books.jsonl'), lines.join('\n') + '\n', 'utf8')
- }
- const DATE_RE = /^\d{4}-\d{2}-\d{2}$/
- test('registerBook:空工作目录登记首本,置当前并带最后打开', async () => {
- const { root, cleanup } = await tmpWorkdir()
- try {
- const r = await registerBook(root, { 书名: '剑起青云', 目录: '剑起青云' })
- assert.equal(r.ok, true)
- const reg = await readBooksRegistry(root)
- assert.equal(reg.books.length, 1)
- assert.equal(reg.books[0].书名, '剑起青云')
- assert.equal(reg.books[0].当前, true)
- assert.match(reg.books[0].最后打开, DATE_RE)
- } finally {
- await cleanup()
- }
- })
- test('registerBook:新书置当前,旧当前退位', async () => {
- const { root, cleanup } = await tmpWorkdir()
- try {
- await writeRegistry(root, [JSON.stringify({ 书名: '星海', 目录: '星海', 当前: true })])
- const r = await registerBook(root, { 书名: '剑起青云', 目录: '剑起青云' })
- assert.equal(r.ok, true)
- const reg = await readBooksRegistry(root)
- assert.equal(reg.books.length, 2)
- assert.equal(reg.books.find((b) => b.书名 === '星海').当前, false)
- assert.equal(reg.books.find((b) => b.书名 === '剑起青云').当前, true)
- } finally {
- await cleanup()
- }
- })
- test('registerBook:同目录重复登记不产生重复行,书名更新', async () => {
- const { root, cleanup } = await tmpWorkdir()
- try {
- await writeRegistry(root, [JSON.stringify({ 书名: '旧名', 目录: '书目录', 当前: true })])
- const r = await registerBook(root, { 书名: '新名', 目录: '书目录' })
- assert.equal(r.ok, true)
- const reg = await readBooksRegistry(root)
- assert.equal(reg.books.length, 1)
- assert.equal(reg.books[0].书名, '新名')
- } finally {
- await cleanup()
- }
- })
- test('registerBook:缺书名/目录 → 人话错误', async () => {
- const { root, cleanup } = await tmpWorkdir()
- try {
- const r = await registerBook(root, { 书名: '', 目录: 'x' })
- assert.equal(r.ok, false)
- assert.ok(r.error.includes('书名'))
- } finally {
- await cleanup()
- }
- })
- test('setCurrentBook:按书名或目录命中,单一当前', async () => {
- const { root, cleanup } = await tmpWorkdir()
- try {
- await writeRegistry(root, [
- JSON.stringify({ 书名: '星海', 目录: 'xinghai', 当前: true }),
- JSON.stringify({ 书名: '剑起青云', 目录: 'jian', 当前: false }),
- ])
- const r = await setCurrentBook(root, '剑起青云')
- assert.equal(r.ok, true)
- assert.equal(r.book.目录, 'jian')
- const reg = await readBooksRegistry(root)
- assert.equal(reg.books.filter((b) => b.当前).length, 1)
- assert.equal(reg.books.find((b) => b.当前).书名, '剑起青云')
- // 按目录名也可命中
- const r2 = await setCurrentBook(root, 'xinghai')
- assert.equal(r2.ok, true)
- assert.equal(r2.book.书名, '星海')
- } finally {
- await cleanup()
- }
- })
- test('setCurrentBook:未命中 → 列候选', async () => {
- const { root, cleanup } = await tmpWorkdir()
- try {
- await writeRegistry(root, [JSON.stringify({ 书名: '星海', 目录: '星海', 当前: true })])
- const r = await setCurrentBook(root, '不存在的书')
- assert.equal(r.ok, false)
- assert.ok(r.error.includes('星海'), `候选应包含书名:${r.error}`)
- } finally {
- await cleanup()
- }
- })
- test('touchLastOpened:刷新最后打开,不改其他字段', async () => {
- const { root, cleanup } = await tmpWorkdir()
- try {
- await writeRegistry(root, [
- JSON.stringify({ 书名: '星海', 目录: '星海', 当前: true, 最后打开: '2000-01-01' }),
- ])
- await touchLastOpened(root, '星海')
- const reg = await readBooksRegistry(root)
- assert.notEqual(reg.books[0].最后打开, '2000-01-01')
- assert.match(reg.books[0].最后打开, DATE_RE)
- assert.equal(reg.books[0].当前, true)
- } finally {
- await cleanup()
- }
- })
- test('loadBooks:坏行丢弃回写自愈(与 assembleSessionContext 同源)', async () => {
- const { root, cleanup } = await tmpWorkdir()
- try {
- await writeRegistry(root, [
- JSON.stringify({ 书名: '星海', 目录: '星海', 当前: true }),
- '{坏的 json',
- ])
- const r = await loadBooks(root)
- assert.equal(r.books.length, 1)
- const raw = await fs.readFile(path.join(root, '.webnovel', 'books.jsonl'), 'utf8')
- assert.ok(!raw.includes('坏的'), '坏行应被自愈回写清除')
- } finally {
- await cleanup()
- }
- })
|