test(api): 补齐天猫恢复审计与指标回归
This commit is contained in:
@@ -903,6 +903,115 @@ describe("Dual-platform live loop", () => {
|
||||
await app.close();
|
||||
});
|
||||
|
||||
it("records recovery audit entries and retry metrics when a SearchBlocked Tmall platform recovers", async () => {
|
||||
let allowTmallSearch = false;
|
||||
const tmallLiveService = createTmallLiveServiceStub({
|
||||
async previewSearch(query) {
|
||||
if (!allowTmallSearch) {
|
||||
const error = new Error("Tmall search session appears invalid.") as Error & {
|
||||
statusCode: number;
|
||||
};
|
||||
error.statusCode = 409;
|
||||
throw error;
|
||||
}
|
||||
|
||||
return {
|
||||
query,
|
||||
source: "html",
|
||||
candidateCount: 1,
|
||||
candidates: [
|
||||
{
|
||||
candidateId: "tmall-934454505228",
|
||||
platform: "tmall",
|
||||
title: "Apple iPhone 15",
|
||||
price: 4399,
|
||||
priceLabel: "CNY 4399",
|
||||
storeName: "Apple 官方旗舰店",
|
||||
productUrl: "https://detail.tmall.com/item.htm?id=934454505228",
|
||||
imageUrl: "https://img.alicdn.com/example.jpg",
|
||||
salesHint: "已售 70万+",
|
||||
specLabel: "128GB",
|
||||
highlights: ["天猫", "官方旗舰店"]
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
});
|
||||
const app = createServer({
|
||||
jdLiveService: createJdLiveServiceStub(),
|
||||
tmallLiveService
|
||||
});
|
||||
await app.ready();
|
||||
await importDualLiveSessions(app);
|
||||
|
||||
const createdTask = await createTask(app, "iPhone 15");
|
||||
expect(
|
||||
createdTask.platformRuns.find((run: { platform: string }) => run.platform === "tmall")
|
||||
).toMatchObject({
|
||||
platform: "tmall",
|
||||
status: "SearchBlocked"
|
||||
});
|
||||
|
||||
allowTmallSearch = true;
|
||||
|
||||
const retryResponse = await app.inject({
|
||||
method: "POST",
|
||||
url: `/api/tasks/${createdTask.taskId}/platforms/tmall/retry`
|
||||
});
|
||||
|
||||
expect(retryResponse.statusCode).toBe(200);
|
||||
expect(
|
||||
retryResponse
|
||||
.json()
|
||||
.task.platformRuns.find((run: { platform: string }) => run.platform === "tmall")
|
||||
).toMatchObject({
|
||||
platform: "tmall",
|
||||
status: "AwaitingSelection"
|
||||
});
|
||||
|
||||
const auditResponse = await app.inject({
|
||||
method: "GET",
|
||||
url: `/api/tasks/${createdTask.taskId}/audit`
|
||||
});
|
||||
|
||||
expect(auditResponse.statusCode).toBe(200);
|
||||
expect(auditResponse.json().audit).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
action: "platform.retry_started",
|
||||
platform: "tmall"
|
||||
}),
|
||||
expect.objectContaining({
|
||||
action: "task.recovery_completed",
|
||||
platform: "tmall"
|
||||
}),
|
||||
expect.objectContaining({
|
||||
action: "platform.retry_completed",
|
||||
platform: "tmall"
|
||||
})
|
||||
])
|
||||
);
|
||||
|
||||
const overviewResponse = await app.inject({
|
||||
method: "GET",
|
||||
url: "/api/observability/overview"
|
||||
});
|
||||
|
||||
expect(overviewResponse.statusCode).toBe(200);
|
||||
expect(
|
||||
overviewResponse
|
||||
.json()
|
||||
.overview.platformRuns.find((metric: { platform: string }) => metric.platform === "tmall")
|
||||
).toMatchObject({
|
||||
platform: "tmall",
|
||||
retryCount: 1,
|
||||
recoveryCount: 1
|
||||
});
|
||||
expect(overviewResponse.json().overview.audits.recoveryActions).toBe(3);
|
||||
|
||||
await app.close();
|
||||
});
|
||||
|
||||
it("keeps the current report version when a blocked Tmall retry does not recover", async () => {
|
||||
const tmallLiveService = createTmallLiveServiceStub({
|
||||
async previewProduct() {
|
||||
|
||||
Reference in New Issue
Block a user