@embedpdf/engine-core 3.0.0-next.0 → 3.0.0-next.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{AbortError-CjSasIlL.js → AbortError-8-9JAX1Y.js} +2 -2
- package/dist/{AbortError-CjSasIlL.js.map → AbortError-8-9JAX1Y.js.map} +1 -1
- package/dist/{AbortError-ByBflvEl.cjs → AbortError-CRSooKsk.cjs} +2 -2
- package/dist/{AbortError-ByBflvEl.cjs.map → AbortError-CRSooKsk.cjs.map} +1 -1
- package/dist/{AnnotationListSnapshot-W0RCsyDE.d.cts → AnnotationListSnapshot-DDxHpJQU.d.cts} +538 -41
- package/dist/{AnnotationListSnapshot-W0RCsyDE.d.ts → AnnotationListSnapshot-DDxHpJQU.d.ts} +538 -41
- package/dist/{DocumentSecurityService-Df79fgpe.d.cts → DocumentSecurityService-BV4_YXkU.d.cts} +33 -2
- package/dist/{DocumentSecurityService-B-tULKNY.d.ts → DocumentSecurityService-o9aeTHwT.d.ts} +33 -2
- package/dist/{Engine-D9loFZc1.d.cts → Engine-D9je6GdU.d.cts} +50 -19
- package/dist/{Engine-B7Oe7f5i.d.ts → Engine-DOoVem7_.d.ts} +50 -19
- package/dist/{subtype-qejjVr6h.cjs → PageInsertBlankInput-CzShuSJI.cjs} +184 -1
- package/dist/PageInsertBlankInput-CzShuSJI.cjs.map +1 -0
- package/dist/{subtype-BvAzLCGC.js → PageInsertBlankInput-WKY0tr6S.js} +149 -2
- package/dist/PageInsertBlankInput-WKY0tr6S.js.map +1 -0
- package/dist/{builders-C548U47M.js → builders-B_KufGJ9.js} +547 -169
- package/dist/builders-B_KufGJ9.js.map +1 -0
- package/dist/{builders-BvikWRuO.cjs → builders-Cp_rlGob.cjs} +603 -225
- package/dist/builders-Cp_rlGob.cjs.map +1 -0
- package/dist/conformance.cjs +822 -198
- package/dist/conformance.cjs.map +1 -1
- package/dist/conformance.d.cts +124 -6
- package/dist/conformance.d.ts +124 -6
- package/dist/conformance.js +777 -157
- package/dist/conformance.js.map +1 -1
- package/dist/{fold-CB4fAOOy.js → fold-BfyxxwS6.js} +162 -3
- package/dist/fold-BfyxxwS6.js.map +1 -0
- package/dist/{fold-IaMph3CO.cjs → fold-C7I5GpBz.cjs} +235 -4
- package/dist/fold-C7I5GpBz.cjs.map +1 -0
- package/dist/index.cjs +36 -18
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +4 -4
- package/dist/runtime.cjs +41 -23
- package/dist/runtime.cjs.map +1 -1
- package/dist/runtime.d.cts +103 -5
- package/dist/runtime.d.ts +103 -5
- package/dist/runtime.js +5 -5
- package/dist/{schemas-B_1VyFsm.cjs → schemas-D1pxEv3t.cjs} +138 -32
- package/dist/schemas-D1pxEv3t.cjs.map +1 -0
- package/dist/{schemas-9OpSSeM6.js → schemas-DAnu8tuW.js} +95 -13
- package/dist/schemas-DAnu8tuW.js.map +1 -0
- package/dist/wire.cjs +118 -3
- package/dist/wire.cjs.map +1 -1
- package/dist/wire.d.cts +139 -27
- package/dist/wire.d.ts +139 -27
- package/dist/wire.js +111 -4
- package/dist/wire.js.map +1 -1
- package/package.json +1 -1
- package/dist/builders-BvikWRuO.cjs.map +0 -1
- package/dist/builders-C548U47M.js.map +0 -1
- package/dist/fold-CB4fAOOy.js.map +0 -1
- package/dist/fold-IaMph3CO.cjs.map +0 -1
- package/dist/schemas-9OpSSeM6.js.map +0 -1
- package/dist/schemas-B_1VyFsm.cjs.map +0 -1
- package/dist/subtype-BvAzLCGC.js.map +0 -1
- package/dist/subtype-qejjVr6h.cjs.map +0 -1
package/dist/conformance.cjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const
|
|
3
|
-
const
|
|
4
|
-
const require_AbortError = require("./AbortError-
|
|
5
|
-
const require_schemas = require("./schemas-
|
|
2
|
+
const require_fold = require("./fold-C7I5GpBz.cjs");
|
|
3
|
+
const require_PageInsertBlankInput = require("./PageInsertBlankInput-CzShuSJI.cjs");
|
|
4
|
+
const require_AbortError = require("./AbortError-CRSooKsk.cjs");
|
|
5
|
+
const require_schemas = require("./schemas-D1pxEv3t.cjs");
|
|
6
6
|
//#region src/conformance/runMetadataConformance.ts
|
|
7
7
|
/**
|
|
8
8
|
* The conformance harness is transport-agnostic. It takes the test runner as
|
|
@@ -19,7 +19,7 @@ function runMetadataConformance(runner, opts) {
|
|
|
19
19
|
if (engine) await engine.destroy();
|
|
20
20
|
});
|
|
21
21
|
test("reads metadata from sample fixture", async () => {
|
|
22
|
-
const doc = await openFixture$
|
|
22
|
+
const doc = await openFixture$17(engine, opts);
|
|
23
23
|
try {
|
|
24
24
|
const meta = await doc.metadata.read();
|
|
25
25
|
expect(meta).toMatchObject(opts.fixture.expected);
|
|
@@ -29,7 +29,7 @@ function runMetadataConformance(runner, opts) {
|
|
|
29
29
|
}
|
|
30
30
|
});
|
|
31
31
|
test("abort() before completion rejects with AbortError", async () => {
|
|
32
|
-
const doc = await openFixture$
|
|
32
|
+
const doc = await openFixture$17(engine, opts);
|
|
33
33
|
try {
|
|
34
34
|
const p = doc.metadata.read();
|
|
35
35
|
p.abort("test");
|
|
@@ -39,7 +39,7 @@ function runMetadataConformance(runner, opts) {
|
|
|
39
39
|
}
|
|
40
40
|
});
|
|
41
41
|
test("aborting one read does not affect a concurrent one", async () => {
|
|
42
|
-
const doc = await openFixture$
|
|
42
|
+
const doc = await openFixture$17(engine, opts);
|
|
43
43
|
try {
|
|
44
44
|
const a = doc.metadata.read();
|
|
45
45
|
const b = doc.metadata.read();
|
|
@@ -51,7 +51,7 @@ function runMetadataConformance(runner, opts) {
|
|
|
51
51
|
}
|
|
52
52
|
});
|
|
53
53
|
test("metadata after close throws DocNotOpen", async () => {
|
|
54
|
-
const doc = await openFixture$
|
|
54
|
+
const doc = await openFixture$17(engine, opts);
|
|
55
55
|
await doc.close();
|
|
56
56
|
let caught;
|
|
57
57
|
try {
|
|
@@ -60,10 +60,10 @@ function runMetadataConformance(runner, opts) {
|
|
|
60
60
|
caught = err;
|
|
61
61
|
}
|
|
62
62
|
expect(caught).toBeTruthy();
|
|
63
|
-
expect(require_fold.EngineError.is(caught,
|
|
63
|
+
expect(require_fold.EngineError.is(caught, require_PageInsertBlankInput.EngineErrorCode.DocNotOpen)).toBe(true);
|
|
64
64
|
});
|
|
65
65
|
test("update() sets standard + custom fields and a subsequent read observes them", async () => {
|
|
66
|
-
const doc = await openFixture$
|
|
66
|
+
const doc = await openFixture$17(engine, opts);
|
|
67
67
|
try {
|
|
68
68
|
const result = await doc.metadata.update({
|
|
69
69
|
title: "Conformance Title",
|
|
@@ -82,7 +82,7 @@ function runMetadataConformance(runner, opts) {
|
|
|
82
82
|
}
|
|
83
83
|
});
|
|
84
84
|
test("update() clears a field with null", async () => {
|
|
85
|
-
const doc = await openFixture$
|
|
85
|
+
const doc = await openFixture$17(engine, opts);
|
|
86
86
|
try {
|
|
87
87
|
await doc.metadata.update({ title: "To Be Cleared" });
|
|
88
88
|
const set = await doc.metadata.read();
|
|
@@ -95,7 +95,7 @@ function runMetadataConformance(runner, opts) {
|
|
|
95
95
|
}
|
|
96
96
|
});
|
|
97
97
|
test("update() after close throws DocNotOpen", async () => {
|
|
98
|
-
const doc = await openFixture$
|
|
98
|
+
const doc = await openFixture$17(engine, opts);
|
|
99
99
|
await doc.close();
|
|
100
100
|
let caught;
|
|
101
101
|
try {
|
|
@@ -104,11 +104,11 @@ function runMetadataConformance(runner, opts) {
|
|
|
104
104
|
caught = err;
|
|
105
105
|
}
|
|
106
106
|
expect(caught).toBeTruthy();
|
|
107
|
-
expect(require_fold.EngineError.is(caught,
|
|
107
|
+
expect(require_fold.EngineError.is(caught, require_PageInsertBlankInput.EngineErrorCode.DocNotOpen)).toBe(true);
|
|
108
108
|
});
|
|
109
109
|
});
|
|
110
110
|
}
|
|
111
|
-
async function openFixture$
|
|
111
|
+
async function openFixture$17(engine, opts) {
|
|
112
112
|
if (opts.openKind === "bytes") {
|
|
113
113
|
const bytes = await opts.fixture.bytes();
|
|
114
114
|
return engine.open({
|
|
@@ -135,11 +135,12 @@ function runAnnotationReadConformance(runner, opts) {
|
|
|
135
135
|
if (engine) await engine.destroy();
|
|
136
136
|
});
|
|
137
137
|
test("listRawAll returns one entry per page with valid PageState", async () => {
|
|
138
|
-
const doc = await openFixture$
|
|
138
|
+
const doc = await openFixture$16(engine, opts);
|
|
139
139
|
try {
|
|
140
140
|
const snap = await doc.annotations.listRawAll();
|
|
141
141
|
expect(require_schemas.AnnotationListSnapshotAllPagesSchema.safeParse(snap).success).toBe(true);
|
|
142
142
|
expect(snap.pages.length >= 1).toBe(true);
|
|
143
|
+
if (snap.auditHead !== void 0) expect(Number.isInteger(snap.auditHead) && snap.auditHead >= 0).toBe(true);
|
|
143
144
|
const target = snap.pages.find((p) => p.pageState.pageObjectNumber === opts.fixture.pageObjectNumber);
|
|
144
145
|
expect(target !== void 0).toBe(true);
|
|
145
146
|
expect(target.annotations.length).toBe(opts.fixture.expectedAnnotationCount);
|
|
@@ -148,7 +149,7 @@ function runAnnotationReadConformance(runner, opts) {
|
|
|
148
149
|
}
|
|
149
150
|
});
|
|
150
151
|
test("listRaw on the test page returns the expected counts and DTO shape", async () => {
|
|
151
|
-
const doc = await openFixture$
|
|
152
|
+
const doc = await openFixture$16(engine, opts);
|
|
152
153
|
try {
|
|
153
154
|
const snap = await doc.annotations.listRaw(opts.fixture.pageObjectNumber);
|
|
154
155
|
expect(require_schemas.AnnotationListPageSnapshotSchema.safeParse(snap).success).toBe(true);
|
|
@@ -178,7 +179,7 @@ function runAnnotationReadConformance(runner, opts) {
|
|
|
178
179
|
}
|
|
179
180
|
});
|
|
180
181
|
test("shape/vertex/line annotations expose their family fields", async () => {
|
|
181
|
-
const doc = await openFixture$
|
|
182
|
+
const doc = await openFixture$16(engine, opts);
|
|
182
183
|
try {
|
|
183
184
|
const snap = await doc.annotations.listRaw(opts.fixture.pageObjectNumber);
|
|
184
185
|
for (const a of snap.annotations) {
|
|
@@ -237,7 +238,7 @@ function runAnnotationReadConformance(runner, opts) {
|
|
|
237
238
|
}
|
|
238
239
|
});
|
|
239
240
|
test("full page list dispatches per-subtype and matches raw counts", async () => {
|
|
240
|
-
const doc = await openFixture$
|
|
241
|
+
const doc = await openFixture$16(engine, opts);
|
|
241
242
|
try {
|
|
242
243
|
const full = await doc.page(opts.fixture.pageObjectNumber).annotations.list();
|
|
243
244
|
expect(require_schemas.AnnotationListPageSnapshotSchema.safeParse(full).success).toBe(true);
|
|
@@ -247,7 +248,7 @@ function runAnnotationReadConformance(runner, opts) {
|
|
|
247
248
|
}
|
|
248
249
|
});
|
|
249
250
|
test("every annotation DTO satisfies AnnotationDTOSchema (discriminated union)", async () => {
|
|
250
|
-
const doc = await openFixture$
|
|
251
|
+
const doc = await openFixture$16(engine, opts);
|
|
251
252
|
try {
|
|
252
253
|
const snap = await doc.annotations.listRaw(opts.fixture.pageObjectNumber);
|
|
253
254
|
for (const a of snap.annotations) {
|
|
@@ -287,7 +288,7 @@ function runAnnotationReadConformance(runner, opts) {
|
|
|
287
288
|
});
|
|
288
289
|
if (opts.fixture.expectsWeakAnnotation) {
|
|
289
290
|
test("weak annotations carry identityQuality: weak and ref.kind: index", async () => {
|
|
290
|
-
const doc = await openFixture$
|
|
291
|
+
const doc = await openFixture$16(engine, opts);
|
|
291
292
|
try {
|
|
292
293
|
const weak = (await doc.annotations.listRaw(opts.fixture.pageObjectNumber)).annotations.find((a) => a.identityQuality === "weak");
|
|
293
294
|
expect(weak !== void 0).toBe(true);
|
|
@@ -297,7 +298,7 @@ function runAnnotationReadConformance(runner, opts) {
|
|
|
297
298
|
}
|
|
298
299
|
});
|
|
299
300
|
test("a stale revision token throws InvalidReference", async () => {
|
|
300
|
-
const doc = await openFixture$
|
|
301
|
+
const doc = await openFixture$16(engine, opts);
|
|
301
302
|
try {
|
|
302
303
|
const snap = await doc.page(opts.fixture.pageObjectNumber).annotations.list();
|
|
303
304
|
const weak = snap.annotations.find((a) => a.identityQuality === "weak");
|
|
@@ -313,7 +314,7 @@ function runAnnotationReadConformance(runner, opts) {
|
|
|
313
314
|
});
|
|
314
315
|
}
|
|
315
316
|
test("abort() on listRaw rejects with AbortError", async () => {
|
|
316
|
-
const doc = await openFixture$
|
|
317
|
+
const doc = await openFixture$16(engine, opts);
|
|
317
318
|
try {
|
|
318
319
|
const p = doc.annotations.listRaw(opts.fixture.pageObjectNumber);
|
|
319
320
|
p.abort("test");
|
|
@@ -323,7 +324,7 @@ function runAnnotationReadConformance(runner, opts) {
|
|
|
323
324
|
}
|
|
324
325
|
});
|
|
325
326
|
test("listRaw on an unknown pageObjectNumber throws NotFound", async () => {
|
|
326
|
-
const doc = await openFixture$
|
|
327
|
+
const doc = await openFixture$16(engine, opts);
|
|
327
328
|
try {
|
|
328
329
|
let caught;
|
|
329
330
|
try {
|
|
@@ -332,14 +333,14 @@ function runAnnotationReadConformance(runner, opts) {
|
|
|
332
333
|
caught = err;
|
|
333
334
|
}
|
|
334
335
|
expect(caught).toBeTruthy();
|
|
335
|
-
expect(require_fold.EngineError.is(caught,
|
|
336
|
+
expect(require_fold.EngineError.is(caught, require_PageInsertBlankInput.EngineErrorCode.NotFound)).toBe(true);
|
|
336
337
|
} finally {
|
|
337
338
|
await doc.close();
|
|
338
339
|
}
|
|
339
340
|
});
|
|
340
341
|
});
|
|
341
342
|
}
|
|
342
|
-
async function openFixture$
|
|
343
|
+
async function openFixture$16(engine, opts) {
|
|
343
344
|
if (opts.openKind === "bytes") {
|
|
344
345
|
const bytes = await opts.fixture.bytes();
|
|
345
346
|
return engine.open({
|
|
@@ -597,7 +598,7 @@ function runAnnotationMutationConformance(runner, opts) {
|
|
|
597
598
|
if (engine) await engine.destroy();
|
|
598
599
|
});
|
|
599
600
|
test("create appends without shifting indices and leaves weak refs valid", async () => {
|
|
600
|
-
const doc = await openFixture$
|
|
601
|
+
const doc = await openFixture$15(engine, opts);
|
|
601
602
|
try {
|
|
602
603
|
const page = doc.page(fix.pageObjectNumber);
|
|
603
604
|
const before = await page.annotations.list();
|
|
@@ -633,7 +634,7 @@ function runAnnotationMutationConformance(runner, opts) {
|
|
|
633
634
|
}
|
|
634
635
|
});
|
|
635
636
|
test("create + update honor annotation flags (set on create, merge on patch)", async () => {
|
|
636
|
-
const doc = await openFixture$
|
|
637
|
+
const doc = await openFixture$15(engine, opts);
|
|
637
638
|
try {
|
|
638
639
|
const page = doc.page(fix.pageObjectNumber);
|
|
639
640
|
const draft = {
|
|
@@ -668,7 +669,7 @@ function runAnnotationMutationConformance(runner, opts) {
|
|
|
668
669
|
}
|
|
669
670
|
});
|
|
670
671
|
test("create shape annotations (circle + square) round-trip shape fields", async () => {
|
|
671
|
-
const doc = await openFixture$
|
|
672
|
+
const doc = await openFixture$15(engine, opts);
|
|
672
673
|
try {
|
|
673
674
|
const page = doc.page(fix.pageObjectNumber);
|
|
674
675
|
const circleDraft = {
|
|
@@ -749,7 +750,7 @@ function runAnnotationMutationConformance(runner, opts) {
|
|
|
749
750
|
}
|
|
750
751
|
});
|
|
751
752
|
test("cloudy border (/BE) + rect differences (/RD) are tri-state", async () => {
|
|
752
|
-
const doc = await openFixture$
|
|
753
|
+
const doc = await openFixture$15(engine, opts);
|
|
753
754
|
try {
|
|
754
755
|
const page = doc.page(fix.pageObjectNumber);
|
|
755
756
|
const plainDraft = {
|
|
@@ -828,7 +829,7 @@ function runAnnotationMutationConformance(runner, opts) {
|
|
|
828
829
|
}
|
|
829
830
|
});
|
|
830
831
|
test("update echoes the appearance verdict: moves preserve /AP, restyles re-bake", async () => {
|
|
831
|
-
const doc = await openFixture$
|
|
832
|
+
const doc = await openFixture$15(engine, opts);
|
|
832
833
|
try {
|
|
833
834
|
const page = doc.page(fix.pageObjectNumber);
|
|
834
835
|
const draft = {
|
|
@@ -903,7 +904,7 @@ function runAnnotationMutationConformance(runner, opts) {
|
|
|
903
904
|
}
|
|
904
905
|
});
|
|
905
906
|
test("a partial /DA patch preserves the unpatched font members", async () => {
|
|
906
|
-
const doc = await openFixture$
|
|
907
|
+
const doc = await openFixture$15(engine, opts);
|
|
907
908
|
try {
|
|
908
909
|
const page = doc.page(fix.pageObjectNumber);
|
|
909
910
|
const draft = {
|
|
@@ -959,7 +960,7 @@ function runAnnotationMutationConformance(runner, opts) {
|
|
|
959
960
|
}
|
|
960
961
|
});
|
|
961
962
|
test("box transform is tri-state: rect-only moves keep rotation, null flattens", async () => {
|
|
962
|
-
const doc = await openFixture$
|
|
963
|
+
const doc = await openFixture$15(engine, opts);
|
|
963
964
|
try {
|
|
964
965
|
const page = doc.page(fix.pageObjectNumber);
|
|
965
966
|
const draft = {
|
|
@@ -1020,7 +1021,7 @@ function runAnnotationMutationConformance(runner, opts) {
|
|
|
1020
1021
|
}
|
|
1021
1022
|
});
|
|
1022
1023
|
test("create vertex + line annotations (polygon/polyline/line) round-trip geometry", async () => {
|
|
1023
|
-
const doc = await openFixture$
|
|
1024
|
+
const doc = await openFixture$15(engine, opts);
|
|
1024
1025
|
try {
|
|
1025
1026
|
const page = doc.page(fix.pageObjectNumber);
|
|
1026
1027
|
const polygonDraft = {
|
|
@@ -1151,7 +1152,7 @@ function runAnnotationMutationConformance(runner, opts) {
|
|
|
1151
1152
|
}
|
|
1152
1153
|
});
|
|
1153
1154
|
test("create free-text + callout round-trip text/colour/intent fields", async () => {
|
|
1154
|
-
const doc = await openFixture$
|
|
1155
|
+
const doc = await openFixture$15(engine, opts);
|
|
1155
1156
|
try {
|
|
1156
1157
|
const page = doc.page(fix.pageObjectNumber);
|
|
1157
1158
|
const freeTextDraft = {
|
|
@@ -1247,7 +1248,7 @@ function runAnnotationMutationConformance(runner, opts) {
|
|
|
1247
1248
|
}
|
|
1248
1249
|
});
|
|
1249
1250
|
test("update a free-text patches alignment + colours and is non-structural", async () => {
|
|
1250
|
-
const doc = await openFixture$
|
|
1251
|
+
const doc = await openFixture$15(engine, opts);
|
|
1251
1252
|
try {
|
|
1252
1253
|
const page = doc.page(fix.pageObjectNumber);
|
|
1253
1254
|
const created = await page.annotations.create({
|
|
@@ -1308,7 +1309,7 @@ function runAnnotationMutationConformance(runner, opts) {
|
|
|
1308
1309
|
}
|
|
1309
1310
|
});
|
|
1310
1311
|
test("create redact (area + text) round-trips label + colour fields", async () => {
|
|
1311
|
-
const doc = await openFixture$
|
|
1312
|
+
const doc = await openFixture$15(engine, opts);
|
|
1312
1313
|
try {
|
|
1313
1314
|
const page = doc.page(fix.pageObjectNumber);
|
|
1314
1315
|
const areaDraft = {
|
|
@@ -1388,7 +1389,7 @@ function runAnnotationMutationConformance(runner, opts) {
|
|
|
1388
1389
|
}
|
|
1389
1390
|
});
|
|
1390
1391
|
test("update a redact patches the label and clears it, non-structurally", async () => {
|
|
1391
|
-
const doc = await openFixture$
|
|
1392
|
+
const doc = await openFixture$15(engine, opts);
|
|
1392
1393
|
try {
|
|
1393
1394
|
const page = doc.page(fix.pageObjectNumber);
|
|
1394
1395
|
const created = await page.annotations.create({
|
|
@@ -1465,7 +1466,7 @@ function runAnnotationMutationConformance(runner, opts) {
|
|
|
1465
1466
|
}
|
|
1466
1467
|
});
|
|
1467
1468
|
test("create + update a caret round-trips color/opacity/rect differences", async () => {
|
|
1468
|
-
const doc = await openFixture$
|
|
1469
|
+
const doc = await openFixture$15(engine, opts);
|
|
1469
1470
|
try {
|
|
1470
1471
|
const page = doc.page(fix.pageObjectNumber);
|
|
1471
1472
|
const caretDraft = {
|
|
@@ -1545,7 +1546,7 @@ function runAnnotationMutationConformance(runner, opts) {
|
|
|
1545
1546
|
}
|
|
1546
1547
|
});
|
|
1547
1548
|
test("update an ink annotation patches strokes + color and is non-structural", async () => {
|
|
1548
|
-
const doc = await openFixture$
|
|
1549
|
+
const doc = await openFixture$15(engine, opts);
|
|
1549
1550
|
try {
|
|
1550
1551
|
const page = doc.page(fix.pageObjectNumber);
|
|
1551
1552
|
const created = await page.annotations.create({
|
|
@@ -1596,7 +1597,7 @@ function runAnnotationMutationConformance(runner, opts) {
|
|
|
1596
1597
|
}
|
|
1597
1598
|
});
|
|
1598
1599
|
test("ink highlight intent + blend round-trip and unrelated patches preserve blend", async () => {
|
|
1599
|
-
const doc = await openFixture$
|
|
1600
|
+
const doc = await openFixture$15(engine, opts);
|
|
1600
1601
|
try {
|
|
1601
1602
|
const page = doc.page(fix.pageObjectNumber);
|
|
1602
1603
|
const created = await page.annotations.create({
|
|
@@ -1639,7 +1640,7 @@ function runAnnotationMutationConformance(runner, opts) {
|
|
|
1639
1640
|
}
|
|
1640
1641
|
});
|
|
1641
1642
|
test("update a polyline patches vertices + line endings and is non-structural", async () => {
|
|
1642
|
-
const doc = await openFixture$
|
|
1643
|
+
const doc = await openFixture$15(engine, opts);
|
|
1643
1644
|
try {
|
|
1644
1645
|
const page = doc.page(fix.pageObjectNumber);
|
|
1645
1646
|
const created = await page.annotations.create({
|
|
@@ -1688,7 +1689,7 @@ function runAnnotationMutationConformance(runner, opts) {
|
|
|
1688
1689
|
}
|
|
1689
1690
|
});
|
|
1690
1691
|
test("update a shape annotation patches color and is non-structural", async () => {
|
|
1691
|
-
const doc = await openFixture$
|
|
1692
|
+
const doc = await openFixture$15(engine, opts);
|
|
1692
1693
|
try {
|
|
1693
1694
|
const page = doc.page(fix.pageObjectNumber);
|
|
1694
1695
|
const created = await page.annotations.create({
|
|
@@ -1737,7 +1738,7 @@ function runAnnotationMutationConformance(runner, opts) {
|
|
|
1737
1738
|
}
|
|
1738
1739
|
});
|
|
1739
1740
|
if (opts.supportsAppearanceRasters) test("creating a shape bakes an /AP appearance the reader can rasterize", async () => {
|
|
1740
|
-
const doc = await openFixture$
|
|
1741
|
+
const doc = await openFixture$15(engine, opts);
|
|
1741
1742
|
try {
|
|
1742
1743
|
const page = doc.page(fix.pageObjectNumber);
|
|
1743
1744
|
const created = await page.annotations.create({
|
|
@@ -1767,7 +1768,7 @@ function runAnnotationMutationConformance(runner, opts) {
|
|
|
1767
1768
|
}
|
|
1768
1769
|
});
|
|
1769
1770
|
test("update on a durable annotation is non-structural and never touches /NM", async () => {
|
|
1770
|
-
const doc = await openFixture$
|
|
1771
|
+
const doc = await openFixture$15(engine, opts);
|
|
1771
1772
|
try {
|
|
1772
1773
|
const page = doc.page(fix.pageObjectNumber);
|
|
1773
1774
|
const before = await page.annotations.list();
|
|
@@ -1793,7 +1794,7 @@ function runAnnotationMutationConformance(runner, opts) {
|
|
|
1793
1794
|
}
|
|
1794
1795
|
});
|
|
1795
1796
|
if (fix.expectsWeakAnnotation) test("update on a weak annotation stamps a UUID v4 /NM and upgrades the ref", async () => {
|
|
1796
|
-
const doc = await openFixture$
|
|
1797
|
+
const doc = await openFixture$15(engine, opts);
|
|
1797
1798
|
try {
|
|
1798
1799
|
const page = doc.page(fix.pageObjectNumber);
|
|
1799
1800
|
const before = await page.annotations.list();
|
|
@@ -1823,7 +1824,7 @@ function runAnnotationMutationConformance(runner, opts) {
|
|
|
1823
1824
|
}
|
|
1824
1825
|
});
|
|
1825
1826
|
test("delete by objectNumber removes the annotation and reports a stable id", async () => {
|
|
1826
|
-
const doc = await openFixture$
|
|
1827
|
+
const doc = await openFixture$15(engine, opts);
|
|
1827
1828
|
try {
|
|
1828
1829
|
const page = doc.page(fix.pageObjectNumber);
|
|
1829
1830
|
const draft = {
|
|
@@ -1853,7 +1854,7 @@ function runAnnotationMutationConformance(runner, opts) {
|
|
|
1853
1854
|
}
|
|
1854
1855
|
});
|
|
1855
1856
|
if (fix.expectsWeakAnnotation) test("delete by index of a weak annotation reports deleted: null and refetch reason", async () => {
|
|
1856
|
-
const doc = await openFixture$
|
|
1857
|
+
const doc = await openFixture$15(engine, opts);
|
|
1857
1858
|
try {
|
|
1858
1859
|
const page = doc.page(fix.pageObjectNumber);
|
|
1859
1860
|
const weak = (await page.annotations.list()).annotations.find((a) => a.identityQuality === "weak");
|
|
@@ -1876,7 +1877,7 @@ function runAnnotationMutationConformance(runner, opts) {
|
|
|
1876
1877
|
}
|
|
1877
1878
|
});
|
|
1878
1879
|
test("abort on create rejects with AbortError", async () => {
|
|
1879
|
-
const doc = await openFixture$
|
|
1880
|
+
const doc = await openFixture$15(engine, opts);
|
|
1880
1881
|
try {
|
|
1881
1882
|
const page = doc.page(fix.pageObjectNumber);
|
|
1882
1883
|
const draft = {
|
|
@@ -1892,7 +1893,7 @@ function runAnnotationMutationConformance(runner, opts) {
|
|
|
1892
1893
|
}
|
|
1893
1894
|
});
|
|
1894
1895
|
test("update with a stale index revision throws InvalidReference", async () => {
|
|
1895
|
-
const doc = await openFixture$
|
|
1896
|
+
const doc = await openFixture$15(engine, opts);
|
|
1896
1897
|
try {
|
|
1897
1898
|
const page = doc.page(fix.pageObjectNumber);
|
|
1898
1899
|
const weak = (await page.annotations.list()).annotations.find((a) => a.identityQuality === "weak");
|
|
@@ -1913,13 +1914,13 @@ function runAnnotationMutationConformance(runner, opts) {
|
|
|
1913
1914
|
} catch (err) {
|
|
1914
1915
|
caught = err;
|
|
1915
1916
|
}
|
|
1916
|
-
expect(require_fold.EngineError.is(caught,
|
|
1917
|
+
expect(require_fold.EngineError.is(caught, require_PageInsertBlankInput.EngineErrorCode.InvalidReference)).toBe(true);
|
|
1917
1918
|
} finally {
|
|
1918
1919
|
await doc.close();
|
|
1919
1920
|
}
|
|
1920
1921
|
});
|
|
1921
1922
|
test("move single durable annotation reorders within the page (single-as-batch)", async () => {
|
|
1922
|
-
const doc = await openFixture$
|
|
1923
|
+
const doc = await openFixture$15(engine, opts);
|
|
1923
1924
|
try {
|
|
1924
1925
|
const page = doc.page(fix.pageObjectNumber);
|
|
1925
1926
|
const aDraft = {
|
|
@@ -1963,7 +1964,7 @@ function runAnnotationMutationConformance(runner, opts) {
|
|
|
1963
1964
|
}
|
|
1964
1965
|
});
|
|
1965
1966
|
test("move multi-block preserves caller-supplied order at the destination", async () => {
|
|
1966
|
-
const doc = await openFixture$
|
|
1967
|
+
const doc = await openFixture$15(engine, opts);
|
|
1967
1968
|
try {
|
|
1968
1969
|
const page = doc.page(fix.pageObjectNumber);
|
|
1969
1970
|
const ids = await Promise.all([
|
|
@@ -2002,7 +2003,7 @@ function runAnnotationMutationConformance(runner, opts) {
|
|
|
2002
2003
|
}
|
|
2003
2004
|
});
|
|
2004
2005
|
if (fix.expectsWeakAnnotation) test("move on a weak annotation upgrades it to durable /NM (one rev bump for batch)", async () => {
|
|
2005
|
-
const doc = await openFixture$
|
|
2006
|
+
const doc = await openFixture$15(engine, opts);
|
|
2006
2007
|
try {
|
|
2007
2008
|
const page = doc.page(fix.pageObjectNumber);
|
|
2008
2009
|
const before = await page.annotations.list();
|
|
@@ -2027,7 +2028,7 @@ function runAnnotationMutationConformance(runner, opts) {
|
|
|
2027
2028
|
}
|
|
2028
2029
|
});
|
|
2029
2030
|
test("move with a stale index revision rejects (locked rev-token guard)", async () => {
|
|
2030
|
-
const doc = await openFixture$
|
|
2031
|
+
const doc = await openFixture$15(engine, opts);
|
|
2031
2032
|
try {
|
|
2032
2033
|
const page = doc.page(fix.pageObjectNumber);
|
|
2033
2034
|
const a = await page.annotations.create({
|
|
@@ -2059,13 +2060,13 @@ function runAnnotationMutationConformance(runner, opts) {
|
|
|
2059
2060
|
} finally {
|
|
2060
2061
|
await weakSession?.release();
|
|
2061
2062
|
}
|
|
2062
|
-
expect(require_fold.EngineError.is(caught,
|
|
2063
|
+
expect(require_fold.EngineError.is(caught, require_PageInsertBlankInput.EngineErrorCode.InvalidReference)).toBe(true);
|
|
2063
2064
|
} finally {
|
|
2064
2065
|
await doc.close();
|
|
2065
2066
|
}
|
|
2066
2067
|
});
|
|
2067
2068
|
test("move with out-of-range toIndex rejects with InvalidArg", async () => {
|
|
2068
|
-
const doc = await openFixture$
|
|
2069
|
+
const doc = await openFixture$15(engine, opts);
|
|
2069
2070
|
try {
|
|
2070
2071
|
const page = doc.page(fix.pageObjectNumber);
|
|
2071
2072
|
const a = await page.annotations.create({
|
|
@@ -2083,13 +2084,13 @@ function runAnnotationMutationConformance(runner, opts) {
|
|
|
2083
2084
|
} finally {
|
|
2084
2085
|
await weakSession?.release();
|
|
2085
2086
|
}
|
|
2086
|
-
expect(require_fold.EngineError.is(caught,
|
|
2087
|
+
expect(require_fold.EngineError.is(caught, require_PageInsertBlankInput.EngineErrorCode.InvalidArg)).toBe(true);
|
|
2087
2088
|
} finally {
|
|
2088
2089
|
await doc.close();
|
|
2089
2090
|
}
|
|
2090
2091
|
});
|
|
2091
2092
|
test("move with duplicate refs rejects with InvalidArg", async () => {
|
|
2092
|
-
const doc = await openFixture$
|
|
2093
|
+
const doc = await openFixture$15(engine, opts);
|
|
2093
2094
|
try {
|
|
2094
2095
|
const page = doc.page(fix.pageObjectNumber);
|
|
2095
2096
|
const a = await page.annotations.create({
|
|
@@ -2106,13 +2107,13 @@ function runAnnotationMutationConformance(runner, opts) {
|
|
|
2106
2107
|
} finally {
|
|
2107
2108
|
await weakSession?.release();
|
|
2108
2109
|
}
|
|
2109
|
-
expect(require_fold.EngineError.is(caught,
|
|
2110
|
+
expect(require_fold.EngineError.is(caught, require_PageInsertBlankInput.EngineErrorCode.InvalidArg)).toBe(true);
|
|
2110
2111
|
} finally {
|
|
2111
2112
|
await doc.close();
|
|
2112
2113
|
}
|
|
2113
2114
|
});
|
|
2114
2115
|
test("abort on move rejects with AbortError", async () => {
|
|
2115
|
-
const doc = await openFixture$
|
|
2116
|
+
const doc = await openFixture$15(engine, opts);
|
|
2116
2117
|
try {
|
|
2117
2118
|
const page = doc.page(fix.pageObjectNumber);
|
|
2118
2119
|
const a = await page.annotations.create({
|
|
@@ -2133,7 +2134,7 @@ function runAnnotationMutationConformance(runner, opts) {
|
|
|
2133
2134
|
}
|
|
2134
2135
|
});
|
|
2135
2136
|
test("a page move does NOT bump per-page RevisionTokens (weak refs survive reorder)", async () => {
|
|
2136
|
-
const doc = await openFixture$
|
|
2137
|
+
const doc = await openFixture$15(engine, opts);
|
|
2137
2138
|
try {
|
|
2138
2139
|
const list = await doc.pages.list();
|
|
2139
2140
|
if (list.pages.length < 1) return;
|
|
@@ -2148,7 +2149,7 @@ function runAnnotationMutationConformance(runner, opts) {
|
|
|
2148
2149
|
}
|
|
2149
2150
|
});
|
|
2150
2151
|
test("create a reply links /IRT and defaults /RT to \"reply\", reporting the parent", async () => {
|
|
2151
|
-
const doc = await openFixture$
|
|
2152
|
+
const doc = await openFixture$15(engine, opts);
|
|
2152
2153
|
try {
|
|
2153
2154
|
const page = doc.page(fix.pageObjectNumber);
|
|
2154
2155
|
const parent = await page.annotations.create({
|
|
@@ -2182,7 +2183,7 @@ function runAnnotationMutationConformance(runner, opts) {
|
|
|
2182
2183
|
}
|
|
2183
2184
|
});
|
|
2184
2185
|
test("create a grouped subordinate writes /RT /Group", async () => {
|
|
2185
|
-
const doc = await openFixture$
|
|
2186
|
+
const doc = await openFixture$15(engine, opts);
|
|
2186
2187
|
try {
|
|
2187
2188
|
const page = doc.page(fix.pageObjectNumber);
|
|
2188
2189
|
const primary = await page.annotations.create({
|
|
@@ -2213,7 +2214,7 @@ function runAnnotationMutationConformance(runner, opts) {
|
|
|
2213
2214
|
}
|
|
2214
2215
|
});
|
|
2215
2216
|
test("create link annotations round-trip uri, goto/xyz, goto/fitH, and dead targets", async () => {
|
|
2216
|
-
const doc = await openFixture$
|
|
2217
|
+
const doc = await openFixture$15(engine, opts);
|
|
2217
2218
|
try {
|
|
2218
2219
|
const page = doc.page(fix.pageObjectNumber);
|
|
2219
2220
|
const uri = await page.annotations.create({
|
|
@@ -2290,7 +2291,7 @@ function runAnnotationMutationConformance(runner, opts) {
|
|
|
2290
2291
|
}
|
|
2291
2292
|
});
|
|
2292
2293
|
test("a link patch retargets in both directions (uri→goto, goto→uri) and moves the rect", async () => {
|
|
2293
|
-
const doc = await openFixture$
|
|
2294
|
+
const doc = await openFixture$15(engine, opts);
|
|
2294
2295
|
try {
|
|
2295
2296
|
const page = doc.page(fix.pageObjectNumber);
|
|
2296
2297
|
const created = await page.annotations.create({
|
|
@@ -2345,7 +2346,7 @@ function runAnnotationMutationConformance(runner, opts) {
|
|
|
2345
2346
|
}
|
|
2346
2347
|
});
|
|
2347
2348
|
test("a link patch clears the target with null — a dead link on re-read", async () => {
|
|
2348
|
-
const doc = await openFixture$
|
|
2349
|
+
const doc = await openFixture$15(engine, opts);
|
|
2349
2350
|
try {
|
|
2350
2351
|
const page = doc.page(fix.pageObjectNumber);
|
|
2351
2352
|
const created = await page.annotations.create({
|
|
@@ -2384,7 +2385,7 @@ function runAnnotationMutationConformance(runner, opts) {
|
|
|
2384
2385
|
}
|
|
2385
2386
|
});
|
|
2386
2387
|
test("a link grouped to a highlight round-trips /IRT + /RT /Group with its target", async () => {
|
|
2387
|
-
const doc = await openFixture$
|
|
2388
|
+
const doc = await openFixture$15(engine, opts);
|
|
2388
2389
|
try {
|
|
2389
2390
|
const page = doc.page(fix.pageObjectNumber);
|
|
2390
2391
|
const parent = await page.annotations.create({
|
|
@@ -2418,7 +2419,7 @@ function runAnnotationMutationConformance(runner, opts) {
|
|
|
2418
2419
|
}
|
|
2419
2420
|
});
|
|
2420
2421
|
test("replace-text round-trips /IT and groups StrikeOut under its Caret", async () => {
|
|
2421
|
-
const doc = await openFixture$
|
|
2422
|
+
const doc = await openFixture$15(engine, opts);
|
|
2422
2423
|
try {
|
|
2423
2424
|
const page = doc.page(fix.pageObjectNumber);
|
|
2424
2425
|
const caret = await page.annotations.create({
|
|
@@ -2470,7 +2471,7 @@ function runAnnotationMutationConformance(runner, opts) {
|
|
|
2470
2471
|
}
|
|
2471
2472
|
});
|
|
2472
2473
|
test("patch inReplyTo: null clears /IRT and /RT (back to top-level)", async () => {
|
|
2473
|
-
const doc = await openFixture$
|
|
2474
|
+
const doc = await openFixture$15(engine, opts);
|
|
2474
2475
|
try {
|
|
2475
2476
|
const page = doc.page(fix.pageObjectNumber);
|
|
2476
2477
|
const parent = await page.annotations.create({
|
|
@@ -2497,7 +2498,7 @@ function runAnnotationMutationConformance(runner, opts) {
|
|
|
2497
2498
|
}
|
|
2498
2499
|
});
|
|
2499
2500
|
test("create with a cross-page /IRT parent throws InvalidArg", async () => {
|
|
2500
|
-
const doc = await openFixture$
|
|
2501
|
+
const doc = await openFixture$15(engine, opts);
|
|
2501
2502
|
try {
|
|
2502
2503
|
const page = doc.page(fix.pageObjectNumber);
|
|
2503
2504
|
const parent = await page.annotations.create({
|
|
@@ -2522,7 +2523,130 @@ function runAnnotationMutationConformance(runner, opts) {
|
|
|
2522
2523
|
} catch (err) {
|
|
2523
2524
|
caught = err;
|
|
2524
2525
|
}
|
|
2525
|
-
expect(require_fold.EngineError.is(caught,
|
|
2526
|
+
expect(require_fold.EngineError.is(caught, require_PageInsertBlankInput.EngineErrorCode.InvalidArg)).toBe(true);
|
|
2527
|
+
} finally {
|
|
2528
|
+
await doc.close();
|
|
2529
|
+
}
|
|
2530
|
+
});
|
|
2531
|
+
test("a review-status reply round-trips /State + /StateModel + /Subj", async () => {
|
|
2532
|
+
const doc = await openFixture$15(engine, opts);
|
|
2533
|
+
try {
|
|
2534
|
+
const page = doc.page(fix.pageObjectNumber);
|
|
2535
|
+
const target = await page.annotations.create({
|
|
2536
|
+
subtype: "highlight",
|
|
2537
|
+
contents: "status target",
|
|
2538
|
+
subject: "Pricing question",
|
|
2539
|
+
quadPoints: quad
|
|
2540
|
+
});
|
|
2541
|
+
expect(target.created.subject).toBe("Pricing question");
|
|
2542
|
+
const status = await page.annotations.create({
|
|
2543
|
+
subtype: "text",
|
|
2544
|
+
rect: shapeRect,
|
|
2545
|
+
inReplyTo: target.created.ref,
|
|
2546
|
+
state: "accepted",
|
|
2547
|
+
stateModel: "review"
|
|
2548
|
+
});
|
|
2549
|
+
expect(require_schemas.AnnotationCreateResultSchema.safeParse(status).success).toBe(true);
|
|
2550
|
+
expect(status.created.subtype).toBe("text");
|
|
2551
|
+
if (status.created.subtype !== "text") return;
|
|
2552
|
+
expect(status.created.state).toBe("accepted");
|
|
2553
|
+
expect(status.created.stateModel).toBe("review");
|
|
2554
|
+
expect(status.created.replyType).toBe("reply");
|
|
2555
|
+
const read = (await page.annotations.list()).annotations.find((a) => a.ref.kind === "objectNumber" && status.created.ref.kind === "objectNumber" && a.ref.annotObjectNumber === status.created.ref.annotObjectNumber);
|
|
2556
|
+
expect(read?.subtype).toBe("text");
|
|
2557
|
+
if (read?.subtype === "text") {
|
|
2558
|
+
expect(read.state).toBe("accepted");
|
|
2559
|
+
expect(read.stateModel).toBe("review");
|
|
2560
|
+
}
|
|
2561
|
+
} finally {
|
|
2562
|
+
await doc.close();
|
|
2563
|
+
}
|
|
2564
|
+
});
|
|
2565
|
+
test("a draft /State without /StateModel is rejected with InvalidArg", async () => {
|
|
2566
|
+
const doc = await openFixture$15(engine, opts);
|
|
2567
|
+
try {
|
|
2568
|
+
const page = doc.page(fix.pageObjectNumber);
|
|
2569
|
+
let caught;
|
|
2570
|
+
try {
|
|
2571
|
+
await page.annotations.create({
|
|
2572
|
+
subtype: "text",
|
|
2573
|
+
rect: shapeRect,
|
|
2574
|
+
state: "accepted"
|
|
2575
|
+
});
|
|
2576
|
+
} catch (err) {
|
|
2577
|
+
caught = err;
|
|
2578
|
+
}
|
|
2579
|
+
expect(require_fold.EngineError.is(caught, require_PageInsertBlankInput.EngineErrorCode.InvalidArg)).toBe(true);
|
|
2580
|
+
} finally {
|
|
2581
|
+
await doc.close();
|
|
2582
|
+
}
|
|
2583
|
+
});
|
|
2584
|
+
test("null-clear patches truly remove /State, /StateModel, /Subj and /Contents", async () => {
|
|
2585
|
+
const doc = await openFixture$15(engine, opts);
|
|
2586
|
+
try {
|
|
2587
|
+
const page = doc.page(fix.pageObjectNumber);
|
|
2588
|
+
const note = await page.annotations.create({
|
|
2589
|
+
subtype: "text",
|
|
2590
|
+
rect: shapeRect,
|
|
2591
|
+
contents: "work in progress",
|
|
2592
|
+
subject: "Draft",
|
|
2593
|
+
state: "none",
|
|
2594
|
+
stateModel: "review"
|
|
2595
|
+
});
|
|
2596
|
+
const cycled = await page.annotations.update(note.created.ref, {
|
|
2597
|
+
subtype: "text",
|
|
2598
|
+
state: "rejected"
|
|
2599
|
+
});
|
|
2600
|
+
expect(cycled.appearance.changed).toBe(false);
|
|
2601
|
+
expect(cycled.updated.subtype).toBe("text");
|
|
2602
|
+
if (cycled.updated.subtype === "text") {
|
|
2603
|
+
expect(cycled.updated.state).toBe("rejected");
|
|
2604
|
+
expect(cycled.updated.stateModel).toBe("review");
|
|
2605
|
+
}
|
|
2606
|
+
const cleared = await page.annotations.update(note.created.ref, {
|
|
2607
|
+
subtype: "text",
|
|
2608
|
+
contents: null,
|
|
2609
|
+
subject: null,
|
|
2610
|
+
state: null,
|
|
2611
|
+
stateModel: null
|
|
2612
|
+
});
|
|
2613
|
+
expect(cleared.appearance.changed).toBe(false);
|
|
2614
|
+
expect(cleared.updated.contents).toBe(null);
|
|
2615
|
+
expect(cleared.updated.subject).toBe(null);
|
|
2616
|
+
if (cleared.updated.subtype === "text") {
|
|
2617
|
+
expect(cleared.updated.state).toBe(null);
|
|
2618
|
+
expect(cleared.updated.stateModel).toBe(null);
|
|
2619
|
+
}
|
|
2620
|
+
const read = (await page.annotations.list()).annotations.find((a) => a.ref.kind === "objectNumber" && note.created.ref.kind === "objectNumber" && a.ref.annotObjectNumber === note.created.ref.annotObjectNumber);
|
|
2621
|
+
expect(read?.contents).toBe(null);
|
|
2622
|
+
expect(read?.subject).toBe(null);
|
|
2623
|
+
if (read?.subtype === "text") {
|
|
2624
|
+
expect(read.state).toBe(null);
|
|
2625
|
+
expect(read.stateModel).toBe(null);
|
|
2626
|
+
}
|
|
2627
|
+
} finally {
|
|
2628
|
+
await doc.close();
|
|
2629
|
+
}
|
|
2630
|
+
});
|
|
2631
|
+
test("custom state models round-trip verbatim", async () => {
|
|
2632
|
+
const doc = await openFixture$15(engine, opts);
|
|
2633
|
+
try {
|
|
2634
|
+
const page = doc.page(fix.pageObjectNumber);
|
|
2635
|
+
const custom = await page.annotations.create({
|
|
2636
|
+
subtype: "text",
|
|
2637
|
+
rect: shapeRect,
|
|
2638
|
+
state: "in-progress",
|
|
2639
|
+
stateModel: "X-ReviewWorkflow"
|
|
2640
|
+
});
|
|
2641
|
+
expect(custom.created.subtype).toBe("text");
|
|
2642
|
+
if (custom.created.subtype !== "text") return;
|
|
2643
|
+
expect(custom.created.state).toBe("in-progress");
|
|
2644
|
+
expect(custom.created.stateModel).toBe("X-ReviewWorkflow");
|
|
2645
|
+
const read = (await page.annotations.list()).annotations.find((a) => a.ref.kind === "objectNumber" && custom.created.ref.kind === "objectNumber" && a.ref.annotObjectNumber === custom.created.ref.annotObjectNumber);
|
|
2646
|
+
if (read?.subtype === "text") {
|
|
2647
|
+
expect(read.state).toBe("in-progress");
|
|
2648
|
+
expect(read.stateModel).toBe("X-ReviewWorkflow");
|
|
2649
|
+
}
|
|
2526
2650
|
} finally {
|
|
2527
2651
|
await doc.close();
|
|
2528
2652
|
}
|
|
@@ -2533,7 +2657,7 @@ async function beginWeakEditIfRequired(doc, pageObjectNumber, fix) {
|
|
|
2533
2657
|
if (doc.capabilities.weakAnnotationEditSessions !== "required" || !fix.expectsWeakAnnotation) return null;
|
|
2534
2658
|
return doc.annotations.beginWeakEdit([pageObjectNumber]);
|
|
2535
2659
|
}
|
|
2536
|
-
async function openFixture$
|
|
2660
|
+
async function openFixture$15(engine, opts) {
|
|
2537
2661
|
if (opts.openKind === "bytes") {
|
|
2538
2662
|
const bytes = await opts.fixture.bytes();
|
|
2539
2663
|
return engine.open({
|
|
@@ -2699,7 +2823,7 @@ function runFormConformance(runner, opts) {
|
|
|
2699
2823
|
await expect(doc.forms.setValue(radioRef, {
|
|
2700
2824
|
type: "toggle",
|
|
2701
2825
|
state: null
|
|
2702
|
-
})).rejects.toMatchObject({ code:
|
|
2826
|
+
})).rejects.toMatchObject({ code: require_PageInsertBlankInput.EngineErrorCode.InvalidArg });
|
|
2703
2827
|
const check = await doc.forms.setValue({
|
|
2704
2828
|
kind: "fqn",
|
|
2705
2829
|
name: "opt_check"
|
|
@@ -2727,7 +2851,7 @@ function runFormConformance(runner, opts) {
|
|
|
2727
2851
|
}, {
|
|
2728
2852
|
type: "toggle",
|
|
2729
2853
|
state: "On"
|
|
2730
|
-
})).rejects.toMatchObject({ code:
|
|
2854
|
+
})).rejects.toMatchObject({ code: require_PageInsertBlankInput.EngineErrorCode.InvalidArg });
|
|
2731
2855
|
const field = await doc.forms.get({
|
|
2732
2856
|
kind: "fqn",
|
|
2733
2857
|
name: "maxlen_text"
|
|
@@ -2831,7 +2955,7 @@ function runFormConformance(runner, opts) {
|
|
|
2831
2955
|
}, {
|
|
2832
2956
|
type: "choice",
|
|
2833
2957
|
values: ["foo", "bar"]
|
|
2834
|
-
})).rejects.toMatchObject({ code:
|
|
2958
|
+
})).rejects.toMatchObject({ code: require_PageInsertBlankInput.EngineErrorCode.InvalidArg });
|
|
2835
2959
|
} finally {
|
|
2836
2960
|
await doc.close();
|
|
2837
2961
|
}
|
|
@@ -2901,7 +3025,7 @@ function runFormConformance(runner, opts) {
|
|
|
2901
3025
|
test("rejects garbage import payloads", async () => {
|
|
2902
3026
|
const doc = await open(opts.fixtures.toggleFields);
|
|
2903
3027
|
try {
|
|
2904
|
-
await expect(doc.forms.importData(new TextEncoder().encode("not a form payload"))).rejects.toMatchObject({ code:
|
|
3028
|
+
await expect(doc.forms.importData(new TextEncoder().encode("not a form payload"))).rejects.toMatchObject({ code: require_PageInsertBlankInput.EngineErrorCode.InvalidArg });
|
|
2905
3029
|
} finally {
|
|
2906
3030
|
await doc.close();
|
|
2907
3031
|
}
|
|
@@ -3008,7 +3132,7 @@ function runFormConformance(runner, opts) {
|
|
|
3008
3132
|
g: 247,
|
|
3009
3133
|
b: 219
|
|
3010
3134
|
});
|
|
3011
|
-
await expect(page.annotations.delete(widgetRef)).rejects.toMatchObject({ code:
|
|
3135
|
+
await expect(page.annotations.delete(widgetRef)).rejects.toMatchObject({ code: require_PageInsertBlankInput.EngineErrorCode.InvalidArg });
|
|
3012
3136
|
await doc.forms.detachWidget(field.field.ref, {
|
|
3013
3137
|
annotObjectNumber: widgetRef.annotObjectNumber,
|
|
3014
3138
|
pageObjectNumber: pon
|
|
@@ -3072,7 +3196,7 @@ function runFormConformance(runner, opts) {
|
|
|
3072
3196
|
await expect(doc.forms.updateField(created.field.ref, {
|
|
3073
3197
|
family: "radio",
|
|
3074
3198
|
name: "unison_radio"
|
|
3075
|
-
})).rejects.toMatchObject({ code:
|
|
3199
|
+
})).rejects.toMatchObject({ code: require_PageInsertBlankInput.EngineErrorCode.InvalidArg });
|
|
3076
3200
|
const before = await doc.page(pon).annotations.list();
|
|
3077
3201
|
const removed = await doc.forms.deleteField(created.field.ref);
|
|
3078
3202
|
expect(removed.removedWidgets.length).toBe(2);
|
|
@@ -3081,7 +3205,7 @@ function runFormConformance(runner, opts) {
|
|
|
3081
3205
|
await expect(doc.forms.get({
|
|
3082
3206
|
kind: "fqn",
|
|
3083
3207
|
name: "renamed_radio"
|
|
3084
|
-
})).rejects.toMatchObject({ code:
|
|
3208
|
+
})).rejects.toMatchObject({ code: require_PageInsertBlankInput.EngineErrorCode.NotFound });
|
|
3085
3209
|
} finally {
|
|
3086
3210
|
await doc.close();
|
|
3087
3211
|
}
|
|
@@ -3092,7 +3216,7 @@ function runFormConformance(runner, opts) {
|
|
|
3092
3216
|
await expect(doc.forms.get({
|
|
3093
3217
|
kind: "fqn",
|
|
3094
3218
|
name: "no.such.field"
|
|
3095
|
-
})).rejects.toMatchObject({ code:
|
|
3219
|
+
})).rejects.toMatchObject({ code: require_PageInsertBlankInput.EngineErrorCode.NotFound });
|
|
3096
3220
|
} finally {
|
|
3097
3221
|
await doc.close();
|
|
3098
3222
|
}
|
|
@@ -3123,7 +3247,7 @@ function runAnnotationAppearanceConformance(runner, opts) {
|
|
|
3123
3247
|
if (engine) await engine.destroy();
|
|
3124
3248
|
});
|
|
3125
3249
|
test("renders the expected set of appearances with valid output", async () => {
|
|
3126
|
-
const doc = await openFixture$
|
|
3250
|
+
const doc = await openFixture$14(engine, opts);
|
|
3127
3251
|
try {
|
|
3128
3252
|
const { pageState, appearances } = await collect(doc, opts, useRaw);
|
|
3129
3253
|
expect(pageState.pageObjectNumber).toBe(opts.fixture.pageObjectNumber);
|
|
@@ -3150,7 +3274,7 @@ function runAnnotationAppearanceConformance(runner, opts) {
|
|
|
3150
3274
|
}
|
|
3151
3275
|
});
|
|
3152
3276
|
if (opts.fixture.expectsWeakAppearance) test("weak (index-only) annotations are emitted, not dropped", async () => {
|
|
3153
|
-
const doc = await openFixture$
|
|
3277
|
+
const doc = await openFixture$14(engine, opts);
|
|
3154
3278
|
try {
|
|
3155
3279
|
const { appearances } = await collect(doc, opts, useRaw);
|
|
3156
3280
|
const weak = appearances.find((a) => a.ref.kind === "index");
|
|
@@ -3160,7 +3284,7 @@ function runAnnotationAppearanceConformance(runner, opts) {
|
|
|
3160
3284
|
}
|
|
3161
3285
|
});
|
|
3162
3286
|
if (useRaw) test("rendered appearances are not blank (non-zero alpha)", async () => {
|
|
3163
|
-
const doc = await openFixture$
|
|
3287
|
+
const doc = await openFixture$14(engine, opts);
|
|
3164
3288
|
try {
|
|
3165
3289
|
const { appearances } = await collect(doc, opts, useRaw);
|
|
3166
3290
|
const anyVisible = appearances.some((a) => a.raster !== null && hasOpaquePixel(a.raster));
|
|
@@ -3170,7 +3294,7 @@ function runAnnotationAppearanceConformance(runner, opts) {
|
|
|
3170
3294
|
}
|
|
3171
3295
|
});
|
|
3172
3296
|
test("abort() rejects with AbortError", async () => {
|
|
3173
|
-
const doc = await openFixture$
|
|
3297
|
+
const doc = await openFixture$14(engine, opts);
|
|
3174
3298
|
try {
|
|
3175
3299
|
const page = doc.page(opts.fixture.pageObjectNumber);
|
|
3176
3300
|
const p = useRaw ? page.annotations.renderAppearances({ scale: 1 }) : page.annotations.renderAppearanceImages({
|
|
@@ -3225,7 +3349,7 @@ function hasOpaquePixel(raster) {
|
|
|
3225
3349
|
}
|
|
3226
3350
|
return false;
|
|
3227
3351
|
}
|
|
3228
|
-
async function openFixture$
|
|
3352
|
+
async function openFixture$14(engine, opts) {
|
|
3229
3353
|
if (opts.openKind === "bytes") {
|
|
3230
3354
|
const bytes = await opts.fixture.bytes();
|
|
3231
3355
|
return engine.open({
|
|
@@ -3294,7 +3418,7 @@ function runPageReorderConformance(runner, opts) {
|
|
|
3294
3418
|
if (engine) await engine.destroy();
|
|
3295
3419
|
});
|
|
3296
3420
|
test("pages.list() returns every page in display order, durable PONs only", async () => {
|
|
3297
|
-
const doc = await openFixture$
|
|
3421
|
+
const doc = await openFixture$13(engine, opts);
|
|
3298
3422
|
try {
|
|
3299
3423
|
const list = await doc.pages.list();
|
|
3300
3424
|
expect(require_schemas.PageListSnapshotSchema.safeParse(list).success).toBe(true);
|
|
@@ -3313,7 +3437,7 @@ function runPageReorderConformance(runner, opts) {
|
|
|
3313
3437
|
}
|
|
3314
3438
|
});
|
|
3315
3439
|
test("pages.move() reorders pages and returns the full post-move order", async () => {
|
|
3316
|
-
const doc = await openFixture$
|
|
3440
|
+
const doc = await openFixture$13(engine, opts);
|
|
3317
3441
|
try {
|
|
3318
3442
|
const before = await doc.pages.list();
|
|
3319
3443
|
if (before.pages.length < 3) return;
|
|
@@ -3337,7 +3461,7 @@ function runPageReorderConformance(runner, opts) {
|
|
|
3337
3461
|
}
|
|
3338
3462
|
});
|
|
3339
3463
|
test("weak index-based annotation refs survive a page reorder", async () => {
|
|
3340
|
-
const doc = await openFixture$
|
|
3464
|
+
const doc = await openFixture$13(engine, opts);
|
|
3341
3465
|
try {
|
|
3342
3466
|
const list = await doc.pages.list();
|
|
3343
3467
|
if (list.pages.length < 2) return;
|
|
@@ -3374,7 +3498,7 @@ function runPageReorderConformance(runner, opts) {
|
|
|
3374
3498
|
}
|
|
3375
3499
|
});
|
|
3376
3500
|
test("pages.move() rejects duplicate PONs with InvalidArg", async () => {
|
|
3377
|
-
const doc = await openFixture$
|
|
3501
|
+
const doc = await openFixture$13(engine, opts);
|
|
3378
3502
|
try {
|
|
3379
3503
|
const list = await doc.pages.list();
|
|
3380
3504
|
if (list.pages.length < 1) return;
|
|
@@ -3385,13 +3509,13 @@ function runPageReorderConformance(runner, opts) {
|
|
|
3385
3509
|
} catch (err) {
|
|
3386
3510
|
caught = err;
|
|
3387
3511
|
}
|
|
3388
|
-
expect(require_fold.EngineError.is(caught,
|
|
3512
|
+
expect(require_fold.EngineError.is(caught, require_PageInsertBlankInput.EngineErrorCode.InvalidArg)).toBe(true);
|
|
3389
3513
|
} finally {
|
|
3390
3514
|
await doc.close();
|
|
3391
3515
|
}
|
|
3392
3516
|
});
|
|
3393
3517
|
test("pages.move() rejects out-of-range destIndex with InvalidArg", async () => {
|
|
3394
|
-
const doc = await openFixture$
|
|
3518
|
+
const doc = await openFixture$13(engine, opts);
|
|
3395
3519
|
try {
|
|
3396
3520
|
const list = await doc.pages.list();
|
|
3397
3521
|
if (list.pages.length < 1) return;
|
|
@@ -3402,13 +3526,13 @@ function runPageReorderConformance(runner, opts) {
|
|
|
3402
3526
|
} catch (err) {
|
|
3403
3527
|
caught = err;
|
|
3404
3528
|
}
|
|
3405
|
-
expect(require_fold.EngineError.is(caught,
|
|
3529
|
+
expect(require_fold.EngineError.is(caught, require_PageInsertBlankInput.EngineErrorCode.InvalidArg)).toBe(true);
|
|
3406
3530
|
} finally {
|
|
3407
3531
|
await doc.close();
|
|
3408
3532
|
}
|
|
3409
3533
|
});
|
|
3410
3534
|
test("pages.move() rejects unknown PON with NotFound or InvalidArg", async () => {
|
|
3411
|
-
const doc = await openFixture$
|
|
3535
|
+
const doc = await openFixture$13(engine, opts);
|
|
3412
3536
|
try {
|
|
3413
3537
|
const list = await doc.pages.list();
|
|
3414
3538
|
let bogus = 0;
|
|
@@ -3420,13 +3544,13 @@ function runPageReorderConformance(runner, opts) {
|
|
|
3420
3544
|
} catch (err) {
|
|
3421
3545
|
caught = err;
|
|
3422
3546
|
}
|
|
3423
|
-
expect(require_fold.EngineError.is(caught,
|
|
3547
|
+
expect(require_fold.EngineError.is(caught, require_PageInsertBlankInput.EngineErrorCode.NotFound) || require_fold.EngineError.is(caught, require_PageInsertBlankInput.EngineErrorCode.InvalidArg)).toBe(true);
|
|
3424
3548
|
} finally {
|
|
3425
3549
|
await doc.close();
|
|
3426
3550
|
}
|
|
3427
3551
|
});
|
|
3428
3552
|
test("abort on pages.move() rejects with AbortError", async () => {
|
|
3429
|
-
const doc = await openFixture$
|
|
3553
|
+
const doc = await openFixture$13(engine, opts);
|
|
3430
3554
|
try {
|
|
3431
3555
|
const list = await doc.pages.list();
|
|
3432
3556
|
if (list.pages.length < 1) return;
|
|
@@ -3440,7 +3564,7 @@ function runPageReorderConformance(runner, opts) {
|
|
|
3440
3564
|
});
|
|
3441
3565
|
});
|
|
3442
3566
|
}
|
|
3443
|
-
async function openFixture$
|
|
3567
|
+
async function openFixture$13(engine, opts) {
|
|
3444
3568
|
if (opts.openKind === "bytes") {
|
|
3445
3569
|
const bytes = await opts.fixture.bytes();
|
|
3446
3570
|
return engine.open({
|
|
@@ -3514,7 +3638,7 @@ function runPageRotateConformance(runner, opts) {
|
|
|
3514
3638
|
if (engine) await engine.destroy();
|
|
3515
3639
|
});
|
|
3516
3640
|
test("pages.rotate() sets the absolute rotation and returns the full layout", async () => {
|
|
3517
|
-
const doc = await openFixture$
|
|
3641
|
+
const doc = await openFixture$12(engine, opts);
|
|
3518
3642
|
try {
|
|
3519
3643
|
const before = await doc.pages.list();
|
|
3520
3644
|
const target = before.pages[0];
|
|
@@ -3533,7 +3657,7 @@ function runPageRotateConformance(runner, opts) {
|
|
|
3533
3657
|
}
|
|
3534
3658
|
});
|
|
3535
3659
|
test("absolute rotation is idempotent: setting the same value twice is a no-op", async () => {
|
|
3536
|
-
const doc = await openFixture$
|
|
3660
|
+
const doc = await openFixture$12(engine, opts);
|
|
3537
3661
|
try {
|
|
3538
3662
|
const pon = (await doc.pages.list()).pages[0].pageObjectNumber;
|
|
3539
3663
|
const first = await doc.pages.rotate([pon], 180);
|
|
@@ -3544,7 +3668,7 @@ function runPageRotateConformance(runner, opts) {
|
|
|
3544
3668
|
}
|
|
3545
3669
|
});
|
|
3546
3670
|
test("one rotation applies to EVERY listed page (the multi-select gesture)", async () => {
|
|
3547
|
-
const doc = await openFixture$
|
|
3671
|
+
const doc = await openFixture$12(engine, opts);
|
|
3548
3672
|
try {
|
|
3549
3673
|
const list = await doc.pages.list();
|
|
3550
3674
|
if (list.pages.length < 2) return;
|
|
@@ -3556,7 +3680,7 @@ function runPageRotateConformance(runner, opts) {
|
|
|
3556
3680
|
}
|
|
3557
3681
|
});
|
|
3558
3682
|
test("weak index-based annotation refs survive a rotate (no revision bump)", async () => {
|
|
3559
|
-
const doc = await openFixture$
|
|
3683
|
+
const doc = await openFixture$12(engine, opts);
|
|
3560
3684
|
try {
|
|
3561
3685
|
const hostPon = (await doc.pages.list()).pages[0].pageObjectNumber;
|
|
3562
3686
|
const hostPage = doc.page(hostPon);
|
|
@@ -3586,7 +3710,7 @@ function runPageRotateConformance(runner, opts) {
|
|
|
3586
3710
|
}
|
|
3587
3711
|
});
|
|
3588
3712
|
test("pages.rotate() rejects an invalid rotation value with InvalidArg", async () => {
|
|
3589
|
-
const doc = await openFixture$
|
|
3713
|
+
const doc = await openFixture$12(engine, opts);
|
|
3590
3714
|
try {
|
|
3591
3715
|
const pon = (await doc.pages.list()).pages[0].pageObjectNumber;
|
|
3592
3716
|
let caught;
|
|
@@ -3595,13 +3719,13 @@ function runPageRotateConformance(runner, opts) {
|
|
|
3595
3719
|
} catch (err) {
|
|
3596
3720
|
caught = err;
|
|
3597
3721
|
}
|
|
3598
|
-
expect(require_fold.EngineError.is(caught,
|
|
3722
|
+
expect(require_fold.EngineError.is(caught, require_PageInsertBlankInput.EngineErrorCode.InvalidArg)).toBe(true);
|
|
3599
3723
|
} finally {
|
|
3600
3724
|
await doc.close();
|
|
3601
3725
|
}
|
|
3602
3726
|
});
|
|
3603
3727
|
test("pages.rotate() rejects duplicate PONs with InvalidArg", async () => {
|
|
3604
|
-
const doc = await openFixture$
|
|
3728
|
+
const doc = await openFixture$12(engine, opts);
|
|
3605
3729
|
try {
|
|
3606
3730
|
const pon = (await doc.pages.list()).pages[0].pageObjectNumber;
|
|
3607
3731
|
let caught;
|
|
@@ -3610,13 +3734,13 @@ function runPageRotateConformance(runner, opts) {
|
|
|
3610
3734
|
} catch (err) {
|
|
3611
3735
|
caught = err;
|
|
3612
3736
|
}
|
|
3613
|
-
expect(require_fold.EngineError.is(caught,
|
|
3737
|
+
expect(require_fold.EngineError.is(caught, require_PageInsertBlankInput.EngineErrorCode.InvalidArg)).toBe(true);
|
|
3614
3738
|
} finally {
|
|
3615
3739
|
await doc.close();
|
|
3616
3740
|
}
|
|
3617
3741
|
});
|
|
3618
3742
|
test("pages.rotate() rejects unknown PON with NotFound or InvalidArg", async () => {
|
|
3619
|
-
const doc = await openFixture$
|
|
3743
|
+
const doc = await openFixture$12(engine, opts);
|
|
3620
3744
|
try {
|
|
3621
3745
|
const list = await doc.pages.list();
|
|
3622
3746
|
let bogus = 0;
|
|
@@ -3628,13 +3752,13 @@ function runPageRotateConformance(runner, opts) {
|
|
|
3628
3752
|
} catch (err) {
|
|
3629
3753
|
caught = err;
|
|
3630
3754
|
}
|
|
3631
|
-
expect(require_fold.EngineError.is(caught,
|
|
3755
|
+
expect(require_fold.EngineError.is(caught, require_PageInsertBlankInput.EngineErrorCode.NotFound) || require_fold.EngineError.is(caught, require_PageInsertBlankInput.EngineErrorCode.InvalidArg)).toBe(true);
|
|
3632
3756
|
} finally {
|
|
3633
3757
|
await doc.close();
|
|
3634
3758
|
}
|
|
3635
3759
|
});
|
|
3636
3760
|
test("abort on pages.rotate() rejects with AbortError", async () => {
|
|
3637
|
-
const doc = await openFixture$
|
|
3761
|
+
const doc = await openFixture$12(engine, opts);
|
|
3638
3762
|
try {
|
|
3639
3763
|
const pon = (await doc.pages.list()).pages[0].pageObjectNumber;
|
|
3640
3764
|
const p = doc.pages.rotate([pon], 90);
|
|
@@ -3646,7 +3770,7 @@ function runPageRotateConformance(runner, opts) {
|
|
|
3646
3770
|
});
|
|
3647
3771
|
});
|
|
3648
3772
|
}
|
|
3649
|
-
async function openFixture$
|
|
3773
|
+
async function openFixture$12(engine, opts) {
|
|
3650
3774
|
if (opts.openKind === "bytes") {
|
|
3651
3775
|
const bytes = await opts.fixture.bytes();
|
|
3652
3776
|
return engine.open({
|
|
@@ -3709,7 +3833,7 @@ function runPageDeleteConformance(runner, opts) {
|
|
|
3709
3833
|
if (engine) await engine.destroy();
|
|
3710
3834
|
});
|
|
3711
3835
|
test("pages.delete() removes the page and returns the surviving layout", async () => {
|
|
3712
|
-
const doc = await openFixture$
|
|
3836
|
+
const doc = await openFixture$11(engine, opts);
|
|
3713
3837
|
try {
|
|
3714
3838
|
const before = await doc.pages.list();
|
|
3715
3839
|
if (before.pages.length < 2) return;
|
|
@@ -3730,7 +3854,7 @@ function runPageDeleteConformance(runner, opts) {
|
|
|
3730
3854
|
}
|
|
3731
3855
|
});
|
|
3732
3856
|
test("addressing a deleted page afterwards is a clean NotFound", async () => {
|
|
3733
|
-
const doc = await openFixture$
|
|
3857
|
+
const doc = await openFixture$11(engine, opts);
|
|
3734
3858
|
try {
|
|
3735
3859
|
const before = await doc.pages.list();
|
|
3736
3860
|
if (before.pages.length < 2) return;
|
|
@@ -3742,13 +3866,13 @@ function runPageDeleteConformance(runner, opts) {
|
|
|
3742
3866
|
} catch (err) {
|
|
3743
3867
|
caught = err;
|
|
3744
3868
|
}
|
|
3745
|
-
expect(require_fold.EngineError.is(caught,
|
|
3869
|
+
expect(require_fold.EngineError.is(caught, require_PageInsertBlankInput.EngineErrorCode.NotFound)).toBe(true);
|
|
3746
3870
|
} finally {
|
|
3747
3871
|
await doc.close();
|
|
3748
3872
|
}
|
|
3749
3873
|
});
|
|
3750
3874
|
test("surviving pages keep their weak index-based annotation refs", async () => {
|
|
3751
|
-
const doc = await openFixture$
|
|
3875
|
+
const doc = await openFixture$11(engine, opts);
|
|
3752
3876
|
try {
|
|
3753
3877
|
const list = await doc.pages.list();
|
|
3754
3878
|
if (list.pages.length < 2) return;
|
|
@@ -3781,7 +3905,7 @@ function runPageDeleteConformance(runner, opts) {
|
|
|
3781
3905
|
}
|
|
3782
3906
|
});
|
|
3783
3907
|
test("deleting EVERY page is rejected with InvalidArg", async () => {
|
|
3784
|
-
const doc = await openFixture$
|
|
3908
|
+
const doc = await openFixture$11(engine, opts);
|
|
3785
3909
|
try {
|
|
3786
3910
|
const list = await doc.pages.list();
|
|
3787
3911
|
let caught;
|
|
@@ -3790,13 +3914,13 @@ function runPageDeleteConformance(runner, opts) {
|
|
|
3790
3914
|
} catch (err) {
|
|
3791
3915
|
caught = err;
|
|
3792
3916
|
}
|
|
3793
|
-
expect(require_fold.EngineError.is(caught,
|
|
3917
|
+
expect(require_fold.EngineError.is(caught, require_PageInsertBlankInput.EngineErrorCode.InvalidArg)).toBe(true);
|
|
3794
3918
|
} finally {
|
|
3795
3919
|
await doc.close();
|
|
3796
3920
|
}
|
|
3797
3921
|
});
|
|
3798
3922
|
test("pages.delete() rejects duplicate PONs with InvalidArg", async () => {
|
|
3799
|
-
const doc = await openFixture$
|
|
3923
|
+
const doc = await openFixture$11(engine, opts);
|
|
3800
3924
|
try {
|
|
3801
3925
|
const pon = (await doc.pages.list()).pages[0].pageObjectNumber;
|
|
3802
3926
|
let caught;
|
|
@@ -3805,13 +3929,13 @@ function runPageDeleteConformance(runner, opts) {
|
|
|
3805
3929
|
} catch (err) {
|
|
3806
3930
|
caught = err;
|
|
3807
3931
|
}
|
|
3808
|
-
expect(require_fold.EngineError.is(caught,
|
|
3932
|
+
expect(require_fold.EngineError.is(caught, require_PageInsertBlankInput.EngineErrorCode.InvalidArg)).toBe(true);
|
|
3809
3933
|
} finally {
|
|
3810
3934
|
await doc.close();
|
|
3811
3935
|
}
|
|
3812
3936
|
});
|
|
3813
3937
|
test("pages.delete() rejects unknown PON with NotFound or InvalidArg", async () => {
|
|
3814
|
-
const doc = await openFixture$
|
|
3938
|
+
const doc = await openFixture$11(engine, opts);
|
|
3815
3939
|
try {
|
|
3816
3940
|
const list = await doc.pages.list();
|
|
3817
3941
|
let bogus = 0;
|
|
@@ -3823,13 +3947,13 @@ function runPageDeleteConformance(runner, opts) {
|
|
|
3823
3947
|
} catch (err) {
|
|
3824
3948
|
caught = err;
|
|
3825
3949
|
}
|
|
3826
|
-
expect(require_fold.EngineError.is(caught,
|
|
3950
|
+
expect(require_fold.EngineError.is(caught, require_PageInsertBlankInput.EngineErrorCode.NotFound) || require_fold.EngineError.is(caught, require_PageInsertBlankInput.EngineErrorCode.InvalidArg)).toBe(true);
|
|
3827
3951
|
} finally {
|
|
3828
3952
|
await doc.close();
|
|
3829
3953
|
}
|
|
3830
3954
|
});
|
|
3831
3955
|
test("abort on pages.delete() rejects with AbortError", async () => {
|
|
3832
|
-
const doc = await openFixture$
|
|
3956
|
+
const doc = await openFixture$11(engine, opts);
|
|
3833
3957
|
try {
|
|
3834
3958
|
const list = await doc.pages.list();
|
|
3835
3959
|
if (list.pages.length < 2) return;
|
|
@@ -3843,7 +3967,7 @@ function runPageDeleteConformance(runner, opts) {
|
|
|
3843
3967
|
});
|
|
3844
3968
|
});
|
|
3845
3969
|
}
|
|
3846
|
-
async function openFixture$
|
|
3970
|
+
async function openFixture$11(engine, opts) {
|
|
3847
3971
|
if (opts.openKind === "bytes") {
|
|
3848
3972
|
const bytes = await opts.fixture.bytes();
|
|
3849
3973
|
return engine.open({
|
|
@@ -3871,7 +3995,7 @@ function runPageFlattenConformance(runner, opts) {
|
|
|
3871
3995
|
if (engine) await engine.destroy();
|
|
3872
3996
|
});
|
|
3873
3997
|
test("flattens eligible appearances once without changing layout", async () => {
|
|
3874
|
-
const doc = await openFixture$
|
|
3998
|
+
const doc = await openFixture$10(engine, opts);
|
|
3875
3999
|
try {
|
|
3876
4000
|
if (!doc.pages.flatten) return;
|
|
3877
4001
|
const layoutBefore = await doc.pages.list();
|
|
@@ -3898,14 +4022,14 @@ function runPageFlattenConformance(runner, opts) {
|
|
|
3898
4022
|
expect(noOp.meta).toBeNull();
|
|
3899
4023
|
expect(events).toHaveLength(1);
|
|
3900
4024
|
unsubscribe();
|
|
3901
|
-
await expect(doc.pages.flatten([pageObjectNumber, pageObjectNumber])).rejects.toMatchObject({ code:
|
|
4025
|
+
await expect(doc.pages.flatten([pageObjectNumber, pageObjectNumber])).rejects.toMatchObject({ code: require_PageInsertBlankInput.EngineErrorCode.InvalidArg });
|
|
3902
4026
|
} finally {
|
|
3903
4027
|
await doc.close();
|
|
3904
4028
|
}
|
|
3905
4029
|
});
|
|
3906
4030
|
});
|
|
3907
4031
|
}
|
|
3908
|
-
async function openFixture$
|
|
4032
|
+
async function openFixture$10(engine, opts) {
|
|
3909
4033
|
if (opts.openKind === "bytes") return engine.open({
|
|
3910
4034
|
kind: "bytes",
|
|
3911
4035
|
id: opts.fixture.id,
|
|
@@ -3960,7 +4084,7 @@ function runRedactionApplyConformance(runner, opts) {
|
|
|
3960
4084
|
if (engine) await engine.destroy();
|
|
3961
4085
|
});
|
|
3962
4086
|
test("annotations scope applies the marked redaction and counts collateral", async () => {
|
|
3963
|
-
const doc = await openFixture$
|
|
4087
|
+
const doc = await openFixture$9(engine, opts);
|
|
3964
4088
|
try {
|
|
3965
4089
|
if (!doc.redaction) return;
|
|
3966
4090
|
const layoutBefore = await doc.pages.list();
|
|
@@ -4014,7 +4138,7 @@ function runRedactionApplyConformance(runner, opts) {
|
|
|
4014
4138
|
}
|
|
4015
4139
|
});
|
|
4016
4140
|
test("pages scope applies everything once and validates its input", async () => {
|
|
4017
|
-
const doc = await openFixture$
|
|
4141
|
+
const doc = await openFixture$9(engine, opts);
|
|
4018
4142
|
try {
|
|
4019
4143
|
if (!doc.redaction) return;
|
|
4020
4144
|
const pageObjectNumber = (await doc.pages.list()).pages[0].pageObjectNumber;
|
|
@@ -4050,7 +4174,7 @@ function runRedactionApplyConformance(runner, opts) {
|
|
|
4050
4174
|
await expect(doc.redaction.apply({
|
|
4051
4175
|
kind: "pages",
|
|
4052
4176
|
pageObjectNumbers: [pageObjectNumber, pageObjectNumber]
|
|
4053
|
-
})).rejects.toMatchObject({ code:
|
|
4177
|
+
})).rejects.toMatchObject({ code: require_PageInsertBlankInput.EngineErrorCode.InvalidArg });
|
|
4054
4178
|
const notRedact = await page.annotations.create({
|
|
4055
4179
|
subtype: "highlight",
|
|
4056
4180
|
quadPoints: COLLATERAL_QUAD
|
|
@@ -4058,14 +4182,14 @@ function runRedactionApplyConformance(runner, opts) {
|
|
|
4058
4182
|
await expect(doc.redaction.apply({
|
|
4059
4183
|
kind: "annotations",
|
|
4060
4184
|
refs: [notRedact.created.ref]
|
|
4061
|
-
})).rejects.toMatchObject({ code:
|
|
4185
|
+
})).rejects.toMatchObject({ code: require_PageInsertBlankInput.EngineErrorCode.InvalidArg });
|
|
4062
4186
|
} finally {
|
|
4063
4187
|
await doc.close();
|
|
4064
4188
|
}
|
|
4065
4189
|
});
|
|
4066
4190
|
});
|
|
4067
4191
|
}
|
|
4068
|
-
async function openFixture$
|
|
4192
|
+
async function openFixture$9(engine, opts) {
|
|
4069
4193
|
if (opts.openKind === "bytes") return engine.open({
|
|
4070
4194
|
kind: "bytes",
|
|
4071
4195
|
id: opts.fixture.id,
|
|
@@ -4105,19 +4229,14 @@ function runPageExtractConformance(runner, opts) {
|
|
|
4105
4229
|
const { describe, test, beforeAll, afterAll, expect } = runner;
|
|
4106
4230
|
describe(`page extract conformance: ${opts.label}`, () => {
|
|
4107
4231
|
let engine;
|
|
4108
|
-
let supported = false;
|
|
4109
4232
|
beforeAll(async () => {
|
|
4110
4233
|
engine = await opts.makeEngine();
|
|
4111
|
-
const probe = await openFixture$5(engine, opts);
|
|
4112
|
-
supported = probe.pages.extract !== void 0;
|
|
4113
|
-
await probe.close();
|
|
4114
4234
|
});
|
|
4115
4235
|
afterAll(async () => {
|
|
4116
4236
|
if (engine) await engine.destroy();
|
|
4117
4237
|
});
|
|
4118
4238
|
test("pages.extract() returns standalone PDF bytes and leaves the source untouched", async () => {
|
|
4119
|
-
|
|
4120
|
-
const doc = await openFixture$5(engine, opts);
|
|
4239
|
+
const doc = await openFixture$8(engine, opts);
|
|
4121
4240
|
try {
|
|
4122
4241
|
const before = await doc.pages.list();
|
|
4123
4242
|
const target = before.pages[before.pages.length - 1];
|
|
@@ -4132,8 +4251,8 @@ function runPageExtractConformance(runner, opts) {
|
|
|
4132
4251
|
}
|
|
4133
4252
|
});
|
|
4134
4253
|
test("extracted bytes re-open as a document with the requested pages, in caller order", async () => {
|
|
4135
|
-
if (
|
|
4136
|
-
const doc = await openFixture$
|
|
4254
|
+
if (opts.openKind !== "bytes") return;
|
|
4255
|
+
const doc = await openFixture$8(engine, opts);
|
|
4137
4256
|
let extracted = null;
|
|
4138
4257
|
try {
|
|
4139
4258
|
const list = await doc.pages.list();
|
|
@@ -4156,8 +4275,7 @@ function runPageExtractConformance(runner, opts) {
|
|
|
4156
4275
|
}
|
|
4157
4276
|
});
|
|
4158
4277
|
test("pages.extract() rejects empty input with InvalidArg", async () => {
|
|
4159
|
-
|
|
4160
|
-
const doc = await openFixture$5(engine, opts);
|
|
4278
|
+
const doc = await openFixture$8(engine, opts);
|
|
4161
4279
|
try {
|
|
4162
4280
|
let caught;
|
|
4163
4281
|
try {
|
|
@@ -4165,14 +4283,13 @@ function runPageExtractConformance(runner, opts) {
|
|
|
4165
4283
|
} catch (err) {
|
|
4166
4284
|
caught = err;
|
|
4167
4285
|
}
|
|
4168
|
-
expect(require_fold.EngineError.is(caught,
|
|
4286
|
+
expect(require_fold.EngineError.is(caught, require_PageInsertBlankInput.EngineErrorCode.InvalidArg)).toBe(true);
|
|
4169
4287
|
} finally {
|
|
4170
4288
|
await doc.close();
|
|
4171
4289
|
}
|
|
4172
4290
|
});
|
|
4173
4291
|
test("pages.extract() rejects duplicate PONs with InvalidArg", async () => {
|
|
4174
|
-
|
|
4175
|
-
const doc = await openFixture$5(engine, opts);
|
|
4292
|
+
const doc = await openFixture$8(engine, opts);
|
|
4176
4293
|
try {
|
|
4177
4294
|
const pon = (await doc.pages.list()).pages[0].pageObjectNumber;
|
|
4178
4295
|
let caught;
|
|
@@ -4181,14 +4298,13 @@ function runPageExtractConformance(runner, opts) {
|
|
|
4181
4298
|
} catch (err) {
|
|
4182
4299
|
caught = err;
|
|
4183
4300
|
}
|
|
4184
|
-
expect(require_fold.EngineError.is(caught,
|
|
4301
|
+
expect(require_fold.EngineError.is(caught, require_PageInsertBlankInput.EngineErrorCode.InvalidArg)).toBe(true);
|
|
4185
4302
|
} finally {
|
|
4186
4303
|
await doc.close();
|
|
4187
4304
|
}
|
|
4188
4305
|
});
|
|
4189
4306
|
test("pages.extract() rejects unknown PON with NotFound or InvalidArg", async () => {
|
|
4190
|
-
|
|
4191
|
-
const doc = await openFixture$5(engine, opts);
|
|
4307
|
+
const doc = await openFixture$8(engine, opts);
|
|
4192
4308
|
try {
|
|
4193
4309
|
const list = await doc.pages.list();
|
|
4194
4310
|
let bogus = 0;
|
|
@@ -4200,14 +4316,13 @@ function runPageExtractConformance(runner, opts) {
|
|
|
4200
4316
|
} catch (err) {
|
|
4201
4317
|
caught = err;
|
|
4202
4318
|
}
|
|
4203
|
-
expect(require_fold.EngineError.is(caught,
|
|
4319
|
+
expect(require_fold.EngineError.is(caught, require_PageInsertBlankInput.EngineErrorCode.NotFound) || require_fold.EngineError.is(caught, require_PageInsertBlankInput.EngineErrorCode.InvalidArg)).toBe(true);
|
|
4204
4320
|
} finally {
|
|
4205
4321
|
await doc.close();
|
|
4206
4322
|
}
|
|
4207
4323
|
});
|
|
4208
4324
|
test("abort on pages.extract() rejects with AbortError", async () => {
|
|
4209
|
-
|
|
4210
|
-
const doc = await openFixture$5(engine, opts);
|
|
4325
|
+
const doc = await openFixture$8(engine, opts);
|
|
4211
4326
|
try {
|
|
4212
4327
|
const list = await doc.pages.list();
|
|
4213
4328
|
const p = doc.pages.extract([list.pages[0].pageObjectNumber]);
|
|
@@ -4219,7 +4334,7 @@ function runPageExtractConformance(runner, opts) {
|
|
|
4219
4334
|
});
|
|
4220
4335
|
});
|
|
4221
4336
|
}
|
|
4222
|
-
async function openFixture$
|
|
4337
|
+
async function openFixture$8(engine, opts) {
|
|
4223
4338
|
if (opts.openKind === "bytes") {
|
|
4224
4339
|
const bytes = await opts.fixture.bytes();
|
|
4225
4340
|
return engine.open({
|
|
@@ -4481,9 +4596,9 @@ function runAttachmentConformance(runner, opts) {
|
|
|
4481
4596
|
//#endregion
|
|
4482
4597
|
//#region src/conformance/runPageInsertConformance.ts
|
|
4483
4598
|
/**
|
|
4484
|
-
* Page insert conformance. `pages.insert
|
|
4485
|
-
*
|
|
4486
|
-
*
|
|
4599
|
+
* Page insert conformance. `pages.insert` is a REQUIRED member — this suite
|
|
4600
|
+
* runs unconditionally on every engine, so an implementation that loses the
|
|
4601
|
+
* verb fails loudly instead of being skipped past.
|
|
4487
4602
|
*
|
|
4488
4603
|
* Invariants:
|
|
4489
4604
|
* 1. Every page of the source bytes is COPIED in at `destIndex` (omitted →
|
|
@@ -4499,19 +4614,14 @@ function runPageInsertConformance(runner, opts) {
|
|
|
4499
4614
|
const { describe, test, beforeAll, afterAll, expect } = runner;
|
|
4500
4615
|
describe(`page insert conformance: ${opts.label}`, () => {
|
|
4501
4616
|
let engine;
|
|
4502
|
-
let supported = false;
|
|
4503
4617
|
beforeAll(async () => {
|
|
4504
4618
|
engine = await opts.makeEngine();
|
|
4505
|
-
const probe = await openFixture$4(engine, opts);
|
|
4506
|
-
supported = probe.pages.insert !== void 0 && probe.pages.extract !== void 0;
|
|
4507
|
-
await probe.close();
|
|
4508
4619
|
});
|
|
4509
4620
|
afterAll(async () => {
|
|
4510
4621
|
if (engine) await engine.destroy();
|
|
4511
4622
|
});
|
|
4512
4623
|
test("appends every source page with fresh PONs; existing pages keep identity", async () => {
|
|
4513
|
-
|
|
4514
|
-
const doc = await openFixture$4(engine, opts);
|
|
4624
|
+
const doc = await openFixture$7(engine, opts);
|
|
4515
4625
|
try {
|
|
4516
4626
|
const before = await doc.pages.list();
|
|
4517
4627
|
const beforePons = before.pages.map((p) => p.pageObjectNumber);
|
|
@@ -4529,8 +4639,7 @@ function runPageInsertConformance(runner, opts) {
|
|
|
4529
4639
|
}
|
|
4530
4640
|
});
|
|
4531
4641
|
test("destIndex places the block mid-document, in source order", async () => {
|
|
4532
|
-
|
|
4533
|
-
const doc = await openFixture$4(engine, opts);
|
|
4642
|
+
const doc = await openFixture$7(engine, opts);
|
|
4534
4643
|
try {
|
|
4535
4644
|
const before = await doc.pages.list();
|
|
4536
4645
|
if (before.pages.length < 2) return;
|
|
@@ -4547,8 +4656,8 @@ function runPageInsertConformance(runner, opts) {
|
|
|
4547
4656
|
}
|
|
4548
4657
|
});
|
|
4549
4658
|
test("the inserted pages persist through save → re-open", async () => {
|
|
4550
|
-
if (
|
|
4551
|
-
const doc = await openFixture$
|
|
4659
|
+
if (opts.openKind !== "bytes") return;
|
|
4660
|
+
const doc = await openFixture$7(engine, opts);
|
|
4552
4661
|
let reopened = null;
|
|
4553
4662
|
try {
|
|
4554
4663
|
const before = await doc.pages.list();
|
|
@@ -4568,8 +4677,7 @@ function runPageInsertConformance(runner, opts) {
|
|
|
4568
4677
|
}
|
|
4569
4678
|
});
|
|
4570
4679
|
test("empty bytes reject with InvalidArg; garbage rejects with MalformedPdf", async () => {
|
|
4571
|
-
|
|
4572
|
-
const doc = await openFixture$4(engine, opts);
|
|
4680
|
+
const doc = await openFixture$7(engine, opts);
|
|
4573
4681
|
try {
|
|
4574
4682
|
let caught;
|
|
4575
4683
|
try {
|
|
@@ -4577,14 +4685,14 @@ function runPageInsertConformance(runner, opts) {
|
|
|
4577
4685
|
} catch (err) {
|
|
4578
4686
|
caught = err;
|
|
4579
4687
|
}
|
|
4580
|
-
expect(require_fold.EngineError.is(caught,
|
|
4688
|
+
expect(require_fold.EngineError.is(caught, require_PageInsertBlankInput.EngineErrorCode.InvalidArg)).toBe(true);
|
|
4581
4689
|
caught = void 0;
|
|
4582
4690
|
try {
|
|
4583
4691
|
await doc.pages.insert(new TextEncoder().encode("not a pdf at all"));
|
|
4584
4692
|
} catch (err) {
|
|
4585
4693
|
caught = err;
|
|
4586
4694
|
}
|
|
4587
|
-
expect(require_fold.EngineError.is(caught,
|
|
4695
|
+
expect(require_fold.EngineError.is(caught, require_PageInsertBlankInput.EngineErrorCode.MalformedPdf)).toBe(true);
|
|
4588
4696
|
const list = await doc.pages.list();
|
|
4589
4697
|
expect(list.pageCount > 0).toBe(true);
|
|
4590
4698
|
} finally {
|
|
@@ -4592,8 +4700,7 @@ function runPageInsertConformance(runner, opts) {
|
|
|
4592
4700
|
}
|
|
4593
4701
|
});
|
|
4594
4702
|
test("out-of-range destIndex rejects with InvalidArg", async () => {
|
|
4595
|
-
|
|
4596
|
-
const doc = await openFixture$4(engine, opts);
|
|
4703
|
+
const doc = await openFixture$7(engine, opts);
|
|
4597
4704
|
try {
|
|
4598
4705
|
const before = await doc.pages.list();
|
|
4599
4706
|
const single = await doc.pages.extract([before.pages[0].pageObjectNumber]);
|
|
@@ -4603,14 +4710,167 @@ function runPageInsertConformance(runner, opts) {
|
|
|
4603
4710
|
} catch (err) {
|
|
4604
4711
|
caught = err;
|
|
4605
4712
|
}
|
|
4606
|
-
expect(require_fold.EngineError.is(caught,
|
|
4713
|
+
expect(require_fold.EngineError.is(caught, require_PageInsertBlankInput.EngineErrorCode.InvalidArg)).toBe(true);
|
|
4607
4714
|
} finally {
|
|
4608
4715
|
await doc.close();
|
|
4609
4716
|
}
|
|
4610
4717
|
});
|
|
4611
4718
|
});
|
|
4612
4719
|
}
|
|
4613
|
-
async function openFixture$
|
|
4720
|
+
async function openFixture$7(engine, opts) {
|
|
4721
|
+
if (opts.openKind === "bytes") {
|
|
4722
|
+
const bytes = await opts.fixture.bytes();
|
|
4723
|
+
return engine.open({
|
|
4724
|
+
kind: "bytes",
|
|
4725
|
+
id: opts.fixture.id,
|
|
4726
|
+
bytes
|
|
4727
|
+
});
|
|
4728
|
+
}
|
|
4729
|
+
return engine.open({
|
|
4730
|
+
kind: "id",
|
|
4731
|
+
id: opts.fixture.cloudId ?? opts.fixture.id
|
|
4732
|
+
});
|
|
4733
|
+
}
|
|
4734
|
+
//#endregion
|
|
4735
|
+
//#region src/conformance/runPageInsertBlankConformance.ts
|
|
4736
|
+
/** An on-purpose non-default size so the assertions can't pass by accident. */
|
|
4737
|
+
const SIZE = {
|
|
4738
|
+
width: 396,
|
|
4739
|
+
height: 612
|
|
4740
|
+
};
|
|
4741
|
+
/**
|
|
4742
|
+
* Blank-page insert conformance. `pages.insertBlank` is a REQUIRED member —
|
|
4743
|
+
* the suite runs unconditionally on every engine (no fixture bytes are
|
|
4744
|
+
* needed at all, which is the point of the verb), so an implementation that
|
|
4745
|
+
* loses the verb fails loudly instead of being skipped past.
|
|
4746
|
+
*
|
|
4747
|
+
* Invariants:
|
|
4748
|
+
* 1. `count` blank pages of exactly `size` appear at `destIndex` (omitted
|
|
4749
|
+
* → append), rotation 0; the result lists their fresh PONs in insertion
|
|
4750
|
+
* order and they agree with the returned layout.
|
|
4751
|
+
* 2. Pre-existing pages keep their identity: same PONs before and after,
|
|
4752
|
+
* in the expected positions (an insert never invalidates neighbours).
|
|
4753
|
+
* 3. The mutation persists through save → re-open (bytes engines only).
|
|
4754
|
+
* 4. Non-positive size / count outside [1, PAGE_INSERT_BLANK_MAX_COUNT] /
|
|
4755
|
+
* out-of-range destIndex reject with InvalidArg, leaving the document
|
|
4756
|
+
* untouched.
|
|
4757
|
+
*/
|
|
4758
|
+
function runPageInsertBlankConformance(runner, opts) {
|
|
4759
|
+
const { describe, test, beforeAll, afterAll, expect } = runner;
|
|
4760
|
+
describe(`page insert-blank conformance: ${opts.label}`, () => {
|
|
4761
|
+
let engine;
|
|
4762
|
+
beforeAll(async () => {
|
|
4763
|
+
engine = await opts.makeEngine();
|
|
4764
|
+
});
|
|
4765
|
+
afterAll(async () => {
|
|
4766
|
+
if (engine) await engine.destroy();
|
|
4767
|
+
});
|
|
4768
|
+
test("appends one blank page of the requested size with a fresh PON", async () => {
|
|
4769
|
+
const doc = await openFixture$6(engine, opts);
|
|
4770
|
+
try {
|
|
4771
|
+
const before = await doc.pages.list();
|
|
4772
|
+
const beforePons = before.pages.map((p) => p.pageObjectNumber);
|
|
4773
|
+
const result = await doc.pages.insertBlank({ size: SIZE });
|
|
4774
|
+
expect(result.insertedPageObjectNumbers.length).toBe(1);
|
|
4775
|
+
expect(result.layout.pageCount).toBe(before.pageCount + 1);
|
|
4776
|
+
expect(result.layout.pages.slice(0, before.pageCount).map((p) => p.pageObjectNumber)).toEqual(beforePons);
|
|
4777
|
+
const newPon = result.insertedPageObjectNumbers[0];
|
|
4778
|
+
expect(beforePons.includes(newPon)).toBe(false);
|
|
4779
|
+
const appended = result.layout.pages[before.pageCount];
|
|
4780
|
+
expect(appended.pageObjectNumber).toBe(newPon);
|
|
4781
|
+
expect(appended.size).toEqual(SIZE);
|
|
4782
|
+
expect(appended.rotation).toBe(0);
|
|
4783
|
+
} finally {
|
|
4784
|
+
await doc.close();
|
|
4785
|
+
}
|
|
4786
|
+
});
|
|
4787
|
+
test("destIndex + count places the blank block mid-document", async () => {
|
|
4788
|
+
const doc = await openFixture$6(engine, opts);
|
|
4789
|
+
try {
|
|
4790
|
+
const before = await doc.pages.list();
|
|
4791
|
+
if (before.pages.length < 2) return;
|
|
4792
|
+
const beforePons = before.pages.map((p) => p.pageObjectNumber);
|
|
4793
|
+
const result = await doc.pages.insertBlank({
|
|
4794
|
+
size: SIZE,
|
|
4795
|
+
count: 2
|
|
4796
|
+
}, 1);
|
|
4797
|
+
expect(result.insertedPageObjectNumbers.length).toBe(2);
|
|
4798
|
+
expect(result.insertedPageObjectNumbers[0] === result.insertedPageObjectNumbers[1]).toBe(false);
|
|
4799
|
+
const pons = result.layout.pages.map((p) => p.pageObjectNumber);
|
|
4800
|
+
expect(pons[0]).toBe(beforePons[0]);
|
|
4801
|
+
expect(pons.slice(1, 3)).toEqual(result.insertedPageObjectNumbers);
|
|
4802
|
+
expect(pons.slice(3)).toEqual(beforePons.slice(1));
|
|
4803
|
+
expect(result.layout.pages[1].size).toEqual(SIZE);
|
|
4804
|
+
expect(result.layout.pages[2].size).toEqual(SIZE);
|
|
4805
|
+
} finally {
|
|
4806
|
+
await doc.close();
|
|
4807
|
+
}
|
|
4808
|
+
});
|
|
4809
|
+
test("the blank pages persist through save → re-open", async () => {
|
|
4810
|
+
if (opts.openKind !== "bytes") return;
|
|
4811
|
+
const doc = await openFixture$6(engine, opts);
|
|
4812
|
+
let reopened = null;
|
|
4813
|
+
try {
|
|
4814
|
+
const before = await doc.pages.list();
|
|
4815
|
+
await doc.pages.insertBlank({ size: SIZE });
|
|
4816
|
+
const bytes = await doc.download();
|
|
4817
|
+
reopened = await engine.open({
|
|
4818
|
+
kind: "bytes",
|
|
4819
|
+
id: `${opts.fixture.id}-insert-blank-reopen`,
|
|
4820
|
+
bytes
|
|
4821
|
+
});
|
|
4822
|
+
const after = await reopened.pages.list();
|
|
4823
|
+
expect(after.pageCount).toBe(before.pageCount + 1);
|
|
4824
|
+
const tail = after.pages[after.pageCount - 1];
|
|
4825
|
+
expect(Math.round(tail.size.width)).toBe(SIZE.width);
|
|
4826
|
+
expect(Math.round(tail.size.height)).toBe(SIZE.height);
|
|
4827
|
+
} finally {
|
|
4828
|
+
if (reopened) await reopened.close();
|
|
4829
|
+
await doc.close();
|
|
4830
|
+
}
|
|
4831
|
+
});
|
|
4832
|
+
test("non-positive size, bad count, and out-of-range destIndex reject with InvalidArg", async () => {
|
|
4833
|
+
const doc = await openFixture$6(engine, opts);
|
|
4834
|
+
try {
|
|
4835
|
+
const before = await doc.pages.list();
|
|
4836
|
+
const rejects = [
|
|
4837
|
+
() => doc.pages.insertBlank({ size: {
|
|
4838
|
+
width: 0,
|
|
4839
|
+
height: 612
|
|
4840
|
+
} }),
|
|
4841
|
+
() => doc.pages.insertBlank({ size: {
|
|
4842
|
+
width: 396,
|
|
4843
|
+
height: -10
|
|
4844
|
+
} }),
|
|
4845
|
+
() => doc.pages.insertBlank({
|
|
4846
|
+
size: SIZE,
|
|
4847
|
+
count: 0
|
|
4848
|
+
}),
|
|
4849
|
+
() => doc.pages.insertBlank({
|
|
4850
|
+
size: SIZE,
|
|
4851
|
+
count: 101
|
|
4852
|
+
}),
|
|
4853
|
+
() => doc.pages.insertBlank({ size: SIZE }, before.pageCount + 1)
|
|
4854
|
+
];
|
|
4855
|
+
for (const attempt of rejects) {
|
|
4856
|
+
let caught;
|
|
4857
|
+
try {
|
|
4858
|
+
await attempt();
|
|
4859
|
+
} catch (err) {
|
|
4860
|
+
caught = err;
|
|
4861
|
+
}
|
|
4862
|
+
expect(require_fold.EngineError.is(caught, require_PageInsertBlankInput.EngineErrorCode.InvalidArg)).toBe(true);
|
|
4863
|
+
}
|
|
4864
|
+
const list = await doc.pages.list();
|
|
4865
|
+
expect(list.pageCount).toBe(before.pageCount);
|
|
4866
|
+
expect(list.pages.map((p) => p.pageObjectNumber)).toEqual(before.pages.map((p) => p.pageObjectNumber));
|
|
4867
|
+
} finally {
|
|
4868
|
+
await doc.close();
|
|
4869
|
+
}
|
|
4870
|
+
});
|
|
4871
|
+
});
|
|
4872
|
+
}
|
|
4873
|
+
async function openFixture$6(engine, opts) {
|
|
4614
4874
|
if (opts.openKind === "bytes") {
|
|
4615
4875
|
const bytes = await opts.fixture.bytes();
|
|
4616
4876
|
return engine.open({
|
|
@@ -4651,7 +4911,7 @@ function runPieceInfoConformance(runner, opts) {
|
|
|
4651
4911
|
let supported = false;
|
|
4652
4912
|
beforeAll(async () => {
|
|
4653
4913
|
engine = await opts.makeEngine();
|
|
4654
|
-
const probe = await openFixture$
|
|
4914
|
+
const probe = await openFixture$5(engine, opts);
|
|
4655
4915
|
supported = probe.pieceInfo !== void 0;
|
|
4656
4916
|
await probe.close();
|
|
4657
4917
|
});
|
|
@@ -4660,7 +4920,7 @@ function runPieceInfoConformance(runner, opts) {
|
|
|
4660
4920
|
});
|
|
4661
4921
|
test("doc-level: the full value vocabulary round-trips with tags intact", async () => {
|
|
4662
4922
|
if (!supported) return;
|
|
4663
|
-
const doc = await openFixture$
|
|
4923
|
+
const doc = await openFixture$5(engine, opts);
|
|
4664
4924
|
try {
|
|
4665
4925
|
await doc.pieceInfo.update(APP, {
|
|
4666
4926
|
name: "Standard Stamps",
|
|
@@ -4700,7 +4960,7 @@ function runPieceInfoConformance(runner, opts) {
|
|
|
4700
4960
|
});
|
|
4701
4961
|
test("page-level: the stamp schema round-trips on a page", async () => {
|
|
4702
4962
|
if (!supported) return;
|
|
4703
|
-
const doc = await openFixture$
|
|
4963
|
+
const doc = await openFixture$5(engine, opts);
|
|
4704
4964
|
try {
|
|
4705
4965
|
const list = await doc.pages.list();
|
|
4706
4966
|
const page = doc.page(list.pages[0].pageObjectNumber);
|
|
@@ -4726,7 +4986,7 @@ function runPieceInfoConformance(runner, opts) {
|
|
|
4726
4986
|
});
|
|
4727
4987
|
test("writes persist through save → re-open", async () => {
|
|
4728
4988
|
if (!supported || opts.openKind !== "bytes") return;
|
|
4729
|
-
const doc = await openFixture$
|
|
4989
|
+
const doc = await openFixture$5(engine, opts);
|
|
4730
4990
|
let reopened = null;
|
|
4731
4991
|
try {
|
|
4732
4992
|
const pon = (await doc.pages.list()).pages[0].pageObjectNumber;
|
|
@@ -4759,7 +5019,7 @@ function runPieceInfoConformance(runner, opts) {
|
|
|
4759
5019
|
});
|
|
4760
5020
|
test("null deletes a key; clear removes an entry; siblings survive", async () => {
|
|
4761
5021
|
if (!supported) return;
|
|
4762
|
-
const doc = await openFixture$
|
|
5022
|
+
const doc = await openFixture$5(engine, opts);
|
|
4763
5023
|
try {
|
|
4764
5024
|
await doc.pieceInfo.update(APP, {
|
|
4765
5025
|
name: "A",
|
|
@@ -4785,7 +5045,7 @@ function runPieceInfoConformance(runner, opts) {
|
|
|
4785
5045
|
});
|
|
4786
5046
|
test("an application that was never written reads as null", async () => {
|
|
4787
5047
|
if (!supported) return;
|
|
4788
|
-
const doc = await openFixture$
|
|
5048
|
+
const doc = await openFixture$5(engine, opts);
|
|
4789
5049
|
try {
|
|
4790
5050
|
expect(await doc.pieceInfo.read("EMBD_NeverWritten")).toBe(null);
|
|
4791
5051
|
const list = await doc.pages.list();
|
|
@@ -4796,7 +5056,7 @@ function runPieceInfoConformance(runner, opts) {
|
|
|
4796
5056
|
});
|
|
4797
5057
|
});
|
|
4798
5058
|
}
|
|
4799
|
-
async function openFixture$
|
|
5059
|
+
async function openFixture$5(engine, opts) {
|
|
4800
5060
|
if (opts.openKind === "bytes") {
|
|
4801
5061
|
const bytes = await opts.fixture.bytes();
|
|
4802
5062
|
return engine.open({
|
|
@@ -4859,7 +5119,7 @@ function runDocumentEventsConformance(runner, opts) {
|
|
|
4859
5119
|
if (engine) await engine.destroy();
|
|
4860
5120
|
});
|
|
4861
5121
|
test("every confirmed mutation publishes exactly one event, results verbatim", async () => {
|
|
4862
|
-
const doc = await openFixture$
|
|
5122
|
+
const doc = await openFixture$4(engine, opts);
|
|
4863
5123
|
try {
|
|
4864
5124
|
const events = [];
|
|
4865
5125
|
doc.events.subscribe((event) => events.push(event));
|
|
@@ -4906,19 +5166,46 @@ function runDocumentEventsConformance(runner, opts) {
|
|
|
4906
5166
|
expect(evDeleted.layout).toEqual(deleted.layout);
|
|
4907
5167
|
}
|
|
4908
5168
|
if (evMeta.type === "metadata.updated") expect(evMeta.metadata).toEqual(meta.metadata);
|
|
5169
|
+
const first = events[0];
|
|
5170
|
+
expect(first !== void 0 && "origin" in first).toBe(true);
|
|
5171
|
+
if (first === void 0 || !("origin" in first)) return;
|
|
4909
5172
|
for (const event of events) {
|
|
5173
|
+
expect("origin" in event).toBe(true);
|
|
5174
|
+
if (!("origin" in event)) continue;
|
|
4910
5175
|
expect(event.origin.kind).toBe("local");
|
|
4911
5176
|
expect(typeof event.origin.sessionId).toBe("string");
|
|
4912
5177
|
expect(event.origin.sessionId.length > 0).toBe(true);
|
|
4913
|
-
expect(event.origin.sessionId).toBe(
|
|
5178
|
+
expect(event.origin.sessionId).toBe(first.origin.sessionId);
|
|
4914
5179
|
expect(typeof event.origin.ts).toBe("number");
|
|
4915
5180
|
}
|
|
4916
5181
|
} finally {
|
|
4917
5182
|
await doc.close();
|
|
4918
5183
|
}
|
|
4919
5184
|
});
|
|
5185
|
+
test("pages.inserted rides verbatim", async () => {
|
|
5186
|
+
const doc = await openFixture$4(engine, opts);
|
|
5187
|
+
try {
|
|
5188
|
+
const events = [];
|
|
5189
|
+
doc.events.subscribe((event) => events.push(event));
|
|
5190
|
+
const inserted = await doc.pages.insertBlank({ size: {
|
|
5191
|
+
width: 396,
|
|
5192
|
+
height: 612
|
|
5193
|
+
} }, 0);
|
|
5194
|
+
expect(events.map((event) => event.type)).toEqual(["pages.inserted"]);
|
|
5195
|
+
const [evInserted] = events;
|
|
5196
|
+
if (evInserted.type === "pages.inserted") {
|
|
5197
|
+
expect(evInserted.insertedPageObjectNumbers).toEqual(inserted.insertedPageObjectNumbers);
|
|
5198
|
+
expect(evInserted.layout).toEqual(inserted.layout);
|
|
5199
|
+
expect(evInserted.cache).toEqual(inserted.cache);
|
|
5200
|
+
expect(evInserted.destIndex).toBe(0);
|
|
5201
|
+
expect(evInserted.origin.kind).toBe("local");
|
|
5202
|
+
}
|
|
5203
|
+
} finally {
|
|
5204
|
+
await doc.close();
|
|
5205
|
+
}
|
|
5206
|
+
});
|
|
4920
5207
|
test("a FAILED mutation publishes nothing (events are ground truth)", async () => {
|
|
4921
|
-
const doc = await openFixture$
|
|
5208
|
+
const doc = await openFixture$4(engine, opts);
|
|
4922
5209
|
try {
|
|
4923
5210
|
const events = [];
|
|
4924
5211
|
doc.events.subscribe((event) => events.push(event));
|
|
@@ -4936,7 +5223,7 @@ function runDocumentEventsConformance(runner, opts) {
|
|
|
4936
5223
|
}
|
|
4937
5224
|
});
|
|
4938
5225
|
test("unsubscribe stops delivery", async () => {
|
|
4939
|
-
const doc = await openFixture$
|
|
5226
|
+
const doc = await openFixture$4(engine, opts);
|
|
4940
5227
|
try {
|
|
4941
5228
|
const events = [];
|
|
4942
5229
|
doc.events.subscribe((event) => events.push(event))();
|
|
@@ -4949,7 +5236,7 @@ function runDocumentEventsConformance(runner, opts) {
|
|
|
4949
5236
|
});
|
|
4950
5237
|
});
|
|
4951
5238
|
}
|
|
4952
|
-
async function openFixture$
|
|
5239
|
+
async function openFixture$4(engine, opts) {
|
|
4953
5240
|
if (opts.openKind === "bytes") {
|
|
4954
5241
|
const bytes = await opts.fixture.bytes();
|
|
4955
5242
|
return engine.open({
|
|
@@ -4976,7 +5263,7 @@ function runPageTextConformance(runner, opts) {
|
|
|
4976
5263
|
if (engine) await engine.destroy();
|
|
4977
5264
|
});
|
|
4978
5265
|
test("read() returns a PageTextSnapshot with non-empty text", async () => {
|
|
4979
|
-
const doc = await openFixture$
|
|
5266
|
+
const doc = await openFixture$3(engine, opts);
|
|
4980
5267
|
try {
|
|
4981
5268
|
const snap = await doc.page(opts.fixture.pageObjectNumber).text.read();
|
|
4982
5269
|
expect(require_schemas.PageTextSnapshotSchema.safeParse(snap).success).toBe(true);
|
|
@@ -4987,7 +5274,7 @@ function runPageTextConformance(runner, opts) {
|
|
|
4987
5274
|
}
|
|
4988
5275
|
});
|
|
4989
5276
|
test("extracted text contains the expected substring", async () => {
|
|
4990
|
-
const doc = await openFixture$
|
|
5277
|
+
const doc = await openFixture$3(engine, opts);
|
|
4991
5278
|
try {
|
|
4992
5279
|
const snap = await doc.page(opts.fixture.pageObjectNumber).text.read();
|
|
4993
5280
|
expect(snap.text.includes(opts.fixture.expectedSubstring)).toBe(true);
|
|
@@ -4996,7 +5283,7 @@ function runPageTextConformance(runner, opts) {
|
|
|
4996
5283
|
}
|
|
4997
5284
|
});
|
|
4998
5285
|
test("read() on an unknown pageObjectNumber throws NotFound", async () => {
|
|
4999
|
-
const doc = await openFixture$
|
|
5286
|
+
const doc = await openFixture$3(engine, opts);
|
|
5000
5287
|
try {
|
|
5001
5288
|
let caught;
|
|
5002
5289
|
try {
|
|
@@ -5005,13 +5292,13 @@ function runPageTextConformance(runner, opts) {
|
|
|
5005
5292
|
caught = err;
|
|
5006
5293
|
}
|
|
5007
5294
|
expect(caught).toBeTruthy();
|
|
5008
|
-
expect(require_fold.EngineError.is(caught,
|
|
5295
|
+
expect(require_fold.EngineError.is(caught, require_PageInsertBlankInput.EngineErrorCode.NotFound)).toBe(true);
|
|
5009
5296
|
} finally {
|
|
5010
5297
|
await doc.close();
|
|
5011
5298
|
}
|
|
5012
5299
|
});
|
|
5013
5300
|
test("abort() on read rejects with AbortError", async () => {
|
|
5014
|
-
const doc = await openFixture$
|
|
5301
|
+
const doc = await openFixture$3(engine, opts);
|
|
5015
5302
|
try {
|
|
5016
5303
|
const p = doc.page(opts.fixture.pageObjectNumber).text.read();
|
|
5017
5304
|
p.abort("test");
|
|
@@ -5021,7 +5308,7 @@ function runPageTextConformance(runner, opts) {
|
|
|
5021
5308
|
}
|
|
5022
5309
|
});
|
|
5023
5310
|
test("read after close throws DocNotOpen", async () => {
|
|
5024
|
-
const doc = await openFixture$
|
|
5311
|
+
const doc = await openFixture$3(engine, opts);
|
|
5025
5312
|
const page = doc.page(opts.fixture.pageObjectNumber);
|
|
5026
5313
|
await doc.close();
|
|
5027
5314
|
let caught;
|
|
@@ -5031,10 +5318,324 @@ function runPageTextConformance(runner, opts) {
|
|
|
5031
5318
|
caught = err;
|
|
5032
5319
|
}
|
|
5033
5320
|
expect(caught).toBeTruthy();
|
|
5034
|
-
expect(require_fold.EngineError.is(caught,
|
|
5321
|
+
expect(require_fold.EngineError.is(caught, require_PageInsertBlankInput.EngineErrorCode.DocNotOpen)).toBe(true);
|
|
5322
|
+
});
|
|
5323
|
+
});
|
|
5324
|
+
}
|
|
5325
|
+
async function openFixture$3(engine, opts) {
|
|
5326
|
+
if (opts.openKind === "bytes") {
|
|
5327
|
+
const bytes = await opts.fixture.bytes();
|
|
5328
|
+
return engine.open({
|
|
5329
|
+
kind: "bytes",
|
|
5330
|
+
id: opts.fixture.id,
|
|
5331
|
+
bytes
|
|
5332
|
+
});
|
|
5333
|
+
}
|
|
5334
|
+
return engine.open({
|
|
5335
|
+
kind: "id",
|
|
5336
|
+
id: opts.fixture.cloudId ?? opts.fixture.id
|
|
5337
|
+
});
|
|
5338
|
+
}
|
|
5339
|
+
//#endregion
|
|
5340
|
+
//#region src/conformance/runTextDivergenceConformance.ts
|
|
5341
|
+
function runTextDivergenceConformance(runner, opts) {
|
|
5342
|
+
const { describe, test, beforeAll, afterAll, expect } = runner;
|
|
5343
|
+
const fixture = opts.fixture;
|
|
5344
|
+
describe(`text divergence conformance: ${opts.label} [${fixture.id}]`, () => {
|
|
5345
|
+
let engine;
|
|
5346
|
+
beforeAll(async () => {
|
|
5347
|
+
engine = await opts.makeEngine();
|
|
5348
|
+
});
|
|
5349
|
+
afterAll(async () => {
|
|
5350
|
+
if (engine) await engine.destroy();
|
|
5351
|
+
});
|
|
5352
|
+
test("snapshot is schema-valid with the exact text, charCount, and charMap", async () => {
|
|
5353
|
+
const doc = await openFixture$2(engine, opts);
|
|
5354
|
+
try {
|
|
5355
|
+
const snap = await doc.page(fixture.pageObjectNumber).text.read();
|
|
5356
|
+
expect(require_schemas.PageTextSnapshotSchema.safeParse(snap).success).toBe(true);
|
|
5357
|
+
expect(snap.text).toBe(fixture.exactText);
|
|
5358
|
+
expect(snap.charCount).toBe(fixture.expectedCharCount);
|
|
5359
|
+
const anchors = snap.charMap ?? null;
|
|
5360
|
+
if (fixture.expectedCharMap === null) expect(anchors === null || anchors.length === 0).toBe(true);
|
|
5361
|
+
else expect(anchors === null ? null : anchors.map((a) => [a[0], a[1]])).toEqual(fixture.expectedCharMap.map((a) => [a[0], a[1]]));
|
|
5362
|
+
} finally {
|
|
5363
|
+
await doc.close();
|
|
5364
|
+
}
|
|
5365
|
+
});
|
|
5366
|
+
test("char-space slicing round-trips through the map", async () => {
|
|
5367
|
+
const doc = await openFixture$2(engine, opts);
|
|
5368
|
+
try {
|
|
5369
|
+
const snap = await doc.page(fixture.pageObjectNumber).text.read();
|
|
5370
|
+
expect(require_PageInsertBlankInput.sliceTextByChars(snap, 0, snap.charCount)).toBe(snap.text);
|
|
5371
|
+
for (const s of fixture.slices ?? []) expect(require_PageInsertBlankInput.sliceTextByChars(snap, s.from, s.to)).toBe(s.text);
|
|
5372
|
+
} finally {
|
|
5373
|
+
await doc.close();
|
|
5374
|
+
}
|
|
5375
|
+
});
|
|
5376
|
+
if (fixture.search) {
|
|
5377
|
+
const probe = fixture.search;
|
|
5378
|
+
test("search hits address character space and join the text by slicing", async () => {
|
|
5379
|
+
const doc = await openFixture$2(engine, opts);
|
|
5380
|
+
try {
|
|
5381
|
+
const hit = (await doc.search.query({
|
|
5382
|
+
query: { text: probe.query },
|
|
5383
|
+
mode: "rects"
|
|
5384
|
+
})).matches.find((m) => m.pageObjectNumber === fixture.pageObjectNumber);
|
|
5385
|
+
expect(hit === void 0).toBe(false);
|
|
5386
|
+
expect(hit.charStart).toBe(probe.charStart);
|
|
5387
|
+
expect(hit.charCount).toBe(probe.charCount);
|
|
5388
|
+
expect(hit.segments.length > 0).toBe(true);
|
|
5389
|
+
const snap = await doc.page(fixture.pageObjectNumber).text.read();
|
|
5390
|
+
expect(require_PageInsertBlankInput.sliceTextByChars(snap, hit.charStart, hit.charStart + hit.charCount)).toBe(probe.matchedText);
|
|
5391
|
+
} finally {
|
|
5392
|
+
await doc.close();
|
|
5393
|
+
}
|
|
5394
|
+
});
|
|
5395
|
+
}
|
|
5396
|
+
});
|
|
5397
|
+
}
|
|
5398
|
+
async function openFixture$2(engine, opts) {
|
|
5399
|
+
if (opts.openKind === "bytes") {
|
|
5400
|
+
const bytes = await opts.fixture.bytes();
|
|
5401
|
+
return engine.open({
|
|
5402
|
+
kind: "bytes",
|
|
5403
|
+
id: opts.fixture.id,
|
|
5404
|
+
bytes
|
|
5035
5405
|
});
|
|
5406
|
+
}
|
|
5407
|
+
return engine.open({
|
|
5408
|
+
kind: "id",
|
|
5409
|
+
id: opts.fixture.cloudId ?? opts.fixture.id
|
|
5036
5410
|
});
|
|
5037
5411
|
}
|
|
5412
|
+
/**
|
|
5413
|
+
* THE pinned divergence cases — one table, consumed by both engines' suites
|
|
5414
|
+
* so expected values cannot drift. Values verified against the wasm runtime
|
|
5415
|
+
* (see each case). All fixtures are single-page; the page's indirect object
|
|
5416
|
+
* number is 3 in each.
|
|
5417
|
+
*/
|
|
5418
|
+
const TEXT_DIVERGENCE_CASES = {
|
|
5419
|
+
/** Leading NON-PRINTING character: 31 character slots, 30 text units —
|
|
5420
|
+
* every text offset shifts by one, encoded by the single anchor [1, 0].
|
|
5421
|
+
* The searchex embeddertest for this fixture pins the same +1 shift. */
|
|
5422
|
+
bug1139: {
|
|
5423
|
+
resource: "bug_1139.pdf",
|
|
5424
|
+
pageObjectNumber: 3,
|
|
5425
|
+
exactText: "Hello, world!\r\nGoodbye, world!",
|
|
5426
|
+
expectedCharCount: 31,
|
|
5427
|
+
expectedCharMap: [[1, 0]],
|
|
5428
|
+
slices: [
|
|
5429
|
+
{
|
|
5430
|
+
from: 0,
|
|
5431
|
+
to: 1,
|
|
5432
|
+
text: ""
|
|
5433
|
+
},
|
|
5434
|
+
{
|
|
5435
|
+
from: 1,
|
|
5436
|
+
to: 7,
|
|
5437
|
+
text: "Hello,"
|
|
5438
|
+
},
|
|
5439
|
+
{
|
|
5440
|
+
from: 16,
|
|
5441
|
+
to: 23,
|
|
5442
|
+
text: "Goodbye"
|
|
5443
|
+
}
|
|
5444
|
+
],
|
|
5445
|
+
search: {
|
|
5446
|
+
query: "Goodbye",
|
|
5447
|
+
charStart: 16,
|
|
5448
|
+
charCount: 7,
|
|
5449
|
+
matchedText: "Goodbye"
|
|
5450
|
+
}
|
|
5451
|
+
},
|
|
5452
|
+
/** `/ActualText` replacement: the span's real glyphs are REPLACED by one
|
|
5453
|
+
* synthetic kPiece character per ActualText character, lockstep with the
|
|
5454
|
+
* text (identity map), with synthesized evenly-divided boxes — so search
|
|
5455
|
+
* segments exist and extraction yields the ActualText, not the glyphs. */
|
|
5456
|
+
actualText: {
|
|
5457
|
+
resource: "bug_384770169.pdf",
|
|
5458
|
+
pageObjectNumber: 3,
|
|
5459
|
+
exactText: "What is my favorite food?",
|
|
5460
|
+
expectedCharCount: 25,
|
|
5461
|
+
expectedCharMap: null,
|
|
5462
|
+
slices: [{
|
|
5463
|
+
from: 11,
|
|
5464
|
+
to: 19,
|
|
5465
|
+
text: "favorite"
|
|
5466
|
+
}],
|
|
5467
|
+
search: {
|
|
5468
|
+
query: "favorite",
|
|
5469
|
+
charStart: 11,
|
|
5470
|
+
charCount: 8,
|
|
5471
|
+
matchedText: "favorite"
|
|
5472
|
+
}
|
|
5473
|
+
},
|
|
5474
|
+
/** Supplementary-plane text via a ToUnicode surrogate pair: PDFium stores
|
|
5475
|
+
* one character-list entry PER SURROGATE HALF in lockstep with the text
|
|
5476
|
+
* (identity map, no divergence in this representation) — and the emoji
|
|
5477
|
+
* SURVIVES extraction end to end. The combined-astral representation
|
|
5478
|
+
* (font-cmap path, one entry per code point → a [+2] anchor) is covered
|
|
5479
|
+
* by the charmap unit tests and the reader's divergent walk. */
|
|
5480
|
+
astralToUnicode: {
|
|
5481
|
+
resource: "embedpdf_astral_tounicode.pdf",
|
|
5482
|
+
pageObjectNumber: 3,
|
|
5483
|
+
exactText: "😀B!",
|
|
5484
|
+
expectedCharCount: 4,
|
|
5485
|
+
expectedCharMap: null,
|
|
5486
|
+
slices: [{
|
|
5487
|
+
from: 0,
|
|
5488
|
+
to: 2,
|
|
5489
|
+
text: "😀"
|
|
5490
|
+
}, {
|
|
5491
|
+
from: 2,
|
|
5492
|
+
to: 3,
|
|
5493
|
+
text: "B"
|
|
5494
|
+
}],
|
|
5495
|
+
search: {
|
|
5496
|
+
query: "B!",
|
|
5497
|
+
charStart: 2,
|
|
5498
|
+
charCount: 2,
|
|
5499
|
+
matchedText: "B!"
|
|
5500
|
+
}
|
|
5501
|
+
}
|
|
5502
|
+
};
|
|
5503
|
+
//#endregion
|
|
5504
|
+
//#region src/conformance/runPageGeometryOrientationConformance.ts
|
|
5505
|
+
const FLAG_EMPTY = 2;
|
|
5506
|
+
/** Absolute tolerance for coordinate assertions (PDF points). */
|
|
5507
|
+
const COORD_TOLERANCE = .001;
|
|
5508
|
+
/** Tolerance for baseline-angle assertions (radians). */
|
|
5509
|
+
const ANGLE_TOLERANCE = .001;
|
|
5510
|
+
function runPageGeometryOrientationConformance(runner, opts) {
|
|
5511
|
+
const { describe, test, beforeAll, afterAll, expect } = runner;
|
|
5512
|
+
describe(`page geometry orientation conformance: ${opts.label} [${opts.fixture.id}]`, () => {
|
|
5513
|
+
let engine;
|
|
5514
|
+
beforeAll(async () => {
|
|
5515
|
+
engine = await opts.makeEngine();
|
|
5516
|
+
});
|
|
5517
|
+
afterAll(async () => {
|
|
5518
|
+
if (engine) await engine.destroy();
|
|
5519
|
+
});
|
|
5520
|
+
const readSnapshot = async () => {
|
|
5521
|
+
const doc = await openFixture$1(engine, opts);
|
|
5522
|
+
return {
|
|
5523
|
+
snapshot: await doc.page(opts.fixture.pageObjectNumber).geometry.read(),
|
|
5524
|
+
close: () => doc.close()
|
|
5525
|
+
};
|
|
5526
|
+
};
|
|
5527
|
+
test("snapshot round-trips the wire schema", async () => {
|
|
5528
|
+
const { snapshot, close } = await readSnapshot();
|
|
5529
|
+
try {
|
|
5530
|
+
const parsed = require_schemas.PageGeometrySnapshotSchema.safeParse(snapshot);
|
|
5531
|
+
expect(parsed.success).toBe(true);
|
|
5532
|
+
if (parsed.success) expect(parsed.data).toEqual(snapshot);
|
|
5533
|
+
} finally {
|
|
5534
|
+
await close();
|
|
5535
|
+
}
|
|
5536
|
+
});
|
|
5537
|
+
test("run charStart indices tile the page glyph sequence", async () => {
|
|
5538
|
+
const { snapshot, close } = await readSnapshot();
|
|
5539
|
+
try {
|
|
5540
|
+
let next = 0;
|
|
5541
|
+
for (const run of snapshot.runs) {
|
|
5542
|
+
expect(run.charStart).toBe(next);
|
|
5543
|
+
next += run.glyphs.length;
|
|
5544
|
+
}
|
|
5545
|
+
} finally {
|
|
5546
|
+
await close();
|
|
5547
|
+
}
|
|
5548
|
+
});
|
|
5549
|
+
test("runs match the fixture orientation expectation", async () => {
|
|
5550
|
+
const { snapshot, close } = await readSnapshot();
|
|
5551
|
+
try {
|
|
5552
|
+
const expectation = opts.fixture.expectation;
|
|
5553
|
+
if (expectation.kind === "upright") {
|
|
5554
|
+
for (const run of snapshot.runs) {
|
|
5555
|
+
expect(require_fold.isRotatedGeometryRun(run)).toBe(false);
|
|
5556
|
+
if (require_fold.isRotatedGeometryRun(run)) continue;
|
|
5557
|
+
for (const glyph of run.glyphs) {
|
|
5558
|
+
expect("looseQuad" in glyph).toBe(false);
|
|
5559
|
+
if (glyph.flags & FLAG_EMPTY) expect(glyph.looseBox).toEqual({
|
|
5560
|
+
left: 0,
|
|
5561
|
+
bottom: 0,
|
|
5562
|
+
right: 0,
|
|
5563
|
+
top: 0
|
|
5564
|
+
});
|
|
5565
|
+
}
|
|
5566
|
+
}
|
|
5567
|
+
return;
|
|
5568
|
+
}
|
|
5569
|
+
if (expectation.kind === "empty-only") {
|
|
5570
|
+
for (const run of snapshot.runs) {
|
|
5571
|
+
expect(require_fold.isRotatedGeometryRun(run)).toBe(false);
|
|
5572
|
+
if (require_fold.isRotatedGeometryRun(run)) continue;
|
|
5573
|
+
for (const glyph of run.glyphs) {
|
|
5574
|
+
expect(glyph.flags & FLAG_EMPTY).toBe(FLAG_EMPTY);
|
|
5575
|
+
expect(glyph.looseBox).toEqual({
|
|
5576
|
+
left: 0,
|
|
5577
|
+
bottom: 0,
|
|
5578
|
+
right: 0,
|
|
5579
|
+
top: 0
|
|
5580
|
+
});
|
|
5581
|
+
}
|
|
5582
|
+
}
|
|
5583
|
+
return;
|
|
5584
|
+
}
|
|
5585
|
+
const rotatedRuns = snapshot.runs.filter(require_fold.isRotatedGeometryRun);
|
|
5586
|
+
expect(rotatedRuns.length >= (expectation.minRotatedRuns ?? 1)).toBe(true);
|
|
5587
|
+
for (const run of rotatedRuns) {
|
|
5588
|
+
expect(expectation.rotations.some((angle) => angleClose(run.rotation, angle, ANGLE_TOLERANCE))).toBe(true);
|
|
5589
|
+
expect(run.ascentFlip).toBe(expectation.ascentFlip);
|
|
5590
|
+
assertRotatedRunGeometry(run);
|
|
5591
|
+
}
|
|
5592
|
+
if (expectation.sheared) {
|
|
5593
|
+
const shearedGlyphs = rotatedRuns.flatMap((run) => run.glyphs).filter((glyph) => (glyph.flags & FLAG_EMPTY) === 0 && Math.abs(glyph.looseQuad.p3.x - glyph.looseQuad.p1.x) > 1);
|
|
5594
|
+
expect(shearedGlyphs.length > 0).toBe(true);
|
|
5595
|
+
}
|
|
5596
|
+
} finally {
|
|
5597
|
+
await close();
|
|
5598
|
+
}
|
|
5599
|
+
});
|
|
5600
|
+
function assertRotatedRunGeometry(run) {
|
|
5601
|
+
for (const glyph of run.glyphs) {
|
|
5602
|
+
if (glyph.flags & FLAG_EMPTY) {
|
|
5603
|
+
expect(glyph.looseQuad).toEqual({
|
|
5604
|
+
p1: {
|
|
5605
|
+
x: 0,
|
|
5606
|
+
y: 0
|
|
5607
|
+
},
|
|
5608
|
+
p2: {
|
|
5609
|
+
x: 0,
|
|
5610
|
+
y: 0
|
|
5611
|
+
},
|
|
5612
|
+
p3: {
|
|
5613
|
+
x: 0,
|
|
5614
|
+
y: 0
|
|
5615
|
+
},
|
|
5616
|
+
p4: {
|
|
5617
|
+
x: 0,
|
|
5618
|
+
y: 0
|
|
5619
|
+
}
|
|
5620
|
+
});
|
|
5621
|
+
continue;
|
|
5622
|
+
}
|
|
5623
|
+
const q = glyph.looseQuad;
|
|
5624
|
+
expect(Math.abs(q.p2.x - q.p1.x - (q.p4.x - q.p3.x)) <= COORD_TOLERANCE).toBe(true);
|
|
5625
|
+
expect(Math.abs(q.p2.y - q.p1.y - (q.p4.y - q.p3.y)) <= COORD_TOLERANCE).toBe(true);
|
|
5626
|
+
const bounds = require_fold.pdfQuadBounds(q);
|
|
5627
|
+
expect(bounds.left >= run.rect.left - COORD_TOLERANCE).toBe(true);
|
|
5628
|
+
expect(bounds.right <= run.rect.right + COORD_TOLERANCE).toBe(true);
|
|
5629
|
+
expect(bounds.bottom >= run.rect.bottom - COORD_TOLERANCE).toBe(true);
|
|
5630
|
+
expect(bounds.top <= run.rect.top + COORD_TOLERANCE).toBe(true);
|
|
5631
|
+
}
|
|
5632
|
+
}
|
|
5633
|
+
});
|
|
5634
|
+
}
|
|
5635
|
+
function angleClose(a, b, tolerance) {
|
|
5636
|
+
const delta = a - b;
|
|
5637
|
+
return Math.abs(Math.atan2(Math.sin(delta), Math.cos(delta))) <= tolerance;
|
|
5638
|
+
}
|
|
5038
5639
|
async function openFixture$1(engine, opts) {
|
|
5039
5640
|
if (opts.openKind === "bytes") {
|
|
5040
5641
|
const bytes = await opts.fixture.bytes();
|
|
@@ -5090,10 +5691,27 @@ function runSearchConformance(runner, opts) {
|
|
|
5090
5691
|
expect(matches.some((m) => m.pageObjectNumber === fixture.presentPageObjectNumber)).toBe(true);
|
|
5091
5692
|
for (const m of matches) {
|
|
5092
5693
|
expect(m.charCount > 0).toBe(true);
|
|
5093
|
-
expect(m.
|
|
5094
|
-
for (const
|
|
5095
|
-
expect(
|
|
5096
|
-
expect(
|
|
5694
|
+
expect(m.segments.length > 0).toBe(true);
|
|
5695
|
+
for (const s of m.segments) {
|
|
5696
|
+
expect(s.rect.right > s.rect.left).toBe(true);
|
|
5697
|
+
expect(s.rect.top > s.rect.bottom).toBe(true);
|
|
5698
|
+
const xs = [
|
|
5699
|
+
s.quad.p1.x,
|
|
5700
|
+
s.quad.p2.x,
|
|
5701
|
+
s.quad.p3.x,
|
|
5702
|
+
s.quad.p4.x
|
|
5703
|
+
];
|
|
5704
|
+
const ys = [
|
|
5705
|
+
s.quad.p1.y,
|
|
5706
|
+
s.quad.p2.y,
|
|
5707
|
+
s.quad.p3.y,
|
|
5708
|
+
s.quad.p4.y
|
|
5709
|
+
];
|
|
5710
|
+
expect(Math.abs(s.rect.left - Math.min(...xs)) < .001).toBe(true);
|
|
5711
|
+
expect(Math.abs(s.rect.right - Math.max(...xs)) < .001).toBe(true);
|
|
5712
|
+
expect(Math.abs(s.rect.bottom - Math.min(...ys)) < .001).toBe(true);
|
|
5713
|
+
expect(Math.abs(s.rect.top - Math.max(...ys)) < .001).toBe(true);
|
|
5714
|
+
expect(s.advance === 1 || s.advance === -1).toBe(true);
|
|
5097
5715
|
}
|
|
5098
5716
|
}
|
|
5099
5717
|
} finally {
|
|
@@ -5193,7 +5811,7 @@ function runSearchConformance(runner, opts) {
|
|
|
5193
5811
|
} catch (err) {
|
|
5194
5812
|
caught = err;
|
|
5195
5813
|
}
|
|
5196
|
-
expect(require_fold.EngineError.is(caught,
|
|
5814
|
+
expect(require_fold.EngineError.is(caught, require_PageInsertBlankInput.EngineErrorCode.InvalidArg)).toBe(true);
|
|
5197
5815
|
} finally {
|
|
5198
5816
|
await doc.close();
|
|
5199
5817
|
}
|
|
@@ -5210,7 +5828,7 @@ function runSearchConformance(runner, opts) {
|
|
|
5210
5828
|
} catch (err) {
|
|
5211
5829
|
caught = err;
|
|
5212
5830
|
}
|
|
5213
|
-
expect(require_fold.EngineError.is(caught,
|
|
5831
|
+
expect(require_fold.EngineError.is(caught, require_PageInsertBlankInput.EngineErrorCode.InvalidArg)).toBe(true);
|
|
5214
5832
|
} finally {
|
|
5215
5833
|
await doc.close();
|
|
5216
5834
|
}
|
|
@@ -5225,7 +5843,7 @@ function runSearchConformance(runner, opts) {
|
|
|
5225
5843
|
expect(matches.length > 0).toBe(true);
|
|
5226
5844
|
for (const m of matches) {
|
|
5227
5845
|
expect(m.charCount > 0).toBe(true);
|
|
5228
|
-
expect(m.
|
|
5846
|
+
expect(m.segments.length > 0).toBe(true);
|
|
5229
5847
|
}
|
|
5230
5848
|
} finally {
|
|
5231
5849
|
await doc.close();
|
|
@@ -5266,7 +5884,7 @@ function runSearchConformance(runner, opts) {
|
|
|
5266
5884
|
} catch (err) {
|
|
5267
5885
|
caught = err;
|
|
5268
5886
|
}
|
|
5269
|
-
expect(require_fold.EngineError.is(caught,
|
|
5887
|
+
expect(require_fold.EngineError.is(caught, require_PageInsertBlankInput.EngineErrorCode.InvalidArg)).toBe(true);
|
|
5270
5888
|
} finally {
|
|
5271
5889
|
await doc.close();
|
|
5272
5890
|
}
|
|
@@ -5288,7 +5906,7 @@ function runSearchConformance(runner, opts) {
|
|
|
5288
5906
|
} catch (err) {
|
|
5289
5907
|
caught = err;
|
|
5290
5908
|
}
|
|
5291
|
-
expect(require_fold.EngineError.is(caught,
|
|
5909
|
+
expect(require_fold.EngineError.is(caught, require_PageInsertBlankInput.EngineErrorCode.InvalidArg)).toBe(true);
|
|
5292
5910
|
}
|
|
5293
5911
|
} finally {
|
|
5294
5912
|
await doc.close();
|
|
@@ -5323,7 +5941,7 @@ function runSearchConformance(runner, opts) {
|
|
|
5323
5941
|
} catch (err) {
|
|
5324
5942
|
caught = err;
|
|
5325
5943
|
}
|
|
5326
|
-
expect(require_fold.EngineError.is(caught,
|
|
5944
|
+
expect(require_fold.EngineError.is(caught, require_PageInsertBlankInput.EngineErrorCode.DocNotOpen)).toBe(true);
|
|
5327
5945
|
});
|
|
5328
5946
|
});
|
|
5329
5947
|
}
|
|
@@ -5352,6 +5970,8 @@ async function openFixture(engine, opts) {
|
|
|
5352
5970
|
* are disjoint. We do compare `pageObjectNumber` and `generation` (which
|
|
5353
5971
|
* should be 0 for fresh reads on both sides). Page order is no longer part
|
|
5354
5972
|
* of `PageState`; it lives in `PageLayout.index` (see `pages.list()`).
|
|
5973
|
+
* `auditHead` is likewise not compared: it is a cloud-only reconciliation
|
|
5974
|
+
* cursor, absent on local snapshots by design.
|
|
5355
5975
|
*/
|
|
5356
5976
|
function diffAnnotationListSnapshot(a, b) {
|
|
5357
5977
|
const errs = [];
|
|
@@ -5390,6 +6010,7 @@ function diffAnnotation(i, a, b, errs) {
|
|
|
5390
6010
|
if (a.nm !== b.nm) errs.push(`annotations[${i}].nm mismatch: ${a.nm} vs ${b.nm}`);
|
|
5391
6011
|
}
|
|
5392
6012
|
//#endregion
|
|
6013
|
+
exports.TEXT_DIVERGENCE_CASES = TEXT_DIVERGENCE_CASES;
|
|
5393
6014
|
exports.diffAnnotationListSnapshot = diffAnnotationListSnapshot;
|
|
5394
6015
|
exports.diffAnnotationListSnapshotAll = diffAnnotationListSnapshotAll;
|
|
5395
6016
|
exports.runActionsConformance = runActionsConformance;
|
|
@@ -5403,6 +6024,8 @@ exports.runMetadataConformance = runMetadataConformance;
|
|
|
5403
6024
|
exports.runPageDeleteConformance = runPageDeleteConformance;
|
|
5404
6025
|
exports.runPageExtractConformance = runPageExtractConformance;
|
|
5405
6026
|
exports.runPageFlattenConformance = runPageFlattenConformance;
|
|
6027
|
+
exports.runPageGeometryOrientationConformance = runPageGeometryOrientationConformance;
|
|
6028
|
+
exports.runPageInsertBlankConformance = runPageInsertBlankConformance;
|
|
5406
6029
|
exports.runPageInsertConformance = runPageInsertConformance;
|
|
5407
6030
|
exports.runPageReorderConformance = runPageReorderConformance;
|
|
5408
6031
|
exports.runPageRotateConformance = runPageRotateConformance;
|
|
@@ -5410,5 +6033,6 @@ exports.runPageTextConformance = runPageTextConformance;
|
|
|
5410
6033
|
exports.runPieceInfoConformance = runPieceInfoConformance;
|
|
5411
6034
|
exports.runRedactionApplyConformance = runRedactionApplyConformance;
|
|
5412
6035
|
exports.runSearchConformance = runSearchConformance;
|
|
6036
|
+
exports.runTextDivergenceConformance = runTextDivergenceConformance;
|
|
5413
6037
|
|
|
5414
6038
|
//# sourceMappingURL=conformance.cjs.map
|