264 lines
7.1 KiB
TypeScript
264 lines
7.1 KiB
TypeScript
// @vitest-environment jsdom
|
|
|
|
import { describe, expect, test } from "vitest";
|
|
|
|
import { createSilentExportController } from "../src/content/market/silent-export-controller";
|
|
|
|
describe("silent-export-controller", () => {
|
|
test("replays exports from the live market page state when the request snapshot attribute is missing", async () => {
|
|
document.body.innerHTML = '<div class="base-author-list"></div>';
|
|
const marketRoot = document.querySelector(".base-author-list") as HTMLElement & {
|
|
__vue__?: {
|
|
_setupState?: Record<string, unknown>;
|
|
};
|
|
};
|
|
marketRoot.__vue__ = {
|
|
_setupState: {
|
|
__$temp_1: {
|
|
reqParams: {
|
|
scene_param: {
|
|
platform_source: 1
|
|
},
|
|
page_param: {
|
|
limit: "20",
|
|
page: "2"
|
|
},
|
|
search_param: {
|
|
seach_type: 3
|
|
}
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
const requestedPages: number[] = [];
|
|
const requestedHeaders: Array<HeadersInit | undefined> = [];
|
|
const requestedUrls: string[] = [];
|
|
const controller = createSilentExportController({
|
|
document,
|
|
fetchImpl: async (url, init) => {
|
|
const body = JSON.parse(String(init?.body ?? "{}")) as {
|
|
page_param?: { page?: number | string };
|
|
};
|
|
const pageNo = Number(body.page_param?.page ?? 0);
|
|
requestedPages.push(pageNo);
|
|
requestedHeaders.push(init?.headers);
|
|
requestedUrls.push(url);
|
|
|
|
return {
|
|
json: async () => ({
|
|
authors: [
|
|
{
|
|
attribute_datas: {
|
|
nickname: `达人${pageNo}`,
|
|
price_20_60: pageNo * 1000
|
|
},
|
|
star_id: String(pageNo)
|
|
}
|
|
],
|
|
pagination: {
|
|
limit: 20,
|
|
page: pageNo,
|
|
total_count: 100
|
|
}
|
|
}),
|
|
ok: true
|
|
};
|
|
}
|
|
});
|
|
|
|
const records = await controller.exportRecords({
|
|
mode: "count",
|
|
pageCount: 2
|
|
});
|
|
|
|
expect(requestedPages).toEqual([2, 3]);
|
|
expect(
|
|
requestedUrls.every((url) =>
|
|
url.endsWith("/gw/api/gsearch/search_for_author_square")
|
|
)
|
|
).toBe(true);
|
|
expect(requestedHeaders).toEqual([
|
|
{
|
|
Accept: "application/json, text/plain, */*",
|
|
"Agw-Js-Conv": "str",
|
|
"Content-Type": "application/json",
|
|
"x-login-source": "1"
|
|
},
|
|
{
|
|
Accept: "application/json, text/plain, */*",
|
|
"Agw-Js-Conv": "str",
|
|
"Content-Type": "application/json",
|
|
"x-login-source": "1"
|
|
}
|
|
]);
|
|
expect(records?.map((record) => record.authorId)).toEqual(["2", "3"]);
|
|
});
|
|
|
|
test("replays paged exports when the page number is nested inside the request body", async () => {
|
|
document.documentElement.setAttribute(
|
|
"data-sces-market-request-snapshot",
|
|
JSON.stringify({
|
|
body: JSON.stringify({
|
|
page_param: {
|
|
page: 2
|
|
}
|
|
}),
|
|
method: "POST",
|
|
url: "https://xingtu.cn/api/mock-market-search"
|
|
})
|
|
);
|
|
|
|
const requestedPages: number[] = [];
|
|
const controller = createSilentExportController({
|
|
document,
|
|
fetchImpl: async (_url, init) => {
|
|
const body = JSON.parse(String(init?.body ?? "{}")) as {
|
|
page_param?: { page?: number };
|
|
};
|
|
const pageNo = body.page_param?.page ?? 0;
|
|
requestedPages.push(pageNo);
|
|
|
|
return {
|
|
json: async () => ({
|
|
authors: [
|
|
{
|
|
attribute_datas: {
|
|
nickname: `达人${pageNo}`,
|
|
price_20_60: pageNo * 1000
|
|
},
|
|
star_id: String(pageNo)
|
|
}
|
|
],
|
|
pagination: {
|
|
limit: 20,
|
|
page: pageNo,
|
|
total_count: 100
|
|
}
|
|
}),
|
|
ok: true
|
|
};
|
|
}
|
|
});
|
|
|
|
const records = await controller.exportRecords({
|
|
mode: "count",
|
|
pageCount: 2
|
|
});
|
|
|
|
expect(requestedPages).toEqual([2, 3]);
|
|
expect(records?.map((record) => record.authorId)).toEqual(["2", "3"]);
|
|
});
|
|
|
|
test("starts from page 1 when the captured request omits an explicit page number", async () => {
|
|
document.documentElement.setAttribute(
|
|
"data-sces-market-request-snapshot",
|
|
JSON.stringify({
|
|
body: JSON.stringify({
|
|
filters: {
|
|
keyword: "test"
|
|
}
|
|
}),
|
|
method: "POST",
|
|
url: "https://xingtu.cn/api/mock-market-search"
|
|
})
|
|
);
|
|
|
|
const requestedPages: number[] = [];
|
|
const controller = createSilentExportController({
|
|
document,
|
|
fetchImpl: async (_url, init) => {
|
|
const body = JSON.parse(String(init?.body ?? "{}")) as { page?: number };
|
|
const page = body.page ?? 0;
|
|
requestedPages.push(page);
|
|
|
|
return {
|
|
json: async () => ({
|
|
data: {
|
|
marketList: [
|
|
{
|
|
attribute_datas: {
|
|
nickname: `达人${page}`,
|
|
price_20_60: page * 1000
|
|
},
|
|
star_id: String(page)
|
|
}
|
|
]
|
|
}
|
|
}),
|
|
ok: true
|
|
};
|
|
}
|
|
});
|
|
|
|
const records = await controller.exportRecords({
|
|
mode: "count",
|
|
pageCount: 2
|
|
});
|
|
|
|
expect(requestedPages).toEqual([1, 2]);
|
|
expect(records?.map((record) => record.authorId)).toEqual(["1", "2"]);
|
|
});
|
|
|
|
test("accepts snapshot headers that contain non-string values from the live XHR capture", async () => {
|
|
document.body.innerHTML = "";
|
|
document.documentElement.setAttribute(
|
|
"data-sces-market-request-snapshot",
|
|
JSON.stringify({
|
|
body: JSON.stringify({
|
|
page_param: {
|
|
page: "1",
|
|
limit: "20"
|
|
}
|
|
}),
|
|
headers: {
|
|
Accept: "application/json, text/plain, */*",
|
|
"Content-Type": "application/json",
|
|
"x-login-source": 1,
|
|
"Agw-Js-Conv": "str"
|
|
},
|
|
method: "POST",
|
|
url: "/gw/api/gsearch/search_for_author_square"
|
|
})
|
|
);
|
|
|
|
const requestedPages: number[] = [];
|
|
const controller = createSilentExportController({
|
|
document,
|
|
fetchImpl: async (_url, init) => {
|
|
const body = JSON.parse(String(init?.body ?? "{}")) as {
|
|
page_param?: { page?: number | string };
|
|
};
|
|
requestedPages.push(Number(body.page_param?.page ?? 0));
|
|
|
|
return {
|
|
json: async () => ({
|
|
authors: [
|
|
{
|
|
attribute_datas: {
|
|
nickname: "达人1"
|
|
},
|
|
star_id: "1"
|
|
}
|
|
],
|
|
pagination: {
|
|
limit: 20,
|
|
page: 1,
|
|
total_count: 20
|
|
}
|
|
}),
|
|
ok: true
|
|
};
|
|
}
|
|
});
|
|
|
|
const records = await controller.exportRecords({
|
|
mode: "count",
|
|
pageCount: 1
|
|
});
|
|
|
|
expect(requestedPages).toEqual([1]);
|
|
expect(records?.map((record) => record.authorId)).toEqual(["1"]);
|
|
});
|
|
});
|