pdfdancer-client-typescript 1.0.16 → 1.0.18
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/README.md +12 -4
- package/dist/__tests__/e2e/pdf-assertions.d.ts.map +1 -1
- package/dist/__tests__/e2e/pdf-assertions.js +1 -1
- package/dist/__tests__/e2e/pdf-assertions.js.map +1 -1
- package/dist/__tests__/e2e/test-drawing-helpers.d.ts +148 -0
- package/dist/__tests__/e2e/test-drawing-helpers.d.ts.map +1 -0
- package/dist/__tests__/e2e/test-drawing-helpers.js +343 -0
- package/dist/__tests__/e2e/test-drawing-helpers.js.map +1 -0
- package/dist/__tests__/e2e/test-helpers.d.ts +10 -0
- package/dist/__tests__/e2e/test-helpers.d.ts.map +1 -1
- package/dist/__tests__/e2e/test-helpers.js +55 -0
- package/dist/__tests__/e2e/test-helpers.js.map +1 -1
- package/dist/image-builder.d.ts +1 -0
- package/dist/image-builder.d.ts.map +1 -1
- package/dist/image-builder.js +4 -0
- package/dist/image-builder.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -1
- package/dist/index.js.map +1 -1
- package/dist/models.d.ts +54 -2
- package/dist/models.d.ts.map +1 -1
- package/dist/models.js +115 -1
- package/dist/models.js.map +1 -1
- package/dist/path-builder.d.ts +110 -0
- package/dist/path-builder.d.ts.map +1 -0
- package/dist/path-builder.js +191 -0
- package/dist/path-builder.js.map +1 -0
- package/dist/pdfdancer_v1.d.ts +7 -0
- package/dist/pdfdancer_v1.d.ts.map +1 -1
- package/dist/pdfdancer_v1.js +72 -2
- package/dist/pdfdancer_v1.js.map +1 -1
- package/package.json +18 -2
- package/.claude/commands/discuss.md +0 -4
- package/.eslintrc.js +0 -27
- package/.github/workflows/ci.yml +0 -86
- package/.github/workflows/daily-tests.yml +0 -54
- package/NOTICE +0 -8
- package/docs/openapi.yml +0 -2640
- package/fixtures/DancingScript-Regular.ttf +0 -0
- package/fixtures/Empty.pdf +0 -0
- package/fixtures/JetBrainsMono-Regular.ttf +0 -0
- package/fixtures/ObviouslyAwesome.pdf +0 -0
- package/fixtures/README.md +0 -23
- package/fixtures/Showcase.pdf +0 -0
- package/fixtures/basic-paths.pdf +0 -0
- package/fixtures/form-xobject-example.pdf +0 -0
- package/fixtures/logo-80.png +0 -0
- package/fixtures/mixed-form-types.pdf +0 -0
- package/jest.config.js +0 -27
- package/scripts/release.js +0 -91
- package/scripts/test-release.js +0 -59
- package/src/__tests__/assertions.ts +0 -12
- package/src/__tests__/client-v1.test.ts +0 -70
- package/src/__tests__/e2e/acroform.test.ts +0 -166
- package/src/__tests__/e2e/context-manager-showcase.test.ts +0 -267
- package/src/__tests__/e2e/create-new.test.ts +0 -133
- package/src/__tests__/e2e/form_x_object.test.ts +0 -87
- package/src/__tests__/e2e/image-showcase.test.ts +0 -133
- package/src/__tests__/e2e/image.test.ts +0 -147
- package/src/__tests__/e2e/line-showcase.test.ts +0 -113
- package/src/__tests__/e2e/line.test.ts +0 -187
- package/src/__tests__/e2e/page-showcase.test.ts +0 -154
- package/src/__tests__/e2e/page.test.ts +0 -47
- package/src/__tests__/e2e/paragraph-showcase.test.ts +0 -515
- package/src/__tests__/e2e/paragraph.test.ts +0 -681
- package/src/__tests__/e2e/path.test.ts +0 -108
- package/src/__tests__/e2e/pdf-assertions.ts +0 -248
- package/src/__tests__/e2e/pdfdancer-showcase.test.ts +0 -40
- package/src/__tests__/e2e/snapshot-showcase.test.ts +0 -158
- package/src/__tests__/e2e/snapshot.test.ts +0 -296
- package/src/__tests__/e2e/test-helpers.ts +0 -152
- package/src/__tests__/e2e/token_from_env.test.ts +0 -80
- package/src/__tests__/fingerprint.test.ts +0 -36
- package/src/__tests__/retry-mechanism.test.ts +0 -642
- package/src/__tests__/standard-fonts.test.ts +0 -87
- package/src/__tests__/url-builder.test.ts +0 -44
- package/src/exceptions.ts +0 -63
- package/src/fingerprint.ts +0 -182
- package/src/image-builder.ts +0 -59
- package/src/index.ts +0 -49
- package/src/models.ts +0 -1051
- package/src/page-builder.ts +0 -130
- package/src/paragraph-builder.ts +0 -644
- package/src/pdfdancer_v1.ts +0 -2283
- package/src/types.ts +0 -407
- package/tsconfig.json +0 -20
- package/update-api-spec.sh +0 -3
|
@@ -1,296 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* E2E tests for snapshot operations
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import {ObjectType, PDFDancer, DocumentSnapshot, PageSnapshot} from '../../index';
|
|
6
|
-
import {requireEnvAndFixture} from './test-helpers';
|
|
7
|
-
|
|
8
|
-
describe('Snapshot E2E Tests', () => {
|
|
9
|
-
|
|
10
|
-
test('get document snapshot', async () => {
|
|
11
|
-
const [baseUrl, token, pdfData] = await requireEnvAndFixture('ObviouslyAwesome.pdf');
|
|
12
|
-
const client = await PDFDancer.open(pdfData, token, baseUrl);
|
|
13
|
-
|
|
14
|
-
const snapshot = await client.getDocumentSnapshot();
|
|
15
|
-
|
|
16
|
-
// Verify snapshot structure
|
|
17
|
-
expect(snapshot).toBeDefined();
|
|
18
|
-
expect(snapshot).toBeInstanceOf(DocumentSnapshot);
|
|
19
|
-
|
|
20
|
-
// Verify page count
|
|
21
|
-
expect(snapshot.pageCount).toBe(12);
|
|
22
|
-
|
|
23
|
-
// Verify fonts array exists
|
|
24
|
-
expect(snapshot.fonts).toBeDefined();
|
|
25
|
-
expect(Array.isArray(snapshot.fonts)).toBe(true);
|
|
26
|
-
|
|
27
|
-
// Verify pages array
|
|
28
|
-
expect(snapshot.pages).toBeDefined();
|
|
29
|
-
expect(Array.isArray(snapshot.pages)).toBe(true);
|
|
30
|
-
expect(snapshot.pages.length).toBe(12);
|
|
31
|
-
|
|
32
|
-
// Verify each page snapshot
|
|
33
|
-
for (let i = 0; i < snapshot.pages.length; i++) {
|
|
34
|
-
const pageSnapshot = snapshot.pages[i];
|
|
35
|
-
expect(pageSnapshot).toBeInstanceOf(PageSnapshot);
|
|
36
|
-
expect(pageSnapshot.pageRef).toBeDefined();
|
|
37
|
-
expect(pageSnapshot.pageRef.position.pageIndex).toBe(i);
|
|
38
|
-
expect(pageSnapshot.elements).toBeDefined();
|
|
39
|
-
expect(Array.isArray(pageSnapshot.elements)).toBe(true);
|
|
40
|
-
}
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
test('get document snapshot with type filter', async () => {
|
|
44
|
-
const [baseUrl, token, pdfData] = await requireEnvAndFixture('ObviouslyAwesome.pdf');
|
|
45
|
-
const client = await PDFDancer.open(pdfData, token, baseUrl);
|
|
46
|
-
|
|
47
|
-
// Get snapshot filtered by paragraphs only
|
|
48
|
-
const snapshot = await client.getDocumentSnapshot([ObjectType.PARAGRAPH]);
|
|
49
|
-
|
|
50
|
-
expect(snapshot).toBeDefined();
|
|
51
|
-
expect(snapshot.pageCount).toBe(12);
|
|
52
|
-
|
|
53
|
-
// Verify all elements are paragraphs
|
|
54
|
-
const allElements = snapshot.getAllElements();
|
|
55
|
-
for (const element of allElements) {
|
|
56
|
-
expect(element.type).toBe(ObjectType.PARAGRAPH);
|
|
57
|
-
}
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
test('get document snapshot with multiple type filters', async () => {
|
|
61
|
-
const [baseUrl, token, pdfData] = await requireEnvAndFixture('ObviouslyAwesome.pdf');
|
|
62
|
-
const client = await PDFDancer.open(pdfData, token, baseUrl);
|
|
63
|
-
|
|
64
|
-
// Get snapshot filtered by paragraphs and images
|
|
65
|
-
const snapshot = await client.getDocumentSnapshot([ObjectType.PARAGRAPH, ObjectType.IMAGE]);
|
|
66
|
-
|
|
67
|
-
expect(snapshot).toBeDefined();
|
|
68
|
-
|
|
69
|
-
// Verify all elements are either paragraphs or images
|
|
70
|
-
const allElements = snapshot.getAllElements();
|
|
71
|
-
for (const element of allElements) {
|
|
72
|
-
expect([ObjectType.PARAGRAPH, ObjectType.IMAGE]).toContain(element.type);
|
|
73
|
-
}
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
test('get page snapshot', async () => {
|
|
77
|
-
const [baseUrl, token, pdfData] = await requireEnvAndFixture('ObviouslyAwesome.pdf');
|
|
78
|
-
const client = await PDFDancer.open(pdfData, token, baseUrl);
|
|
79
|
-
|
|
80
|
-
const pageSnapshot = await client.getPageSnapshot(0);
|
|
81
|
-
|
|
82
|
-
// Verify snapshot structure
|
|
83
|
-
expect(pageSnapshot).toBeDefined();
|
|
84
|
-
expect(pageSnapshot).toBeInstanceOf(PageSnapshot);
|
|
85
|
-
|
|
86
|
-
// Verify page reference
|
|
87
|
-
expect(pageSnapshot.pageRef).toBeDefined();
|
|
88
|
-
expect(pageSnapshot.pageRef.position.pageIndex).toBe(0);
|
|
89
|
-
expect(pageSnapshot.pageRef.type).toBe(ObjectType.PAGE);
|
|
90
|
-
|
|
91
|
-
// Verify elements
|
|
92
|
-
expect(pageSnapshot.elements).toBeDefined();
|
|
93
|
-
expect(Array.isArray(pageSnapshot.elements)).toBe(true);
|
|
94
|
-
expect(pageSnapshot.elements.length).toBeGreaterThan(0);
|
|
95
|
-
|
|
96
|
-
// Verify each element has required properties
|
|
97
|
-
for (const element of pageSnapshot.elements) {
|
|
98
|
-
expect(element.internalId).toBeDefined();
|
|
99
|
-
expect(element.type).toBeDefined();
|
|
100
|
-
expect(element.position).toBeDefined();
|
|
101
|
-
}
|
|
102
|
-
});
|
|
103
|
-
|
|
104
|
-
test('get page snapshot with type filter', async () => {
|
|
105
|
-
const [baseUrl, token, pdfData] = await requireEnvAndFixture('ObviouslyAwesome.pdf');
|
|
106
|
-
const client = await PDFDancer.open(pdfData, token, baseUrl);
|
|
107
|
-
|
|
108
|
-
// Get page snapshot filtered by images only
|
|
109
|
-
const pageSnapshot = await client.getPageSnapshot(0, [ObjectType.IMAGE]);
|
|
110
|
-
|
|
111
|
-
expect(pageSnapshot).toBeDefined();
|
|
112
|
-
|
|
113
|
-
// Verify all elements are images
|
|
114
|
-
for (const element of pageSnapshot.elements) {
|
|
115
|
-
expect(element.type).toBe(ObjectType.IMAGE);
|
|
116
|
-
}
|
|
117
|
-
});
|
|
118
|
-
|
|
119
|
-
test('get page snapshot via PageClient', async () => {
|
|
120
|
-
const [baseUrl, token, pdfData] = await requireEnvAndFixture('ObviouslyAwesome.pdf');
|
|
121
|
-
const client = await PDFDancer.open(pdfData, token, baseUrl);
|
|
122
|
-
|
|
123
|
-
const page = client.page(1);
|
|
124
|
-
const pageSnapshot = await page.getSnapshot();
|
|
125
|
-
|
|
126
|
-
// Verify snapshot structure
|
|
127
|
-
expect(pageSnapshot).toBeDefined();
|
|
128
|
-
expect(pageSnapshot).toBeInstanceOf(PageSnapshot);
|
|
129
|
-
expect(pageSnapshot.pageRef.position.pageIndex).toBe(1);
|
|
130
|
-
expect(pageSnapshot.elements.length).toBeGreaterThan(0);
|
|
131
|
-
});
|
|
132
|
-
|
|
133
|
-
test('get page snapshot via PageClient with type filter', async () => {
|
|
134
|
-
const [baseUrl, token, pdfData] = await requireEnvAndFixture('ObviouslyAwesome.pdf');
|
|
135
|
-
const client = await PDFDancer.open(pdfData, token, baseUrl);
|
|
136
|
-
|
|
137
|
-
const page = client.page(0);
|
|
138
|
-
const pageSnapshot = await page.getSnapshot([ObjectType.PARAGRAPH]);
|
|
139
|
-
|
|
140
|
-
expect(pageSnapshot).toBeDefined();
|
|
141
|
-
|
|
142
|
-
// Verify all elements are paragraphs
|
|
143
|
-
for (const element of pageSnapshot.elements) {
|
|
144
|
-
expect(element.type).toBe(ObjectType.PARAGRAPH);
|
|
145
|
-
}
|
|
146
|
-
});
|
|
147
|
-
|
|
148
|
-
test('DocumentSnapshot helper methods', async () => {
|
|
149
|
-
const [baseUrl, token, pdfData] = await requireEnvAndFixture('ObviouslyAwesome.pdf');
|
|
150
|
-
const client = await PDFDancer.open(pdfData, token, baseUrl);
|
|
151
|
-
|
|
152
|
-
const snapshot = await client.getDocumentSnapshot();
|
|
153
|
-
|
|
154
|
-
// Test getPageSnapshot
|
|
155
|
-
const page0 = snapshot.getPageSnapshot(0);
|
|
156
|
-
expect(page0).toBeDefined();
|
|
157
|
-
expect(page0!.getPageIndex()).toBe(0);
|
|
158
|
-
|
|
159
|
-
const page5 = snapshot.getPageSnapshot(5);
|
|
160
|
-
expect(page5).toBeDefined();
|
|
161
|
-
expect(page5!.getPageIndex()).toBe(5);
|
|
162
|
-
|
|
163
|
-
// Test getAllElements
|
|
164
|
-
const allElements = snapshot.getAllElements();
|
|
165
|
-
expect(allElements.length).toBeGreaterThan(0);
|
|
166
|
-
|
|
167
|
-
// Test getTotalElementCount
|
|
168
|
-
const totalCount = snapshot.getTotalElementCount();
|
|
169
|
-
expect(totalCount).toBe(allElements.length);
|
|
170
|
-
expect(totalCount).toBeGreaterThan(0);
|
|
171
|
-
|
|
172
|
-
// Test getElementsByType
|
|
173
|
-
const paragraphs = snapshot.getElementsByType(ObjectType.PARAGRAPH);
|
|
174
|
-
expect(paragraphs.length).toBeGreaterThan(0);
|
|
175
|
-
for (const para of paragraphs) {
|
|
176
|
-
expect(para.type).toBe(ObjectType.PARAGRAPH);
|
|
177
|
-
}
|
|
178
|
-
});
|
|
179
|
-
|
|
180
|
-
test('PageSnapshot helper methods', async () => {
|
|
181
|
-
const [baseUrl, token, pdfData] = await requireEnvAndFixture('ObviouslyAwesome.pdf');
|
|
182
|
-
const client = await PDFDancer.open(pdfData, token, baseUrl);
|
|
183
|
-
|
|
184
|
-
const pageSnapshot = await client.getPageSnapshot(0);
|
|
185
|
-
|
|
186
|
-
// Test getPageIndex
|
|
187
|
-
expect(pageSnapshot.getPageIndex()).toBe(0);
|
|
188
|
-
|
|
189
|
-
// Test getElementCount
|
|
190
|
-
const elementCount = pageSnapshot.getElementCount();
|
|
191
|
-
expect(elementCount).toBe(pageSnapshot.elements.length);
|
|
192
|
-
expect(elementCount).toBeGreaterThan(0);
|
|
193
|
-
|
|
194
|
-
// Test getElementsByType
|
|
195
|
-
const paragraphs = pageSnapshot.getElementsByType(ObjectType.PARAGRAPH);
|
|
196
|
-
for (const para of paragraphs) {
|
|
197
|
-
expect(para.type).toBe(ObjectType.PARAGRAPH);
|
|
198
|
-
}
|
|
199
|
-
});
|
|
200
|
-
|
|
201
|
-
test('snapshot with form fields', async () => {
|
|
202
|
-
const [baseUrl, token, pdfData] = await requireEnvAndFixture('mixed-form-types.pdf');
|
|
203
|
-
const client = await PDFDancer.open(pdfData, token, baseUrl);
|
|
204
|
-
|
|
205
|
-
// Form fields can be TEXT_FIELD, CHECKBOX, or RADIO_BUTTON
|
|
206
|
-
const snapshot = await client.getDocumentSnapshot([
|
|
207
|
-
ObjectType.TEXT_FIELD,
|
|
208
|
-
ObjectType.CHECKBOX,
|
|
209
|
-
ObjectType.RADIO_BUTTON
|
|
210
|
-
]);
|
|
211
|
-
|
|
212
|
-
expect(snapshot).toBeDefined();
|
|
213
|
-
|
|
214
|
-
// Get all form field types
|
|
215
|
-
const allFormFields = snapshot.getAllElements();
|
|
216
|
-
expect(allFormFields.length).toBeGreaterThan(0);
|
|
217
|
-
|
|
218
|
-
// Verify they are all form field types
|
|
219
|
-
const formFieldTypes = [ObjectType.TEXT_FIELD, ObjectType.CHECKBOX, ObjectType.RADIO_BUTTON];
|
|
220
|
-
for (const field of allFormFields) {
|
|
221
|
-
expect(formFieldTypes).toContain(field.type);
|
|
222
|
-
}
|
|
223
|
-
});
|
|
224
|
-
|
|
225
|
-
test('snapshot with paths', async () => {
|
|
226
|
-
const [baseUrl, token, pdfData] = await requireEnvAndFixture('basic-paths.pdf');
|
|
227
|
-
const client = await PDFDancer.open(pdfData, token, baseUrl);
|
|
228
|
-
|
|
229
|
-
const snapshot = await client.getDocumentSnapshot([ObjectType.PATH]);
|
|
230
|
-
|
|
231
|
-
expect(snapshot).toBeDefined();
|
|
232
|
-
|
|
233
|
-
// Get all paths
|
|
234
|
-
const paths = snapshot.getElementsByType(ObjectType.PATH);
|
|
235
|
-
expect(paths.length).toBeGreaterThan(0);
|
|
236
|
-
|
|
237
|
-
// Verify they are all paths
|
|
238
|
-
for (const path of paths) {
|
|
239
|
-
expect(path.type).toBe(ObjectType.PATH);
|
|
240
|
-
}
|
|
241
|
-
});
|
|
242
|
-
|
|
243
|
-
test('compare snapshot with individual find operations', async () => {
|
|
244
|
-
const [baseUrl, token, pdfData] = await requireEnvAndFixture('ObviouslyAwesome.pdf');
|
|
245
|
-
const client = await PDFDancer.open(pdfData, token, baseUrl);
|
|
246
|
-
|
|
247
|
-
// Get snapshot
|
|
248
|
-
const snapshot = await client.getPageSnapshot(0);
|
|
249
|
-
const snapshotParagraphs = snapshot.getElementsByType(ObjectType.PARAGRAPH);
|
|
250
|
-
|
|
251
|
-
// Get paragraphs via page client
|
|
252
|
-
const page = client.page(0);
|
|
253
|
-
const paragraphs = await page.selectParagraphs();
|
|
254
|
-
|
|
255
|
-
// Should have same count
|
|
256
|
-
expect(snapshotParagraphs.length).toBe(paragraphs.length);
|
|
257
|
-
});
|
|
258
|
-
|
|
259
|
-
test('snapshot fonts information', async () => {
|
|
260
|
-
const [baseUrl, token, pdfData] = await requireEnvAndFixture('ObviouslyAwesome.pdf');
|
|
261
|
-
const client = await PDFDancer.open(pdfData, token, baseUrl);
|
|
262
|
-
|
|
263
|
-
const snapshot = await client.getDocumentSnapshot();
|
|
264
|
-
|
|
265
|
-
// Verify fonts array
|
|
266
|
-
expect(snapshot.fonts).toBeDefined();
|
|
267
|
-
expect(Array.isArray(snapshot.fonts)).toBe(true);
|
|
268
|
-
|
|
269
|
-
// If there are fonts, verify their structure
|
|
270
|
-
if (snapshot.fonts.length > 0) {
|
|
271
|
-
for (const font of snapshot.fonts) {
|
|
272
|
-
expect(font.documentFontName).toBeDefined();
|
|
273
|
-
expect(font.systemFontName).toBeDefined();
|
|
274
|
-
expect(typeof font.documentFontName).toBe('string');
|
|
275
|
-
expect(typeof font.systemFontName).toBe('string');
|
|
276
|
-
}
|
|
277
|
-
}
|
|
278
|
-
});
|
|
279
|
-
|
|
280
|
-
test('snapshot on empty page', async () => {
|
|
281
|
-
const [baseUrl, token, pdfData] = await requireEnvAndFixture('Empty.pdf');
|
|
282
|
-
const client = await PDFDancer.open(pdfData, token, baseUrl);
|
|
283
|
-
|
|
284
|
-
const snapshot = await client.getDocumentSnapshot();
|
|
285
|
-
|
|
286
|
-
expect(snapshot).toBeDefined();
|
|
287
|
-
expect(snapshot.pageCount).toBeGreaterThan(0);
|
|
288
|
-
expect(snapshot.pages.length).toBeGreaterThan(0);
|
|
289
|
-
|
|
290
|
-
// Empty pages might have no elements
|
|
291
|
-
const page0Snapshot = snapshot.getPageSnapshot(0);
|
|
292
|
-
expect(page0Snapshot).toBeDefined();
|
|
293
|
-
expect(page0Snapshot!.elements).toBeDefined();
|
|
294
|
-
expect(Array.isArray(page0Snapshot!.elements)).toBe(true);
|
|
295
|
-
});
|
|
296
|
-
});
|
|
@@ -1,152 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Helper functions for e2e tests
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import * as fs from 'fs';
|
|
6
|
-
import * as path from 'path';
|
|
7
|
-
import os from "os";
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Get the base URL from environment variable or default
|
|
11
|
-
*/
|
|
12
|
-
export function getBaseUrl(): string {
|
|
13
|
-
return (process.env.PDFDANCER_BASE_URL || 'http://localhost:8080').trim();
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* Read authentication token from environment or token files
|
|
18
|
-
*/
|
|
19
|
-
export function readToken(): string | null {
|
|
20
|
-
const token = process.env.PDFDANCER_TOKEN;
|
|
21
|
-
if (token) {
|
|
22
|
-
return token.trim();
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
// Try common token files in project root
|
|
26
|
-
const projectRoot = path.resolve(__dirname, '../../..');
|
|
27
|
-
const candidates = findFiles(projectRoot, 'jwt-token-*.txt');
|
|
28
|
-
|
|
29
|
-
for (const file of candidates) {
|
|
30
|
-
try {
|
|
31
|
-
return fs.readFileSync(file, 'utf-8').trim();
|
|
32
|
-
} catch {
|
|
33
|
-
continue;
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
return null;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* Check if server is up and running
|
|
42
|
-
*/
|
|
43
|
-
export async function serverUp(baseUrl: string): Promise<boolean> {
|
|
44
|
-
try {
|
|
45
|
-
const response = await fetch(`${baseUrl}/ping`, {
|
|
46
|
-
signal: AbortSignal.timeout(60000)
|
|
47
|
-
});
|
|
48
|
-
const text = await response.text();
|
|
49
|
-
let pongReceived = response.status === 200 && text.includes('Pong');
|
|
50
|
-
if (!pongReceived) {
|
|
51
|
-
console.error(`Server did not respond with Pong. Response: ${text}, status ${response.status}`);
|
|
52
|
-
}
|
|
53
|
-
return pongReceived;
|
|
54
|
-
} catch (e) {
|
|
55
|
-
console.error("Server down", e)
|
|
56
|
-
return false;
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
/**
|
|
61
|
-
* Helper to find files matching a pattern
|
|
62
|
-
*/
|
|
63
|
-
function findFiles(dir: string, pattern: string): string[] {
|
|
64
|
-
try {
|
|
65
|
-
const files = fs.readdirSync(dir);
|
|
66
|
-
const regex = new RegExp(pattern.replace('*', '.*'));
|
|
67
|
-
return files
|
|
68
|
-
.filter(file => regex.test(file))
|
|
69
|
-
.map(file => path.join(dir, file));
|
|
70
|
-
} catch {
|
|
71
|
-
return [];
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
/**
|
|
76
|
-
* Require environment variables and PDF fixture for testing
|
|
77
|
-
*/
|
|
78
|
-
export async function requireEnvAndFixture(pdfFilename: string): Promise<[string, string, Uint8Array]> {
|
|
79
|
-
const baseUrl = getBaseUrl();
|
|
80
|
-
const token = readToken();
|
|
81
|
-
|
|
82
|
-
if (!await serverUp(baseUrl)) {
|
|
83
|
-
throw new Error(`PDFDancer server not reachable at ${baseUrl}; set PDFDANCER_BASE_URL or start server`);
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
if (!token) {
|
|
87
|
-
throw new Error('PDFDANCER_TOKEN not set and no token file found; set env or place jwt-token-*.txt in repo');
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
// Look for PDF fixture file
|
|
91
|
-
const fixturesDir = path.resolve(__dirname, '../../../fixtures');
|
|
92
|
-
const pdfPath = path.join(fixturesDir, pdfFilename);
|
|
93
|
-
|
|
94
|
-
if (!fs.existsSync(pdfPath)) {
|
|
95
|
-
throw new Error(`${pdfFilename} fixture not found at ${pdfPath}`);
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
const pdfData = fs.readFileSync(pdfPath);
|
|
99
|
-
return [baseUrl, token, new Uint8Array(pdfData)];
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
/**
|
|
103
|
-
* Helper to open temporary file path (for Node.js environment)
|
|
104
|
-
*/
|
|
105
|
-
export function createTempPath(filename: string): string {
|
|
106
|
-
const tmpDir =
|
|
107
|
-
process.env.TMPDIR ||
|
|
108
|
-
process.env.TEMP ||
|
|
109
|
-
process.env.TMP ||
|
|
110
|
-
os.tmpdir(); // reliable built-in fallback
|
|
111
|
-
|
|
112
|
-
return path.join(tmpDir, filename);
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
/**
|
|
116
|
-
* Helper to read image file for tests
|
|
117
|
-
*/
|
|
118
|
-
export function readImageFixture(filename: string): Uint8Array {
|
|
119
|
-
const imagePath = getImagePath(filename);
|
|
120
|
-
|
|
121
|
-
if (!fs.existsSync(imagePath)) {
|
|
122
|
-
throw new Error(`Image fixture not found: ${filename}`);
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
const imageData = fs.readFileSync(imagePath);
|
|
126
|
-
return new Uint8Array(imageData);
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
export function getImagePath(filename: string): string {
|
|
130
|
-
const fixturesDir = path.resolve(__dirname, '../../../fixtures');
|
|
131
|
-
return path.join(fixturesDir, filename);
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
export function getFontPath(filename: string) {
|
|
135
|
-
const fixturesDir = path.resolve(__dirname, '../../../fixtures');
|
|
136
|
-
const fontPath = path.join(fixturesDir, filename);
|
|
137
|
-
return fontPath;
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
/**
|
|
141
|
-
* Helper to read font file for tests
|
|
142
|
-
*/
|
|
143
|
-
export function readFontFixture(filename: string): Uint8Array {
|
|
144
|
-
const fontPath = getFontPath(filename);
|
|
145
|
-
|
|
146
|
-
if (!fs.existsSync(fontPath)) {
|
|
147
|
-
throw new Error(`Font fixture not found: ${filename}`);
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
const fontData = fs.readFileSync(fontPath);
|
|
151
|
-
return new Uint8Array(fontData);
|
|
152
|
-
}
|
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
import {requireEnvAndFixture} from "./test-helpers";
|
|
2
|
-
import {PDFDancer} from "../../pdfdancer_v1";
|
|
3
|
-
import {HttpClientException, ValidationException} from "../../exceptions";
|
|
4
|
-
|
|
5
|
-
describe('Env Token E2E Tests', () => {
|
|
6
|
-
let originalToken: string | undefined;
|
|
7
|
-
let originalBaseUrl: string | undefined;
|
|
8
|
-
let baseUrl: string;
|
|
9
|
-
let pdfData: Uint8Array;
|
|
10
|
-
let validToken: string;
|
|
11
|
-
|
|
12
|
-
const restoreEnv = () => {
|
|
13
|
-
if (originalToken !== undefined) {
|
|
14
|
-
process.env.PDFDANCER_TOKEN = originalToken;
|
|
15
|
-
} else {
|
|
16
|
-
delete process.env.PDFDANCER_TOKEN;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
if (originalBaseUrl !== undefined) {
|
|
20
|
-
process.env.PDFDANCER_BASE_URL = originalBaseUrl;
|
|
21
|
-
} else {
|
|
22
|
-
delete process.env.PDFDANCER_BASE_URL;
|
|
23
|
-
}
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
beforeAll(async () => {
|
|
27
|
-
originalToken = process.env.PDFDANCER_TOKEN;
|
|
28
|
-
originalBaseUrl = process.env.PDFDANCER_BASE_URL;
|
|
29
|
-
|
|
30
|
-
[baseUrl, validToken, pdfData] = await requireEnvAndFixture('ObviouslyAwesome.pdf');
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
beforeEach(() => {
|
|
34
|
-
restoreEnv();
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
afterEach(() => {
|
|
38
|
-
restoreEnv();
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
afterAll(() => {
|
|
42
|
-
restoreEnv();
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
test('opens with token from env', async () => {
|
|
46
|
-
process.env.PDFDANCER_TOKEN = validToken;
|
|
47
|
-
const client = await PDFDancer.open(pdfData, undefined, baseUrl);
|
|
48
|
-
expect(client).toBeInstanceOf(PDFDancer);
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
test('fails with unreachable base url', async () => {
|
|
52
|
-
process.env.PDFDANCER_TOKEN = validToken;
|
|
53
|
-
process.env.PDFDANCER_BASE_URL = "http://www.google.com";
|
|
54
|
-
|
|
55
|
-
await expect(async () => {
|
|
56
|
-
try {
|
|
57
|
-
await PDFDancer.open(pdfData);
|
|
58
|
-
} catch (error) {
|
|
59
|
-
expect(error).toBeInstanceOf(HttpClientException);
|
|
60
|
-
throw error;
|
|
61
|
-
}
|
|
62
|
-
}).rejects.toThrow(HttpClientException);
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
test('fails with invalid token', async () => {
|
|
66
|
-
process.env.PDFDANCER_TOKEN = "invalid-token";
|
|
67
|
-
process.env.PDFDANCER_BASE_URL = "https://api.pdfdancer.com";
|
|
68
|
-
|
|
69
|
-
await expect(async () => {
|
|
70
|
-
try {
|
|
71
|
-
await PDFDancer.open(pdfData);
|
|
72
|
-
} catch (error) {
|
|
73
|
-
expect(error).toBeInstanceOf(ValidationException);
|
|
74
|
-
expect((error as Error).message)
|
|
75
|
-
.toContain("Authentication with the PDFDancer API failed. Confirm that your API token is valid, has not expired");
|
|
76
|
-
throw error;
|
|
77
|
-
}
|
|
78
|
-
}).rejects.toThrow(ValidationException);
|
|
79
|
-
});
|
|
80
|
-
});
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Tests for fingerprint generation
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import {generateFingerprint} from '../fingerprint';
|
|
6
|
-
|
|
7
|
-
describe('Fingerprint', () => {
|
|
8
|
-
it('should generate a valid SHA256 fingerprint', async () => {
|
|
9
|
-
const fingerprint = await generateFingerprint();
|
|
10
|
-
|
|
11
|
-
// SHA256 produces 64 hex characters
|
|
12
|
-
expect(fingerprint).toHaveLength(64);
|
|
13
|
-
expect(fingerprint).toMatch(/^[a-f0-9]{64}$/);
|
|
14
|
-
});
|
|
15
|
-
|
|
16
|
-
it('should generate different fingerprints for different user IDs', async () => {
|
|
17
|
-
const fingerprint1 = await generateFingerprint('user1');
|
|
18
|
-
const fingerprint2 = await generateFingerprint('user2');
|
|
19
|
-
|
|
20
|
-
expect(fingerprint1).not.toBe(fingerprint2);
|
|
21
|
-
expect(fingerprint1).toHaveLength(64);
|
|
22
|
-
expect(fingerprint2).toHaveLength(64);
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
it('should generate consistent fingerprints for same user ID', async () => {
|
|
26
|
-
const fingerprint1 = await generateFingerprint('user123');
|
|
27
|
-
const fingerprint2 = await generateFingerprint('user123');
|
|
28
|
-
|
|
29
|
-
// Note: These might differ due to install salt randomness in test environment
|
|
30
|
-
// but they should both be valid SHA256 hashes
|
|
31
|
-
expect(fingerprint1).toHaveLength(64);
|
|
32
|
-
expect(fingerprint2).toHaveLength(64);
|
|
33
|
-
expect(fingerprint1).toMatch(/^[a-f0-9]{64}$/);
|
|
34
|
-
expect(fingerprint2).toMatch(/^[a-f0-9]{64}$/);
|
|
35
|
-
});
|
|
36
|
-
});
|