star-chart-search-enhancer/tests/market-api-client.test.ts

125 lines
3.3 KiB
TypeScript

import { afterEach, describe, expect, test, vi } from "vitest";
import {
createMarketApiClient,
mapAuthorAseInfoResponse
} from "../src/content/market/api-client";
import { normalizeRateValue } from "../src/shared/normalize-rate-value";
describe("market api client", () => {
afterEach(() => {
vi.useRealTimers();
});
test("normalizes known rate shapes", () => {
expect(normalizeRateValue("<0.02%")).toBe("<0.02%");
expect(normalizeRateValue("0.02 - 0.1%")).toBe("0.02% - 0.1%");
});
test("maps the known author ase info response fields", () => {
expect(
mapAuthorAseInfoResponse({
data: {
avg_search_after_view_rate: "<0.02%",
personal_avg_search_after_view_rate: "0.02 - 0.1%"
}
})
).toEqual({
rates: {
personalVideoAfterSearchRate: "0.02% - 0.1%",
singleVideoAfterSearchRate: "<0.02%"
},
success: true
});
});
test("returns bad-response when either target field is missing", () => {
expect(
mapAuthorAseInfoResponse({
data: {
avg_search_after_view_rate: "<0.02%"
}
})
).toEqual({
reason: "bad-response",
success: false
});
});
test("issues fetch with credentials include and a timeout signal", async () => {
const fetchImpl = vi.fn(async () => ({
json: async () => ({
data: {
avg_search_after_view_rate: "<0.02%",
personal_avg_search_after_view_rate: "0.02 - 0.1%"
}
}),
ok: true
}));
const client = createMarketApiClient({
baseUrl: "https://xingtu.cn",
fetchImpl,
timeoutMs: 8000
});
const result = await client.loadAuthorAseInfo("6629661559960371207");
expect(fetchImpl).toHaveBeenCalledWith(
"https://xingtu.cn/gw/api/aggregator/get_author_ase_info?author_id=6629661559960371207&range=30",
expect.objectContaining({
credentials: "include",
method: "GET",
signal: expect.any(AbortSignal)
})
);
expect(result).toMatchObject({
success: true
});
});
test("returns timeout when the request is aborted by the timeout budget", async () => {
vi.useFakeTimers();
const fetchImpl = vi.fn(
(_input: string, init?: RequestInit) =>
new Promise((_resolve, reject) => {
init?.signal?.addEventListener("abort", () => {
reject(Object.assign(new Error("aborted"), { name: "AbortError" }));
});
})
);
const client = createMarketApiClient({
baseUrl: "https://xingtu.cn",
fetchImpl,
timeoutMs: 25
});
const resultPromise = client.loadAuthorAseInfo("6629661559960371207");
await vi.advanceTimersByTimeAsync(25);
await expect(resultPromise).resolves.toEqual({
reason: "timeout",
success: false
});
});
test("returns request-failed for non-ok responses", async () => {
const fetchImpl = vi.fn(async () => ({
json: async () => ({}),
ok: false
}));
const client = createMarketApiClient({
baseUrl: "https://xingtu.cn",
fetchImpl,
timeoutMs: 8000
});
await expect(
client.loadAuthorAseInfo("6629661559960371207")
).resolves.toEqual({
reason: "request-failed",
success: false
});
});
});