Prepare internal extension distribution

This commit is contained in:
2026-04-29 16:58:35 +08:00
parent 4f1f80b79b
commit 37e29bd6b8
23 changed files with 380 additions and 38 deletions
+112 -1
View File
@@ -1535,6 +1535,117 @@ describe("market-content-entry", () => {
]);
});
test(
"selected export keeps a generic loading status while exporting the default paged range",
async () => {
const pages = [
[
{ authorId: "111", authorName: "达人 A", price21To60s: "¥11,000" },
{ authorId: "222", authorName: "达人 B", price21To60s: "¥22,000" }
],
[{ authorId: "333", authorName: "达人 C", price21To60s: "¥33,000" }],
[{ authorId: "444", authorName: "达人 D", price21To60s: "¥44,000" }],
[{ authorId: "555", authorName: "达人 E", price21To60s: "¥55,000" }],
[{ authorId: "666", authorName: "达人 F", price21To60s: "¥66,000" }]
];
const secondPageDeferred = createDeferred<{
json(): Promise<unknown>;
ok: boolean;
}>();
document.body.innerHTML = buildRealMarketFixture(pages[0]);
const buildCsv = vi.fn(() => "csv-output");
const fetchMock = vi.fn(async (_input: string, init?: RequestInit) => {
const body = JSON.parse(String(init?.body ?? "{}")) as { page?: number };
const pageNumber = body.page ?? 1;
const response = {
json: async () => ({
data: {
marketList: buildMarketListResponseRows(pages[pageNumber - 1] ?? []),
totalPages: 5
}
}),
ok: true
};
if (pageNumber === 2) {
return secondPageDeferred.promise;
}
return response;
});
(
globalThis as typeof globalThis & {
fetch?: typeof fetchMock;
}
).fetch = fetchMock;
document.documentElement.setAttribute(
"data-sces-market-request-snapshot",
JSON.stringify({
body: JSON.stringify({
page: 1
}),
method: "POST",
url: "https://xingtu.cn/api/mock-market-search"
})
);
const { createMarketController } = await import("../src/content/market/index");
const controller = trackController(createMarketController({
buildCsv,
document,
loadAuthorMetrics: async () => ({
success: false,
reason: "request-failed"
}),
onCsvReady: vi.fn(),
window
}));
await controller.ready;
clickSelectionCheckboxForAuthor("111");
click('[data-plugin-export="button"]');
for (let attempt = 0; attempt < 40; attempt += 1) {
if (
fetchMock.mock.calls.some(([, init]) => {
const body = JSON.parse(
String((init as RequestInit | undefined)?.body ?? "{}")
) as { page?: number };
return body.page === 2;
})
) {
break;
}
await new Promise((resolve) => setTimeout(resolve, 50));
await Promise.resolve();
}
expect(
document.querySelector('[data-plugin-export-status="text"]')?.textContent
).toBe("导出中...");
secondPageDeferred.resolve({
json: async () => ({
data: {
marketList: buildMarketListResponseRows(pages[1]),
totalPages: 5
}
}),
ok: true
});
await waitForMockCall(buildCsv, 120, 50);
expect(buildCsv.mock.calls[0][0].map((record) => record.authorId)).toEqual([
"111"
]);
},
15000
);
test("selected export falls back to all creators in the current range when no selection matches", async () => {
const pages = [
[
@@ -1610,11 +1721,11 @@ describe("market-content-entry", () => {
expect(promptBatchName).toHaveBeenCalledTimes(1);
expect(submitBatch).toHaveBeenCalledWith(
expect.objectContaining({
batchId: expect.stringContaining("p7pdhhtde8kj-"),
batchName: "618达人筛选第一批",
logtoUserId: "p7pdhhtde8kj"
})
);
expect(submitBatch.mock.calls[0]?.[0]).not.toHaveProperty("batchId");
});
test("selected batch submit uses only creators selected in the current range", async () => {