feat: add full scan controller
This commit is contained in:
@@ -0,0 +1,153 @@
|
||||
import { describe, expect, test, vi } from "vitest";
|
||||
|
||||
import { createFullScanController } from "../src/content/market/full-scan-controller";
|
||||
import { createMarketResultStore } from "../src/content/market/result-store";
|
||||
|
||||
describe("full-scan-controller", () => {
|
||||
test("does not start a scan during initial construction", () => {
|
||||
const readCurrentPageRows = vi.fn(() => []);
|
||||
|
||||
createFullScanController({
|
||||
goToNextPage: async () => false,
|
||||
hasNextPage: () => false,
|
||||
loadAuthorMetrics: async () => ({
|
||||
success: false as const,
|
||||
reason: "request-failed" as const
|
||||
}),
|
||||
readCurrentPageRows,
|
||||
resultStore: createMarketResultStore()
|
||||
});
|
||||
|
||||
expect(readCurrentPageRows).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test("starts a full scan for filter actions", async () => {
|
||||
const harness = createHarness();
|
||||
|
||||
await harness.controller.ensureScanForFilter();
|
||||
|
||||
expect(harness.readCurrentPageRows).toHaveBeenCalledTimes(2);
|
||||
expect(harness.loadAuthorMetrics).toHaveBeenCalledTimes(2);
|
||||
});
|
||||
|
||||
test("starts a full scan for sort actions", async () => {
|
||||
const harness = createHarness();
|
||||
|
||||
await harness.controller.ensureScanForSort();
|
||||
|
||||
expect(harness.readCurrentPageRows).toHaveBeenCalledTimes(2);
|
||||
});
|
||||
|
||||
test("starts a full scan for export actions", async () => {
|
||||
const harness = createHarness();
|
||||
|
||||
await harness.controller.ensureScanForExport();
|
||||
|
||||
expect(harness.readCurrentPageRows).toHaveBeenCalledTimes(2);
|
||||
});
|
||||
|
||||
test("does not restart a completed scan unnecessarily", async () => {
|
||||
const harness = createHarness();
|
||||
|
||||
await harness.controller.ensureScanForFilter();
|
||||
await harness.controller.ensureScanForSort();
|
||||
|
||||
expect(harness.readCurrentPageRows).toHaveBeenCalledTimes(2);
|
||||
expect(harness.loadAuthorMetrics).toHaveBeenCalledTimes(2);
|
||||
});
|
||||
|
||||
test("records failed author fetches without aborting the whole scan", async () => {
|
||||
const store = createMarketResultStore();
|
||||
let pageIndex = 0;
|
||||
const pages = [
|
||||
[
|
||||
{
|
||||
authorId: "a",
|
||||
authorName: "Alpha"
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
authorId: "b",
|
||||
authorName: "Beta"
|
||||
}
|
||||
]
|
||||
];
|
||||
|
||||
const controller = createFullScanController({
|
||||
goToNextPage: async () => {
|
||||
pageIndex += 1;
|
||||
return true;
|
||||
},
|
||||
hasNextPage: () => pageIndex < pages.length - 1,
|
||||
loadAuthorMetrics: async (authorId) =>
|
||||
authorId === "a"
|
||||
? {
|
||||
success: false as const,
|
||||
reason: "request-failed" as const
|
||||
}
|
||||
: {
|
||||
success: true as const,
|
||||
rates: {
|
||||
singleVideoAfterSearchRate: "0.5% - 1%",
|
||||
personalVideoAfterSearchRate: "0.02% - 0.1%"
|
||||
}
|
||||
},
|
||||
readCurrentPageRows: vi.fn(() => pages[pageIndex]),
|
||||
resultStore: store
|
||||
});
|
||||
|
||||
await controller.ensureScanForExport();
|
||||
|
||||
expect(store.getRecord("a")).toMatchObject({
|
||||
status: "failed",
|
||||
failureReason: "request-failed"
|
||||
});
|
||||
expect(store.getRecord("b")).toMatchObject({
|
||||
status: "success"
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
function createHarness() {
|
||||
const store = createMarketResultStore();
|
||||
let pageIndex = 0;
|
||||
const pages = [
|
||||
[
|
||||
{
|
||||
authorId: "a",
|
||||
authorName: "Alpha"
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
authorId: "b",
|
||||
authorName: "Beta"
|
||||
}
|
||||
]
|
||||
];
|
||||
const readCurrentPageRows = vi.fn(() => pages[pageIndex]);
|
||||
const loadAuthorMetrics = vi.fn(async () => ({
|
||||
success: true as const,
|
||||
rates: {
|
||||
singleVideoAfterSearchRate: "0.5% - 1%",
|
||||
personalVideoAfterSearchRate: "0.02% - 0.1%"
|
||||
}
|
||||
}));
|
||||
|
||||
return {
|
||||
controller: createFullScanController({
|
||||
goToNextPage: async () => {
|
||||
pageIndex += 1;
|
||||
return true;
|
||||
},
|
||||
hasNextPage: () => pageIndex < pages.length - 1,
|
||||
loadAuthorMetrics,
|
||||
readCurrentPageRows,
|
||||
resultStore: store
|
||||
}),
|
||||
loadAuthorMetrics,
|
||||
readCurrentPageRows,
|
||||
store
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user