feat: export author spread metrics

This commit is contained in:
wxs
2026-06-29 16:06:14 +08:00
parent 7839380613
commit 121977fd0d
14 changed files with 1117 additions and 20 deletions
+69 -9
View File
@@ -1,6 +1,7 @@
import { describe, expect, test } from "vitest";
import { buildMarketCsv } from "../src/content/market/csv-exporter";
import { buildSpreadInfoColumns } from "../src/content/market/spread-info";
import type { MarketRecord } from "../src/content/market/types";
describe("csv-exporter", () => {
@@ -21,12 +22,13 @@ describe("csv-exporter", () => {
"秒思api-新增A3数",
"秒思api-新增A3率",
"秒思api-CPA3",
"秒思api-cp_search"
"秒思api-cp_search",
...buildSpreadInfoColumns()
].join(",")
);
});
test("uses page export field order and appends the two plugin columns", () => {
test("uses page export field order and appends the plugin columns", () => {
const csv = buildMarketCsv([
{
authorId: "123",
@@ -66,11 +68,16 @@ describe("csv-exporter", () => {
"秒思api-新增A3数",
"秒思api-新增A3率",
"秒思api-CPA3",
"秒思api-cp_search"
"秒思api-cp_search",
...buildSpreadInfoColumns()
].join(",")
);
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'
expect(rowLine).toMatch(
new RegExp(
`^${escapeRegExp(
'Alice,100w,"¥450,000",0.5% - 1%,1% - 3%,0.36%,"9,689.96","78,366.22",3.44%,1.79,14.46'
)}`
)
);
});
@@ -101,10 +108,13 @@ describe("csv-exporter", () => {
"秒思api-新增A3数",
"秒思api-新增A3率",
"秒思api-CPA3",
"秒思api-cp_search"
"秒思api-cp_search",
...buildSpreadInfoColumns()
].join(",")
);
expect(rowLine).toBe("Alice,100w,,,,,,,,");
expect(rowLine.split(",").slice(0, 10).join(",")).toBe(
"Alice,100w,,,,,,,,"
);
});
test("escapes commas and quotes", () => {
@@ -137,7 +147,10 @@ describe("csv-exporter", () => {
]);
const [, rowLine] = csv.split("\n");
expect(rowLine).toBe("123,Alice,,,,,,,,,,");
expect(rowLine.split(",").slice(0, 12).join(",")).toBe(
"123,Alice,,,,,,,,,,"
);
expect(rowLine.split(",").slice(12).every((cell) => cell === "")).toBe(true);
});
test("uses normalized display values in export rows", () => {
@@ -172,6 +185,53 @@ describe("csv-exporter", () => {
]);
const [, rowLine] = csv.split("\n");
expect(rowLine).toBe("123,Alice,,,0.5% - 1%,0.02% - 0.1%,,,,,,");
expect(rowLine.split(",").slice(0, 12).join(",")).toBe(
"123,Alice,,,0.5% - 1%,0.02% - 0.1%,,,,,,"
);
});
test("appends spread info metric columns after backend metrics", () => {
const csv = buildMarketCsv([
{
authorId: "123",
authorName: "Alice",
spreadMetrics: {
"个人视频_近30天_完播率": "28.24%",
"只看指派_排除营销流量_星图视频_近30天_互动率": "4.02%"
},
status: "success"
} satisfies MarketRecord
]);
const [headerLine, rowLine] = csv.split("\n");
expect(headerLine).toContain(
[
"秒思api-cp_search",
"个人视频_近30天_完播率",
"个人视频_近30天_播放量中位数"
].join(",")
);
expect(headerLine).toContain(
"只看指派_排除营销流量_星图视频_近30天_互动率"
);
expect(rowLine).toContain("28.24%");
expect(rowLine).toContain("4.02%");
});
test("emits empty spread info cells when spread metrics are absent", () => {
const csv = buildMarketCsv([
{
authorId: "123",
authorName: "Alice",
status: "success"
} satisfies MarketRecord
]);
const [, rowLine] = csv.split("\n");
expect(rowLine.split(",").slice(-70).every((cell) => cell === "")).toBe(true);
});
});
function escapeRegExp(value: string): string {
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
}