Allow partial market rates in CSV export
This commit is contained in:
@@ -15,7 +15,13 @@ describe("csv-exporter", () => {
|
||||
"地区",
|
||||
"21-60s报价",
|
||||
"单视频看后搜率",
|
||||
"个人视频看后搜率"
|
||||
"个人视频看后搜率",
|
||||
"看后搜率",
|
||||
"看后搜数",
|
||||
"新增A3数",
|
||||
"新增A3率",
|
||||
"CPA3",
|
||||
"cp_search"
|
||||
].join(",")
|
||||
);
|
||||
});
|
||||
@@ -27,10 +33,19 @@ describe("csv-exporter", () => {
|
||||
authorName: "Alice",
|
||||
exportFields: {
|
||||
达人信息: "Alice",
|
||||
代表视频: "示例视频",
|
||||
粉丝数: "100w",
|
||||
"21-60s报价": "¥450,000"
|
||||
},
|
||||
status: "success",
|
||||
backendMetrics: {
|
||||
a3IncreaseCount: "78,366.22",
|
||||
afterViewSearchCount: "9,689.96",
|
||||
afterViewSearchRate: "0.36%",
|
||||
cpSearch: "14.46",
|
||||
cpa3: "1.79",
|
||||
newA3Rate: "3.44%"
|
||||
},
|
||||
rates: {
|
||||
singleVideoAfterSearchRate: "0.5%-1%",
|
||||
personalVideoAfterSearchRate: "1% - 3%"
|
||||
@@ -40,11 +55,56 @@ describe("csv-exporter", () => {
|
||||
|
||||
const [headerLine, rowLine] = csv.split("\n");
|
||||
expect(headerLine).toBe(
|
||||
["达人信息", "粉丝数", "21-60s报价", "单视频看后搜率", "个人视频看后搜率"].join(
|
||||
","
|
||||
)
|
||||
[
|
||||
"达人信息",
|
||||
"粉丝数",
|
||||
"21-60s报价",
|
||||
"单视频看后搜率",
|
||||
"个人视频看后搜率",
|
||||
"看后搜率",
|
||||
"看后搜数",
|
||||
"新增A3数",
|
||||
"新增A3率",
|
||||
"CPA3",
|
||||
"cp_search"
|
||||
].join(",")
|
||||
);
|
||||
expect(rowLine).toBe('Alice,100w,"¥450,000",0.5% - 1%,1% - 3%');
|
||||
expect(rowLine).toBe(
|
||||
'Alice,100w,"¥450,000",0.5% - 1%,1% - 3%,0.36%,"9,689.96","78,366.22",3.44%,1.79,14.46'
|
||||
);
|
||||
});
|
||||
|
||||
test("omits the representative video column from exported page fields", () => {
|
||||
const csv = buildMarketCsv([
|
||||
{
|
||||
authorId: "123",
|
||||
authorName: "Alice",
|
||||
exportFields: {
|
||||
达人信息: "Alice",
|
||||
代表视频: "示例视频",
|
||||
粉丝数: "100w"
|
||||
},
|
||||
status: "success"
|
||||
} satisfies MarketRecord
|
||||
]);
|
||||
|
||||
const [headerLine, rowLine] = csv.split("\n");
|
||||
|
||||
expect(headerLine).toBe(
|
||||
[
|
||||
"达人信息",
|
||||
"粉丝数",
|
||||
"单视频看后搜率",
|
||||
"个人视频看后搜率",
|
||||
"看后搜率",
|
||||
"看后搜数",
|
||||
"新增A3数",
|
||||
"新增A3率",
|
||||
"CPA3",
|
||||
"cp_search"
|
||||
].join(",")
|
||||
);
|
||||
expect(rowLine).toBe("Alice,100w,,,,,,,,");
|
||||
});
|
||||
|
||||
test("escapes commas and quotes", () => {
|
||||
@@ -77,7 +137,7 @@ describe("csv-exporter", () => {
|
||||
]);
|
||||
|
||||
const [, rowLine] = csv.split("\n");
|
||||
expect(rowLine).toBe("123,Alice,,,,");
|
||||
expect(rowLine).toBe("123,Alice,,,,,,,,,,");
|
||||
});
|
||||
|
||||
test("uses normalized display values in export rows", () => {
|
||||
@@ -97,4 +157,21 @@ describe("csv-exporter", () => {
|
||||
expect(rowLine).toContain("0.5% - 1%");
|
||||
expect(rowLine).toContain("0.02% - 0.1%");
|
||||
});
|
||||
|
||||
test("emits empty backend metric cells when backend metrics are absent", () => {
|
||||
const csv = buildMarketCsv([
|
||||
{
|
||||
authorId: "123",
|
||||
authorName: "Alice",
|
||||
status: "success",
|
||||
rates: {
|
||||
singleVideoAfterSearchRate: "0.5%-1%",
|
||||
personalVideoAfterSearchRate: "0.02 - 0.1%"
|
||||
}
|
||||
} satisfies MarketRecord
|
||||
]);
|
||||
|
||||
const [, rowLine] = csv.split("\n");
|
||||
expect(rowLine).toBe("123,Alice,,,0.5% - 1%,0.02% - 0.1%,,,,,,");
|
||||
});
|
||||
});
|
||||
|
||||
@@ -33,12 +33,10 @@ describe("market-api-client", () => {
|
||||
});
|
||||
});
|
||||
|
||||
test("returns a missing-rate failure when the payload omits a required field", () => {
|
||||
test("returns a missing-rate failure when the payload omits both rate fields", () => {
|
||||
expect(
|
||||
mapAuthorAseInfoResponse({
|
||||
data: {
|
||||
avg_search_after_view_rate: "<0.02%"
|
||||
}
|
||||
data: {}
|
||||
})
|
||||
).toMatchObject({
|
||||
success: false,
|
||||
@@ -46,6 +44,21 @@ describe("market-api-client", () => {
|
||||
});
|
||||
});
|
||||
|
||||
test("maps a partially populated payload into partial rates", () => {
|
||||
expect(
|
||||
mapAuthorAseInfoResponse({
|
||||
data: {
|
||||
personal_avg_search_after_view_rate: "0.02 - 0.1%"
|
||||
}
|
||||
})
|
||||
).toMatchObject({
|
||||
success: true,
|
||||
rates: {
|
||||
personalVideoAfterSearchRate: "0.02% - 0.1%"
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
test("returns a request-failed result for non-ok responses", async () => {
|
||||
const client = createMarketApiClient({
|
||||
fetchImpl: async () => ({
|
||||
|
||||
Reference in New Issue
Block a user