implement phase 4
This commit is contained in:
parent
25c2ce53cd
commit
f4b1c3e14b
27 changed files with 6929 additions and 48 deletions
98
addin/src/services/fileService.test.ts
Normal file
98
addin/src/services/fileService.test.ts
Normal file
|
|
@ -0,0 +1,98 @@
|
|||
import { getCurrentDocumentFile, DOCX_CONTENT_TYPE } from "./fileService";
|
||||
|
||||
interface FileMockState {
|
||||
getFileCalls: number;
|
||||
requestedSlices: number[];
|
||||
closeCalls: number;
|
||||
}
|
||||
|
||||
/** mock Office.context.document.getFileAsync + File.getSliceAsync/closeAsync */
|
||||
function installOfficeFileMock(
|
||||
slices: Uint8Array[],
|
||||
options: { failSliceIndex?: number; failClose?: boolean; sliceDataForm?: "buffer" | "view" } = {}
|
||||
): FileMockState {
|
||||
const state: FileMockState = { getFileCalls: 0, requestedSlices: [], closeCalls: 0 };
|
||||
|
||||
const file = {
|
||||
sliceCount: slices.length,
|
||||
getSliceAsync: (index: number, callback: (result: unknown) => void) => {
|
||||
state.requestedSlices.push(index);
|
||||
if (options.failSliceIndex === index) {
|
||||
callback({ status: "failed", error: { message: `อ่าน slice ${index} พัง (mock)` } });
|
||||
} else {
|
||||
// host จริงอาจส่งมาเป็น ArrayBuffer หรือ view — ทดสอบทั้งคู่
|
||||
const data = options.sliceDataForm === "view" ? slices[index] : slices[index].buffer;
|
||||
callback({ status: "succeeded", value: { index, data, size: slices[index].byteLength } });
|
||||
}
|
||||
},
|
||||
closeAsync: (callback?: (result: unknown) => void) => {
|
||||
state.closeCalls++;
|
||||
callback?.({ status: options.failClose ? "failed" : "succeeded" });
|
||||
},
|
||||
};
|
||||
|
||||
(globalThis as unknown as Record<string, unknown>).Office = {
|
||||
FileType: { Compressed: "compressed", Text: "text" },
|
||||
AsyncResultStatus: { Succeeded: "succeeded", Failed: "failed" },
|
||||
context: {
|
||||
document: {
|
||||
getFileAsync: (
|
||||
_fileType: unknown,
|
||||
_options: unknown,
|
||||
callback: (result: unknown) => void
|
||||
) => {
|
||||
state.getFileCalls++;
|
||||
callback({ status: "succeeded", value: file });
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
function bytes(...values: number[]): Uint8Array {
|
||||
return new Uint8Array(values);
|
||||
}
|
||||
|
||||
describe("getCurrentDocumentFile", () => {
|
||||
it("ประกอบ slice หลากขนาดเป็น Blob เดียว อ่านครบทุก slice ตามลำดับ และ closeAsync หนึ่งครั้ง", async () => {
|
||||
const state = installOfficeFileMock([
|
||||
bytes(1, 2, 3),
|
||||
bytes(4, 5),
|
||||
new Uint8Array(2048).fill(9),
|
||||
]);
|
||||
|
||||
const blob = await getCurrentDocumentFile();
|
||||
|
||||
expect(blob.type).toBe(DOCX_CONTENT_TYPE);
|
||||
expect(blob.size).toBe(3 + 2 + 2048);
|
||||
expect(state.requestedSlices).toEqual([0, 1, 2]);
|
||||
expect(state.getFileCalls).toBe(1);
|
||||
expect(state.closeCalls).toBe(1);
|
||||
});
|
||||
|
||||
it("slice มาเป็น typed array view (ไม่ใช่ ArrayBuffer) ก็ประกอบได้", async () => {
|
||||
const state = installOfficeFileMock([bytes(10, 20), bytes(30)], { sliceDataForm: "view" });
|
||||
|
||||
const blob = await getCurrentDocumentFile();
|
||||
|
||||
expect(blob.size).toBe(3);
|
||||
expect(state.closeCalls).toBe(1);
|
||||
});
|
||||
|
||||
it("อ่าน slice กลางที่พัง → reject พร้อม error แต่ยังเรียก closeAsync เสมอ", async () => {
|
||||
const state = installOfficeFileMock([bytes(1), bytes(2), bytes(3)], { failSliceIndex: 1 });
|
||||
|
||||
await expect(getCurrentDocumentFile()).rejects.toThrow("อ่าน slice 1 พัง (mock)");
|
||||
expect(state.closeCalls).toBe(1);
|
||||
expect(state.requestedSlices).toEqual([0, 1]);
|
||||
});
|
||||
|
||||
it("closeAsync fail เอง → ไม่ทำ flow พัง (blob ยังคืนมา)", async () => {
|
||||
installOfficeFileMock([bytes(7, 8, 9)], { failClose: true });
|
||||
|
||||
const blob = await getCurrentDocumentFile();
|
||||
expect(blob.size).toBe(3);
|
||||
});
|
||||
});
|
||||
Loading…
Add table
Add a link
Reference in a new issue