83 lines
5.8 KiB
TypeScript
83 lines
5.8 KiB
TypeScript
import { mkdtemp, readFile, rm } from "node:fs/promises";
|
|
import os from "node:os";
|
|
import path from "node:path";
|
|
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 "./word";
|
|
import "./word-extended";
|
|
|
|
const directories: 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(directories.splice(0).map((directory) => rm(directory, { recursive: true, force: true }))));
|
|
|
|
const ids = ["Word_New_V1", "Word_GetPath", "Word_ReadAll", "Word_Replace", "Word_Enter", "Word_InsertPage", "Word_SetFontName", "Word_SetFontSize", "Word_SetFontStyle", "Word_SetFontColor", "Word_SetAlign", "Word_InsertPicture", "Word_WriteTable", "Word_Close", "Word_ReadSelect", "Word_CutSelect", "Word_CopySelect", "Word_PasteSelect", "Word_DeleteSelect", "Word_SelectAll", "Word_SelectRow", "Word_SetPosition", "Word_MovePosition", "Word_PositionToSelect", "Word_ReadTable"];
|
|
|
|
describe("Word extended capabilities", () => {
|
|
it("registers automated Word operations", () => { for (const id of ids) expect(getHandler(id), id).toBeTruthy(); });
|
|
|
|
it("creates, writes, reads and replaces Word content", async () => {
|
|
if (process.platform !== "win32") return;
|
|
const directory = await mkdtemp(path.join(os.tmpdir(), "rpa-word-extended-")); directories.push(directory);
|
|
const handle = await run("Word_New_V1", { filePath: directory, name: "extended.docx" });
|
|
await run("Word_Write", { objWord: handle, text: "原始内容" });
|
|
await expect(run("Word_ReadAll", { objWord: handle })).resolves.toContain("原始内容");
|
|
await run("Word_Replace", { objWord: handle, oldText: "原始", newText: "替换后" });
|
|
await expect(run("Word_ReadAll", { objWord: handle })).resolves.toContain("替换后内容");
|
|
await run("Word_SetFontSize", { objWord: handle, fontSize: 12 });
|
|
await run("Word_SetFontStyle", { objWord: handle, isBold: "True", isItalic: "False", isUnderline: "False" });
|
|
await run("Word_Enter", { objWord: handle });
|
|
expect((await readFile(path.join(directory, "extended.docx"))).byteLength).toBeGreaterThan(1000);
|
|
}, 120000);
|
|
|
|
it("uses a persistent selection and reads a Word table through COM", async () => {
|
|
if (process.platform !== "win32") return;
|
|
const directory = await mkdtemp(path.join(os.tmpdir(), "rpa-word-selection-")); directories.push(directory);
|
|
let handle = await run("Word_New_V1", { filePath: directory, name: "selection.docx" });
|
|
await run("Word_Write", { objWord: handle, text: "alpha beta gamma" });
|
|
handle = await run("Word_PositionToSelect", { objWord: handle, text: "beta", pos_index: 1, direction: "select" });
|
|
await expect(run("Word_ReadSelect", { objWord: handle })).resolves.toBe("beta");
|
|
handle = await run("Word_CopySelect", { objWord: handle });
|
|
handle = await run("Word_MovePosition", { objWord: handle, length: 1, unit: "word", direction: "right", isSelect: false });
|
|
await run("Word_PasteSelect", { objWord: handle });
|
|
handle = await run("Word_PositionToSelect", { objWord: handle, text: "gamma", direction: "select" });
|
|
handle = await run("Word_CutSelect", { objWord: handle });
|
|
await expect(run("Word_ReadSelect", { objWord: handle })).resolves.toBe("");
|
|
await run("Word_DeleteSelect", { objWord: handle });
|
|
handle = await run("Word_SetPosition", { objWord: handle, length: -2, unit: "word" });
|
|
handle = await run("Word_SelectRow", { objWord: handle, st: 1, ed: 1 });
|
|
await expect(run("Word_ReadSelect", { objWord: handle })).resolves.toContain("alpha");
|
|
handle = await run("Word_SelectAll", { objWord: handle });
|
|
await expect(run("Word_ReadSelect", { objWord: handle })).resolves.toContain("alpha beta beta");
|
|
await run("Word_WriteTable", { objWord: handle, data: [["name", "age"], ["Alice", "30"]] });
|
|
await expect(run("Word_ReadTable", { objWord: handle, find_type: "content", table_content: "Alice" })).resolves.toEqual([["name", "age"], ["Alice", "30"]]);
|
|
}, 180000);
|
|
|
|
it("saves and saves-as a Word document through real COM", async () => {
|
|
if (process.platform !== "win32") return;
|
|
const directory = await mkdtemp(path.join(os.tmpdir(), "rpa-word-saveas-")); directories.push(directory);
|
|
const handle = await run("Word_New_V1", { filePath: directory, name: "source.docx" });
|
|
await run("Word_Write", { objWord: handle, text: "另存前内容" });
|
|
|
|
await expect(run("Word_Save", { objWord: handle })).resolves.toEqual({ path: path.join(directory, "source.docx") });
|
|
await expect(run("Word_Save", { objWord: { path: path.join(directory, "missing.docx") } })).rejects.toThrow("Word文件不存在");
|
|
|
|
const targetDir = path.join(directory, "out");
|
|
const saved = await run("Word_SaveAs", { objWord: handle, fileAddr: targetDir, filename: "renamed" }) as { path: string };
|
|
expect(saved.path).toBe(path.join(targetDir, "renamed.docx"));
|
|
await expect(readFile(saved.path)).resolves.toBeTruthy();
|
|
|
|
const kept = await run("Word_SaveAs", { objWord: saved, fileAddr: directory }) as { path: string };
|
|
expect(kept.path).toBe(path.join(directory, "renamed.docx"));
|
|
await expect(readFile(kept.path)).resolves.toBeTruthy();
|
|
|
|
const relative = await run("Word_SaveAs", { objWord: kept, fileAddr: "sub", filename: "rel-target" }) as { path: string };
|
|
expect(relative.path).toBe(path.join(directory, "sub", "rel-target.docx"));
|
|
await expect(readFile(relative.path)).resolves.toBeTruthy();
|
|
}, 180000);
|
|
});
|