ledger.test.js 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657
  1. import { test } from 'node:test';
  2. import assert from 'node:assert/strict';
  3. import { criteriaOf, queryOf, applyFilter, facetCounts, toggle, collectValues } from '../src/core/kfs/ledger.js';
  4. /** 六维各取不同值,便于验证「同维 OR、跨维 AND」 */
  5. const rows = [
  6. { id: '1', title: '夜宵低卡拌面', oneLiner: '加班', priority: 'S', category: '拌面', status: 'candidate', layer: 'process', stage: 'S3 机会识别', ownerName: '张伟' },
  7. { id: '2', title: '办公室速食拌面', oneLiner: '午休', priority: 'A', category: '拌面', status: 'approved', layer: 'process', stage: 'S4 验证评估', ownerName: '李娜' },
  8. { id: '3', title: '银发低钠汤面', oneLiner: '控盐', priority: 'B', category: '汤面', status: 'candidate', layer: 'sediment', stage: 'S1 品类市场分析', ownerName: '张伟' },
  9. { id: '4', title: '露营拌面', oneLiner: '户外', priority: 'S', category: '杯面', status: 'rejected', layer: 'record', stage: 'S5 场景与卖点设计', ownerName: '陈静' },
  10. ];
  11. const ids = (c) => applyFilter(rows, criteriaOf(c)).map((r) => r.id).sort();
  12. test('单维多选:任一命中(OR)', () => {
  13. assert.deepEqual(ids({ priority: 'S,A' }), ['1', '2', '4']);
  14. assert.deepEqual(ids({ stage: 'S1,S5' }), ['3', '4']);
  15. });
  16. test('跨维组合:取交集(AND)', () => {
  17. assert.deepEqual(ids({ priority: 'S', category: '拌面' }), ['1']);
  18. assert.deepEqual(ids({ priority: 'S,A', category: '拌面', member: '张伟' }), ['1']);
  19. assert.deepEqual(ids({ priority: 'S,A', category: '拌面', member: '张伟', stage: 'S4' }), [], '张伟在 S4 没成果');
  20. });
  21. test('六维全部叠加', () => {
  22. assert.deepEqual(ids({ status: 'candidate', priority: 'B', category: '汤面', stage: 'S1', member: '张伟', layer: 'sediment' }), ['3']);
  23. assert.deepEqual(ids({ status: 'candidate', priority: 'B', category: '汤面', stage: 'S1', member: '张伟', layer: 'process' }), []);
  24. });
  25. test('搜索词跨字段', () => {
  26. assert.deepEqual(ids({ q: '户外' }), ['4']);
  27. assert.deepEqual(ids({ q: '张伟' }), ['1', '3']);
  28. });
  29. test('URL 状态:条件 → 查询串 → 条件 往返不丢', () => {
  30. const c = criteriaOf({ priority: 'S,A', stage: 'S3', q: '面', sort: 'score' });
  31. const q = queryOf(c);
  32. assert.equal(q.priority, 'S,A');
  33. assert.deepEqual(criteriaOf(q), c);
  34. assert.deepEqual(queryOf(criteriaOf({})), {}, '空条件不写进 URL');
  35. });
  36. test('分面计数受其他维度约束、不受本维约束', () => {
  37. const c = criteriaOf({ priority: 'S,A', category: '拌面' });
  38. const m = facetCounts(rows, c, 'priority');
  39. // 在「拌面」范围内,S 有 1 条、A 有 1 条;B 的拌面没有
  40. assert.equal(m.get('S'), 1);
  41. assert.equal(m.get('A'), 1);
  42. assert.equal(m.get('B'), undefined);
  43. });
  44. test('toggle 与取值收集', () => {
  45. const c = toggle({ priority: [] }, 'priority', 'S');
  46. assert.deepEqual(c.priority, ['S']);
  47. assert.deepEqual(toggle(c, 'priority', 'S').priority, []);
  48. assert.deepEqual(collectValues(rows, 'category').map((x) => x.value), ['拌面', '杯面', '汤面'], '次数相同按中文排序');
  49. });