Add recovery Excel export and automatic account detection
This commit is contained in:
@@ -2,6 +2,7 @@ import assert from "node:assert/strict";
|
||||
import test from "node:test";
|
||||
import {
|
||||
formatShanghaiDate,
|
||||
formatShanghaiToday,
|
||||
parseStoredDate,
|
||||
} from "../lib/date-utils.ts";
|
||||
|
||||
@@ -14,3 +15,7 @@ test("treats D1 CURRENT_TIMESTAMP values as UTC and displays Beijing time", () =
|
||||
test("keeps date-only deadlines on the intended Shanghai calendar date", () => {
|
||||
assert.match(formatShanghaiDate("2026-08-12"), /08\/12/);
|
||||
});
|
||||
|
||||
test("formats the dashboard date from the Shanghai calendar", () => {
|
||||
assert.equal(formatShanghaiToday(new Date("2026-08-04T16:30:00Z")), "8月5日");
|
||||
});
|
||||
|
||||
52
tests/recovery-workbook.test.mjs
Normal file
52
tests/recovery-workbook.test.mjs
Normal file
@@ -0,0 +1,52 @@
|
||||
import assert from "node:assert/strict";
|
||||
import test from "node:test";
|
||||
import { strFromU8, unzipSync } from "fflate";
|
||||
import { buildRecoveryWorkbook } from "../lib/recovery-workbook.ts";
|
||||
|
||||
const tinyPng = Uint8Array.from([
|
||||
0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a,
|
||||
0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52,
|
||||
0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
|
||||
]);
|
||||
|
||||
test("creates an xlsx archive whose pictures are embedded in worksheet cells", () => {
|
||||
const workbook = buildRecoveryWorkbook({
|
||||
sheetName: "数据回收",
|
||||
headers: ["序号", "标题", "原图", "笔记截图"],
|
||||
columnWidths: [8, 24, 24, 24],
|
||||
rows: [
|
||||
{
|
||||
cells: [1, "测试笔记", "见图", "见图"],
|
||||
images: [
|
||||
{
|
||||
column: 2,
|
||||
image: {
|
||||
bytes: tinyPng,
|
||||
contentType: "image/png",
|
||||
width: 1,
|
||||
height: 1,
|
||||
description: "原图1",
|
||||
},
|
||||
},
|
||||
{
|
||||
column: 3,
|
||||
image: {
|
||||
bytes: tinyPng,
|
||||
contentType: "image/png",
|
||||
width: 1,
|
||||
height: 1,
|
||||
description: "发布截图",
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
});
|
||||
const archive = unzipSync(workbook);
|
||||
|
||||
assert.ok(archive["xl/media/image1.png"]);
|
||||
assert.ok(archive["xl/media/image2.png"]);
|
||||
assert.match(strFromU8(archive["xl/worksheets/sheet1.xml"]), /<drawing r:id="rId1"\/>/);
|
||||
assert.match(strFromU8(archive["xl/drawings/drawing1.xml"]), /oneCellAnchor/);
|
||||
assert.match(strFromU8(archive["xl/drawings/_rels/drawing1.xml.rels"]), /image2\.png/);
|
||||
});
|
||||
@@ -13,6 +13,8 @@ test("builds the KOC LOOP product shell", async () => {
|
||||
assert.match(adminApp, /KOC LOOP/);
|
||||
assert.match(adminApp, /内容分发闭环/);
|
||||
assert.match(adminApp, /分发工作台/);
|
||||
assert.match(adminApp, /formatShanghaiToday/);
|
||||
assert.doesNotMatch(adminApp, /7月27日/);
|
||||
assert.match(adminApp, /获取KOC领取链接/);
|
||||
assert.match(layout, /KOC LOOP|内容分发闭环/);
|
||||
assert.doesNotMatch(adminApp, /codex-preview|Your site is taking shape/);
|
||||
@@ -114,6 +116,8 @@ test("issues external task links and supports one-to-one note submissions", asyn
|
||||
assert.match(partnerRoute, /微信号或手机号/);
|
||||
assert.match(partnerRoute, /extractXhsPublishUrl/);
|
||||
assert.match(partnerRoute, /小红书长链或短链/);
|
||||
assert.match(partnerRoute, /请填写发布链接/);
|
||||
assert.doesNotMatch(partnerRoute, /请填写发布账号昵称和发布链接/);
|
||||
assert.match(partnerRoute, /没有找到领取记录/);
|
||||
assert.match(partnerRoute, /publicImageAssets/);
|
||||
assert.match(partnerRoute, /withPartnerCors/);
|
||||
@@ -224,6 +228,28 @@ test("supports task collection schedules and latest public metrics", async () =>
|
||||
assert.match(deployConfig, /"crons":\["0 2 \* \* \*"\]/);
|
||||
});
|
||||
|
||||
test("exports complete task recovery data to Excel with embedded images", async () => {
|
||||
const [adminApp, exportRoute, workbook] = await Promise.all([
|
||||
readFile(new URL("../app/admin-app.tsx", import.meta.url), "utf8"),
|
||||
readFile(new URL("../app/api/recovery-export/route.ts", import.meta.url), "utf8"),
|
||||
readFile(new URL("../lib/recovery-workbook.ts", import.meta.url), "utf8"),
|
||||
]);
|
||||
|
||||
assert.match(adminApp, /导出全部数据/);
|
||||
assert.match(adminApp, /\/api\/recovery-export/);
|
||||
assert.match(adminApp, /图片和截图已嵌入表格/);
|
||||
assert.match(exportRoute, /小红书昵称/);
|
||||
assert.match(exportRoute, /曝光量-实际(第7天)/);
|
||||
assert.match(exportRoute, /阅读量-实际(第7天)/);
|
||||
assert.match(exportRoute, /publish_screenshot_key/);
|
||||
assert.match(exportRoute, /screenshot_key/);
|
||||
assert.match(exportRoute, /image_assets/);
|
||||
assert.match(exportRoute, /isAdminRequest/);
|
||||
assert.match(workbook, /xl\/drawings\/drawing1\.xml/);
|
||||
assert.match(workbook, /xl\/media\/image/);
|
||||
assert.match(workbook, /oneCellAnchor/);
|
||||
});
|
||||
|
||||
test("supports anonymous partner delegation without creating a second data flow", async () => {
|
||||
const [
|
||||
adminApp,
|
||||
|
||||
Reference in New Issue
Block a user