Skip to content

Commit 1b568e8

Browse files
committed
test(knowledge): 补全知识库相关命令参数并增加E2E测试覆盖
- 添加知识库列表、创建、删除及文件删除等命令路由 - 新增知识块、分类、文件相关参数的端到端测试,覆盖文件列表、分类列表、块新增更新及分页等功能 - 增加对知识文档状态上传、等待、轮询参数的实时测试及自清理逻辑 - 新增知识文档列表分页、过滤参数的E2E测试覆盖 - 扩展知识文档上传命令的轮询间隔参数测试,验证无错误 - 补充知识库删除命令的轮询间隔参数传递测试 - 增强知识库列表的分页、名称过滤测试用例 - 丰富知识服务命令的参数全覆盖测试,包括创建、更新、部署、删除及多版本描述等功能 - 添加知识检索命令的重新排序指令与过时参数的实时测试覆盖
1 parent e292b20 commit 1b568e8

9 files changed

Lines changed: 1132 additions & 2 deletions

packages/commands/tests/e2e/knowledge/knowledge-chunk-category-file.e2e.test.ts

Lines changed: 451 additions & 0 deletions
Large diffs are not rendered by default.

packages/commands/tests/e2e/knowledge/knowledge-doc-list.e2e.test.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,5 +93,25 @@ describe.skipIf(!isKbAdminE2EReady())("e2e: knowledge doc list (live)", () => {
9393
expect(exitCode, stderr).toBe(0);
9494
const data = parseStdoutJson<{ code: string }>(stdout);
9595
expect(data.code).toBe("Success");
96+
97+
// P6: --page-number + --page-size
98+
const pagedRun = await runCommandE2e(KNOWLEDGE_DOC_LIST_ROUTES, [
99+
"knowledge",
100+
"doc",
101+
"list",
102+
"--index-id",
103+
firstIndexId,
104+
"--page-number",
105+
"1",
106+
"--page-size",
107+
"10",
108+
"--workspace-id",
109+
workspaceId,
110+
"--output",
111+
"json",
112+
]);
113+
expect(pagedRun.exitCode, pagedRun.stderr).toBe(0);
114+
const pagedData = parseStdoutJson<{ code: string }>(pagedRun.stdout);
115+
expect(pagedData.code).toBe("Success");
96116
});
97117
});

packages/commands/tests/e2e/knowledge/knowledge-doc-status.e2e.test.ts

Lines changed: 140 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
1+
import { mkdtempSync, writeFileSync } from "node:fs";
2+
import { tmpdir } from "node:os";
3+
import { join } from "node:path";
14
import { describe, expect, test } from "vite-plus/test";
2-
import { parseStdoutJson, runCommandE2e } from "../helpers.ts";
5+
import { isKbAdminE2EReady, parseStdoutJson, runCommandE2e } from "../helpers.ts";
36
import { KNOWLEDGE_DOC_STATUS_ROUTES } from "../topic-routes.ts";
47

