154 lines
3.9 KiB
TypeScript
154 lines
3.9 KiB
TypeScript
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
|
|
};
|
|
}
|