PRA-only-demo/packages/rpa-core/src/capabilities/excel-store.test.ts
yu caa8e19332 阶段1-rpa-core建包: engine+31个纯Node能力迁入packages/rpa-core, 领域类型单一源化, createEngine工厂收拢模块级状态
- engine/(registry/types/runtime/expression)物理迁入包, 解耦shared/types(域类型归包, 宿主type-only re-export)
- 31个纯Node能力+27个测试迁入包; 宿主留守Electron/浏览器/AI依赖能力, index.ts经@rpa/core/capabilities拉起
- 新增createEngine()/defaultEngine: excel缓存/Excel句柄/db连接/FTP客户端/OCR实例/拟真设置挂引擎实例
- remaining-core子流程依赖改为host-bridge注入, 包内不再import宿主flows
- 宿主main/index.ts启动时注入子流程源; electron-vite/vitest/tsconfig配@rpa/core源码别名
- 验证: typecheck绿, 快照909个id diff为零, 332测试过(2个桌面冒烟因会话无交互SetForegroundWindow被拒, 环境阻塞)
2026-11-04 12:36:03 +08:00

69 lines
4.5 KiB
TypeScript

import { mkdtemp, rm } from "node:fs/promises";
import os from "node:os";
import path from "node:path";
import ExcelJS from "exceljs";
import { afterEach, describe, expect, it } from "vitest";
import type { CatalogComponent, FlowNode } from "../types";
import type { RunContext } from "../engine/types";
import { getHandler } from "../engine/registry";
import "./office";
import "./extended";
import "./office-file-extended";
import "./office-aliases";
import "./excel-common";
import "./common-final";
const dirs: string[] = [];
const context = {} as RunContext;
const component = {} as CatalogComponent;
const node = (id: string): FlowNode => ({ id, componentId: id, position: { x: 0, y: 0 }, values: {}, options: {} });
async function run(id: string, args: Record<string, unknown>) { const handler = getHandler(id); expect(handler, id).toBeTruthy(); return handler!(context, node(id), args, component); }
afterEach(async () => Promise.all(dirs.splice(0).map((dir) => rm(dir, { recursive: true, force: true }))));
describe("excel shared workbook store", () => {
it("keeps widths/heights set by office-file-extended when excel-common saves afterwards", async () => {
const directory = await mkdtemp(path.join(os.tmpdir(), "rpa-store-")); dirs.push(directory);
const handle = await run("Excel_NewExcel", { filePath: directory, name: "a.xlsx", isMakedirs: "True" }) as { path: string };
await run("Excel_Cs_WriteRangeV2", { workbook: handle, sheet: "Sheet1", row: "1", column: "A", contents: [["名称", "数量", "备注"], ["鼠标", 20, "A;B"]], isSave: "True" });
await run("Excel_Cs_SetWidth", { workbook: handle, sheet: "Sheet1", columns: "A:C", width: "20", save: "True" });
await run("Excel_Cs_SetHeight", { workbook: handle, sheet: "Sheet1", rows: "1", height: "26", save: "True" });
await run("Excel_Cs_MergeCells", { workbook: handle, sheet: "Sheet1", range: "A1:C1", merge: "0", save: "True" });
await run("Excel_Cs_SetRangeBackground", { workbook: handle, sheet: "Sheet1", range: "A1:C1", color: "FFF2CC", save: "True" });
await run("Excel_SetCellFontColor", { objExcel: handle, sheet: "Sheet1", cellPos: "A1", cellColor: "FF0000", isSave: "True" });
const wb = new ExcelJS.Workbook();
await wb.xlsx.readFile(handle.path);
const ws = wb.worksheets[0];
expect(ws.getColumn("A").width).toBe(20);
expect(ws.getRow(1).height).toBe(26);
expect(ws.model.merges).toContain("A1:C1");
expect((ws.getCell("A1").fill as ExcelJS.FillPattern).fgColor?.argb).toBe("FFFFF2CC");
expect((ws.getCell("A1").font?.color as { argb?: string } | undefined)?.argb).toBe("FFFF0000");
expect(ws.getCell("A1").value).toBe("名称");
});
it("keeps copied sheets created by office-file-extended when sheets are created and deleted later", async () => {
const directory = await mkdtemp(path.join(os.tmpdir(), "rpa-store-")); dirs.push(directory);
const handle = await run("Excel_NewExcel", { filePath: directory, name: "b.xlsx", isMakedirs: "True" }) as { path: string };
await run("Excel_Cs_WriteRangeV2", { workbook: handle, sheet: "Sheet1", row: "1", column: "A", contents: [["名称"]], isSave: "True" });
await run("Excel_Cs_CopyV2", { workbook: handle, sheet: "Sheet1", newSheet: "Sheet1副本", override: "True", save: "True" });
await run("Excel_CreateSheet", { workbook: handle, sheet: "临时表", save: "True" });
await run("Excel_DeleteSheet", { workbook: handle, sheet: "临时表", save: "True" });
const wb = new ExcelJS.Workbook();
await wb.xlsx.readFile(handle.path);
expect(wb.worksheets.map((sheet) => sheet.name)).toEqual(["Sheet1", "Sheet1副本"]);
});
it("keeps the shared instance usable after save-as switches the handle path", async () => {
const directory = await mkdtemp(path.join(os.tmpdir(), "rpa-store-")); dirs.push(directory);
const handle = await run("Excel_NewExcel", { filePath: directory, name: "c.xlsx", isMakedirs: "True" }) as { path: string };
await run("Excel_Cs_SetWidth", { workbook: handle, sheet: "Sheet1", columns: "A", width: "18", save: "True" });
const saved = await run("Excel_Cs_SaveAs", { workbook: handle, path: path.join(directory, "d.xlsx") }) as { path: string };
expect(saved.path).toBe(path.resolve(directory, "d.xlsx"));
await run("Excel_Cs_SetHeight", { workbook: handle, sheet: "Sheet1", rows: "1", height: "30", save: "True" });
const wb = new ExcelJS.Workbook();
await wb.xlsx.readFile(path.resolve(directory, "d.xlsx"));
expect(wb.worksheets[0].getColumn("A").width).toBe(18);
expect(wb.worksheets[0].getRow(1).height).toBe(30);
});
});