58
// Live coverage depends on a real job_id produced by doc upload; it is exercised
@@ -93,3 +96,139 @@ describe("e2e: knowledge doc status", () => {
9396
expect(data.endpoint).toMatch(/page_size=50/);
9497
});
9598
});
99+
100+
// Live: --wait + --poll-interval on a real job_id produced by upload --index-id --wait
101+
describe.skipIf(!isKbAdminE2EReady())("e2e: knowledge doc status (live, 自清理)", () => {
102+
const workspaceId = process.env.BAILIAN_WORKSPACE_ID!;
103+
104+
test("status --wait --poll-interval → 返回 COMPLETED", async () => {
105+
const fixtureDir = mkdtempSync(join(tmpdir(), "doc-status-e2e-"));
106+
const filePathA = join(fixtureDir, `status-a-${Date.now()}.md`);
107+
writeFileSync(filePathA, "# doc status e2e fixture A\n");
108+
109+
// 1) Upload file A to data center
110+
const uploadRunA = await runCommandE2e(KNOWLEDGE_DOC_STATUS_ROUTES, [
111+
"knowledge",
112+
"doc",
113+
"upload",
114+
"--file",
115+
filePathA,
116+
"--workspace-id",
117+
workspaceId,
118+
"--quiet",
119+
]);
120+
expect(uploadRunA.exitCode, uploadRunA.stderr).toBe(0);
121+
const fileIdA = uploadRunA.stdout.trim();
122+
expect(fileIdA).toMatch(/^file_/);
123+
124+
let indexId = "";
125+
let fileIdB = "";
126+
try {
127+
// 2) Create a throwaway base (gives us an index_id)
128+
const createRun = await runCommandE2e(KNOWLEDGE_DOC_STATUS_ROUTES, [
129+
"knowledge",
130+
"create",
131+
"--name",
132+
`e2e-st-${Date.now() % 100000000}`,
133+
"--doc-id",
134+
fileIdA,
135+
"--workspace-id",
136+
workspaceId,
137+
"--wait",
138+
"--quiet",
139+
]);
140+
expect(createRun.exitCode, createRun.stderr).toBe(0);
141+
indexId = createRun.stdout.trim().split("\n")[0]!;
142+
expect(indexId).toBeTruthy();
143+
144+
// 3) Upload file B to the base (--index-id --wait --output json) → ingestion_id
145+
const filePathB = join(fixtureDir, `status-b-${Date.now()}.md`);
146+
writeFileSync(filePathB, "# doc status e2e fixture B\n");
147+
const uploadRunB = await runCommandE2e(KNOWLEDGE_DOC_STATUS_ROUTES, [
148+
"knowledge",
149+
"doc",
150+
"upload",
151+
"--file",
152+
filePathB,
153+
"--index-id",
154+
indexId,
155+
"--wait",
156+
"--poll-interval",
157+
"3",
158+
"--workspace-id",
159+
workspaceId,
160+
"--output",
161+
"json",
162+
]);
163+
expect(uploadRunB.exitCode, uploadRunB.stderr).toBe(0);
164+
const importData = parseStdoutJson<{
165+
files: Array<{ fileId: string }>;
166+
ingestion_id?: string;
167+
final_status?: string;
168+
}>(uploadRunB.stdout);
169+
const jobId = importData.ingestion_id;
170+
expect(jobId).toBeTruthy();
171+
fileIdB = importData.files?.[0]?.fileId ?? "";
172+
173+
// 4) status --wait --poll-interval: verify COMPLETED
174+
// (upload --wait already ensured completion, so this should return immediately)
175+
const statusRun = await runCommandE2e(KNOWLEDGE_DOC_STATUS_ROUTES, [
176+
"knowledge",
177+
"doc",
178+
"status",
179+
"--index-id",
180+
indexId,
181+
"--job-id",
182+
jobId!,
183+
"--wait",
184+
"--poll-interval",
185+
"3",
186+
"--workspace-id",
187+
workspaceId,
188+
"--output",
189+
"json",
190+
]);
191+
expect(statusRun.exitCode, statusRun.stderr).toBe(0);
192+
const statusData = parseStdoutJson<{
193+
data?: { final_status?: string };
194+
}>(statusRun.stdout);
195+
expect(statusData.data?.final_status).toBe("COMPLETED");
196+
} finally {
197+
// Cleanup base + data-center files
198+
if (fileIdB) {
199+
await runCommandE2e(KNOWLEDGE_DOC_STATUS_ROUTES, [
200+
"knowledge",
201+
"file",
202+
"delete",
203+
"--file-id",
204+
fileIdB,
205+
"--yes",
206+
"--workspace-id",
207+
workspaceId,
208+
]);
209+
}
210+
if (indexId) {
211+
await runCommandE2e(KNOWLEDGE_DOC_STATUS_ROUTES, [
212+
"knowledge",
213+
"delete",
214+
"--index-id",
215+
indexId,
216+
"--yes",
217+
"--workspace-id",
218+
workspaceId,
219+
]);
220+
}
221+
await runCommandE2e(KNOWLEDGE_DOC_STATUS_ROUTES, [
222+
"knowledge",
223+
"file",
224+
"delete",
225+
"--file-id",
226+
fileIdA,
227+
"--yes",
228+
"--workspace-id",
229+
workspaceId,
230+
]);
231+
}
232+
// kb create --wait adds a full import phase — generous timeout
233+
}, 600_000);
234+
});

