query-command.test.js 3.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061
  1. import { test } from 'node:test'
  2. import assert from 'node:assert/strict'
  3. import path from 'node:path'
  4. import os from 'node:os'
  5. import { mkdtemp, mkdir, rm, writeFile } from 'node:fs/promises'
  6. import { fileURLToPath } from 'node:url'
  7. import { run } from '../../src/commands/knowledge-query.js'
  8. const packageRoot = path.join(path.dirname(fileURLToPath(import.meta.url)), '../..')
  9. test('knowledge-query:只给少量材料并明确允许拒绝、自定义', async () => {
  10. const result = await run([], { 维度: '场景', 问题: '拍卖会竞价夺宝' }, { packageRoot })
  11. assert.equal(result.ok, true, result.error)
  12. assert.match(result.output, /拍卖会/)
  13. assert.match(result.output, /来源:场景\/拍卖会\.md@sha256:/)
  14. assert.match(result.output, /选择、组合、修改、拒绝或自定义/)
  15. })
  16. test('knowledge-query:无命中不回退全量菜单;非法维度前置拒绝', async () => {
  17. const empty = await run([], { 维度: '技法', 问题: '未知写法' }, { packageRoot })
  18. assert.equal(empty.ok, true)
  19. assert.match(empty.output, /没有按名称、编号或现有索引命中/)
  20. assert.match(empty.output, /不要为了凑候选改用全量菜单/)
  21. const invalid = await run([], { 维度: '桥段', 问题: '冲突' }, { packageRoot })
  22. assert.equal(invalid.ok, false)
  23. assert.match(invalid.error, /维度/)
  24. })
  25. test('knowledge-query:创意约束按未决问题给材料,不按题材固定选择', async () => {
  26. const result = await run(
  27. [],
  28. { 维度: '创意约束', 问题: '知道答案就能成功,知识可以直接变现,缺少现实阻力' },
  29. { packageRoot }
  30. )
  31. assert.equal(result.ok, true)
  32. assert.match(result.output, /知识转化有门槛/)
  33. assert.match(result.output, /选择、组合、修改、拒绝或自定义/)
  34. })
  35. test('knowledge-query:故事对象类型筛选使用受控字段并拒绝未知类型', async () => {
  36. const root = await mkdtemp(path.join(os.tmpdir(), 'wnw-object-query-'))
  37. try {
  38. for (const dir of ['设定', '人物', '命名']) await mkdir(path.join(root, 'references', dir), { recursive: true })
  39. await writeFile(path.join(root, 'references', '设定', '能力.md'), ['---', '名称: 能力', '对象类型: 能力', '一句话: 能力有代价', '---', '## 规划时', '', '锁定代价。'].join('\n'), 'utf8')
  40. await writeFile(path.join(root, 'references', '人物', '关系.md'), ['---', '名称: 关系', '人物类别: 关系', '一句话: 利益变化推动关系', '---', '## 规划时', '', '锁定变化条件。'].join('\n'), 'utf8')
  41. await writeFile(path.join(root, 'references', '命名', '角色名.md'), ['---', '名称: 角色名', '命名对象:', ' - 角色', '一句话: 名字承担身份辨识', '---', '## 规划时', '', '检查近名冲突。'].join('\n'), 'utf8')
  42. const person = await run([], { 维度: '人物', 类型: '关系' }, { packageRoot: root })
  43. assert.equal(person.ok, true, person.error)
  44. assert.match(person.output, /关系/)
  45. assert.match(person.output, /规划切片/)
  46. const naming = await run([], { 维度: '命名', 类型: '角色' }, { packageRoot: root })
  47. assert.equal(naming.ok, true, naming.error)
  48. assert.match(naming.output, /角色名/)
  49. const invalid = await run([], { 维度: '人物', 类型: '反派' }, { packageRoot: root })
  50. assert.equal(invalid.ok, false)
  51. assert.match(invalid.error, /角色、关系/)
  52. } finally {
  53. await rm(root, { recursive: true, force: true })
  54. }
  55. })