列表为什么少一项:用 5 条演示数据核对筛选条件
用 5 条虚构记录,先独立列出八组查询的期望 ID,再运行本地脚本核对关键词、分类、状态和空白处理。检查完整 ID 与输入是否改变,并明确这份演示不能替代接口或页面验收。
执行信息
- 测试环境
- Node.js v22.22.0 本地固定输入验证;不涉及生产接口、分页、权限或浏览器
- 输入
- 请查看正文中的输入说明
- 产出
- 请查看正文中的产出说明
- 实测结果
- 请以作者提供的实测记录为准
AgentField 编辑整理|5 条记录均为虚构演示输入。本文验证本地 JavaScript 筛选逻辑,不是本站搜索实现、线上故障复现或用户案例。
“列表少了一条”可能是规则不同,也可能是实现有误。先别急着改界面:把输入固定下来,写出应该留下哪些 ID,再看实际返回什么。数量相同也可能选错记录,所以要核对明细。
一、先说清楚这次筛选的规则
本例只约定四件事:关键词只查标题,用连续子串匹配;关键词先去首尾空白,空关键词不限制;分类和状态使用完整字符串相等,空值表示不限制;多个条件必须同时满足,保留输入顺序。
本例不做拼音、分词或大小写转换,也不涉及分页和权限。查询字段省略时等同空字符串;输入记录及查询值都按下面约定使用字符串,输入记录缺少所需字段、显式 null 或其他类型不在这段演示的处理范围内。真实产品的规则需要另行确认,不能照搬本例猜测。
将下面的固定输入保存为 rows.json:
[
{"id":"demo-01","title":"网站首页检查","category":"网站","status":"待处理"},
{"id":"demo-02","title":"网站表单检查","category":"网站","status":"已完成"},
{"id":"demo-03","title":"网站素材整理","category":"自动化","status":"待处理"},
{"id":"demo-04","title":"表格数据清理","category":"自动化","status":"已完成"},
{"id":"demo-05","title":"网站首页说明","category":"网站","status":"已完成"}
]
注意 demo-03:标题有“网站”,分类却是“自动化”。这能帮助我们发现“关键词命中”与“分类命中”被误当成同一件事。
二、先手工列出期望 ID
以下期望按上面的记录逐项列出,不由待测筛选函数生成。为便于阅读,这里用 01 表示 demo-01,其余同理。
- 不加条件:01、02、03、04、05。
- 关键词“网站”:01、02、03、05。
- 只选分类“网站”:01、02、05。
- 只选状态“待处理”:01、03。
- 关键词“网站”+分类“网站”+状态“已完成”:02、05。
- 关键词“财务”:空列表。
- 关键词首尾各有两个空格的“网站”:01、02、03、05。
- 关键词只有空格、制表符和换行:01、02、03、04、05。
第五项尤其有用:01 因状态不符被排除,03 的分类和状态都不符。只凭“标题里有网站”认定它们丢失,会把正常排除误报为缺陷。若要改成“任一条件满足”,先修改规则及独立期望,再修改实现。
三、运行同一份输入,比较实际结果
把以下代码存为同目录的 check-filter.cjs,在该目录运行 node check-filter.cjs。代码中的期望 ID 对应上面的八项;核对失败会抛出断言错误,不应把没有跑完当成通过。
const fs = require('node:fs');
const assert = require('node:assert/strict');
const rows = JSON.parse(fs.readFileSync('rows.json', 'utf8'));
const before = JSON.parse(JSON.stringify(rows));
const cases = [
[{}, ['demo-01','demo-02','demo-03','demo-04','demo-05']],
[{q:'网站'}, ['demo-01','demo-02','demo-03','demo-05']],
[{category:'网站'}, ['demo-01','demo-02','demo-05']],
[{status:'待处理'}, ['demo-01','demo-03']],
[{q:'网站',category:'网站',status:'已完成'}, ['demo-02','demo-05']],
[{q:'财务'}, []],
[{q:' 网站 '}, ['demo-01','demo-02','demo-03','demo-05']],
[{q:' \t\n '}, ['demo-01','demo-02','demo-03','demo-04','demo-05']]
];
function selectIds(rows, {q = '', category = '', status = ''} = {}) {
const keyword = q.trim();
return rows.filter(row =>
(keyword === '' || row.title.includes(keyword)) &&
(category === '' || row.category === category) &&
(status === '' || row.status === status)
).map(row => row.id);
}
const checks = cases.map(([query, expectedIds], index) => {
const actualIds = selectIds(rows, query);
assert.deepStrictEqual(actualIds, expectedIds, `用例 ${index + 1}`);
assert.deepStrictEqual(rows, before, '输入记录被修改');
return {case: index + 1, query, expectedIds, actualIds, passed: true};
});
console.log(JSON.stringify({node: process.version, checks, inputUnchanged: true}, null, 2));