packages/commands/tests/e2e/knowledge/knowledge-doc-upload.e2e.test.ts

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,4 +240,57 @@ describe.skipIf(!isKbAdminE2EReady())("e2e: knowledge doc upload (live)", () =>
240240
expect(fileDeleteRun.exitCode, fileDeleteRun.stderr).toBe(0);
241241
}
242242
}, 120_000);
243+
244+
test("upload --index-id --wait --poll-interval 3 (不报错验证)", async () => {
245+
// P6: --poll-interval — local behavior param, verify no error
246+
// Grab a real index id from the workspace
247+
const listRun = await runCommandE2e(KNOWLEDGE_DOC_UPLOAD_ROUTES, [
248+
"knowledge",
249+
"list",
250+
"--workspace-id",
251+
workspaceId,
252+
"--quiet",
253+
]);
254+
expect(listRun.exitCode, listRun.stderr).toBe(0);
255+
const indexId = listRun.stdout.trim().split("\n")[0];
256+
if (!indexId) return;
257+
258+
const pollFilePath = join(fixtureDir, `poll-${Date.now()}.md`);
259+
writeFileSync(pollFilePath, "# e2e poll interval fixture\n");
260+
const uploadRun = await runCommandE2e(KNOWLEDGE_DOC_UPLOAD_ROUTES, [
261+
"knowledge",
262+
"doc",
263+
"upload",
264+
"--file",
265+
pollFilePath,
266+
"--index-id",
267+
indexId,
268+
"--wait",
269+
"--poll-interval",
270+
"3",
271+
"--workspace-id",
272+
workspaceId,
273+
"--output",
274+
"json",
275+
]);
276+
expect(uploadRun.exitCode, uploadRun.stderr).toBe(0);
277+
278+
// Cleanup the uploaded file
279+
const importData = parseStdoutJson<{
280+
files: Array<{ fileId: string }>;
281+
}>(uploadRun.stdout);
282+
const pollFileId = importData.files?.[0]?.fileId;
283+
if (pollFileId) {
284+
await runCommandE2e(KNOWLEDGE_DOC_UPLOAD_ROUTES, [
285+
"knowledge",
286+
"file",
287+
"delete",
288+
"--file-id",
289+
pollFileId,
290+
"--yes",
291+
"--workspace-id",
292+
workspaceId,
293+
]);
294+
}
295+
}, 120_000);
243296
});

packages/commands/tests/e2e/knowledge/knowledge-kb-delete.e2e.test.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,8 @@ describe.skipIf(!isKbAdminE2EReady())("e2e: knowledge kb 写链路 (live, 自清
106106
"--workspace-id",
107107
workspaceId,
108108
"--wait",
109+
"--poll-interval",
110+
"3",
109111
"--quiet",
110112
]);
111113
expect(createRun.exitCode, createRun.stderr).toBe(0);

packages/commands/tests/e2e/knowledge/knowledge-kb-list.e2e.test.ts

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,4 +124,51 @@ describe.skipIf(!isKbAdminE2EReady())("e2e: knowledge kb list (live)", () => {
124124
const lines = quietRun.stdout.trim().split("\n").filter(Boolean);
125125
expect(lines.length).toBe(rows.length);
126126
});
127+
128+
test("--name 过滤 + --page-number/--page-size 分页", async () => {
129+
// P6: --name
130+
const jsonRun = await runCommandE2e(KNOWLEDGE_KB_LIST_ROUTES, [
131+
"knowledge",
132+
"list",
133+
"--workspace-id",
134+
workspaceId,
135+
"--output",
136+
"json",
137+
]);
138+
expect(jsonRun.exitCode, jsonRun.stderr).toBe(0);
139+
const allRows = parseStdoutJson<KbListResponse>(jsonRun.stdout).data.rows;
140+
if (allRows.length === 0) return;
141+
142+
const firstName = allRows[0]!.name;
143+
const nameRun = await runCommandE2e(KNOWLEDGE_KB_LIST_ROUTES, [
144+
"knowledge",
145+
"list",
146+
"--name",
147+
firstName,
148+
"--workspace-id",
149+
workspaceId,
150+
"--output",
151+
"json",
152+
]);
153+
expect(nameRun.exitCode, nameRun.stderr).toBe(0);
154+
const nameData = parseStdoutJson<KbListResponse>(nameRun.stdout);
155+
expect(nameData.data.rows.some((row) => row.name === firstName)).toBe(true);
156+
157+
// P6: --page-number + --page-size
158+
const pagedRun = await runCommandE2e(KNOWLEDGE_KB_LIST_ROUTES, [
159+
"knowledge",
160+
"list",
161+
"--page-number",
162+
"1",
163+
"--page-size",
164+
"1",
165+
"--workspace-id",
166+
workspaceId,
167+
"--output",
168+
"json",
169+
]);
170+
expect(pagedRun.exitCode, pagedRun.stderr).toBe(0);
171+
const pagedData = parseStdoutJson<KbListResponse>(pagedRun.stdout);
172+
expect(pagedData.data.rows.length).toBeLessThanOrEqual(1);
173+
});
127174
});

0 commit comments

Comments
 (0)