pdfdancer-client-typescript 1.0.13 → 1.0.15

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.
Files changed (45) hide show
  1. package/.eslintrc.js +26 -18
  2. package/.github/workflows/ci.yml +51 -2
  3. package/.github/workflows/daily-tests.yml +54 -0
  4. package/README.md +50 -6
  5. package/dist/__tests__/e2e/test-helpers.d.ts.map +1 -1
  6. package/dist/__tests__/e2e/test-helpers.js +17 -5
  7. package/dist/__tests__/e2e/test-helpers.js.map +1 -1
  8. package/dist/fingerprint.d.ts.map +1 -1
  9. package/dist/fingerprint.js +16 -5
  10. package/dist/fingerprint.js.map +1 -1
  11. package/dist/index.d.ts +2 -1
  12. package/dist/index.d.ts.map +1 -1
  13. package/dist/index.js +4 -2
  14. package/dist/index.js.map +1 -1
  15. package/dist/models.d.ts +18 -15
  16. package/dist/models.d.ts.map +1 -1
  17. package/dist/models.js +21 -18
  18. package/dist/models.js.map +1 -1
  19. package/dist/pdfdancer_v1.d.ts +71 -3
  20. package/dist/pdfdancer_v1.d.ts.map +1 -1
  21. package/dist/pdfdancer_v1.js +301 -35
  22. package/dist/pdfdancer_v1.js.map +1 -1
  23. package/docs/openapi.yml +637 -73
  24. package/jest.config.js +1 -1
  25. package/package.json +2 -2
  26. package/src/__tests__/e2e/acroform.test.ts +58 -0
  27. package/src/__tests__/e2e/form_x_object.test.ts +29 -0
  28. package/src/__tests__/e2e/image-showcase.test.ts +6 -6
  29. package/src/__tests__/e2e/image.test.ts +39 -5
  30. package/src/__tests__/e2e/line-showcase.test.ts +6 -11
  31. package/src/__tests__/e2e/line.test.ts +63 -7
  32. package/src/__tests__/e2e/page-showcase.test.ts +12 -12
  33. package/src/__tests__/e2e/page.test.ts +3 -3
  34. package/src/__tests__/e2e/paragraph-showcase.test.ts +0 -8
  35. package/src/__tests__/e2e/paragraph.test.ts +64 -8
  36. package/src/__tests__/e2e/path.test.ts +33 -4
  37. package/src/__tests__/e2e/snapshot-showcase.test.ts +10 -10
  38. package/src/__tests__/e2e/snapshot.test.ts +18 -18
  39. package/src/__tests__/e2e/test-helpers.ts +16 -5
  40. package/src/__tests__/e2e/token_from_env.test.ts +0 -15
  41. package/src/__tests__/retry-mechanism.test.ts +420 -0
  42. package/src/fingerprint.ts +20 -7
  43. package/src/index.ts +3 -1
  44. package/src/models.ts +21 -17
  45. package/src/pdfdancer_v1.ts +467 -71
package/jest.config.js CHANGED
@@ -1,7 +1,7 @@
1
1
  module.exports = {
2
2
  preset: 'ts-jest',
3
3
  testEnvironment: 'node',
4
- testTimeout: 60000,
4
+ testTimeout: 120000,
5
5
  roots: ['<rootDir>/src'],
6
6
  testMatch: ['**/__tests__/**/*.ts', '**/?(*.)+(spec|test).ts'],
7
7
  collectCoverageFrom: [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pdfdancer-client-typescript",
3
- "version": "1.0.13",
3
+ "version": "1.0.15",
4
4
  "description": "A TypeScript client library for the PDFDancer PDF manipulation API",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -10,7 +10,7 @@
10
10
  "test:unit": "jest --selectProjects unit",
11
11
  "test:e2e": "jest --selectProjects e2e",
12
12
  "test:watch": "jest --watch",
13
- "lint": "eslint src/**/*.ts",
13
+ "lint": "eslint src/",
14
14
  "prepublishOnly": "npm run build",
15
15
  "release": "node scripts/release.js",
16
16
  "release:skip-tests": "node scripts/release.js --skip-tests",
@@ -105,4 +105,62 @@ describe('AcroForm Fields E2E Tests (v2 API)', () => {
105
105
  const assertions = await PDFAssertions.create(pdf);
106
106
  await assertions.assertNumberOfFormFields(10);
107
107
  });
108
+
109
+ // Tests for singular select methods
110
+ test('selectFormField returns first field or null', async () => {
111
+ const [baseUrl, token, pdfData] = await requireEnvAndFixture('mixed-form-types.pdf');
112
+ const pdf = await PDFDancer.open(pdfData, token, baseUrl);
113
+
114
+ // Test with results
115
+ const field = await pdf.page(0).selectFormField();
116
+ expect(field).not.toBeNull();
117
+ expect(field!.internalId).toBe('FORM_FIELD_000001');
118
+
119
+ // Test with PDFDancer class
120
+ const fieldFromPdf = await pdf.selectFormField();
121
+ expect(fieldFromPdf).not.toBeNull();
122
+ expect(fieldFromPdf!.internalId).toBe('FORM_FIELD_000001');
123
+ });
124
+
125
+ test('selectFormFieldByName returns first field by name or null', async () => {
126
+ const [baseUrl, token, pdfData] = await requireEnvAndFixture('mixed-form-types.pdf');
127
+ const pdf = await PDFDancer.open(pdfData, token, baseUrl);
128
+
129
+ const field = await pdf.page(0).selectFormFieldByName('firstName');
130
+ expect(field).not.toBeNull();
131
+ expect(field!.name).toBe('firstName');
132
+ expect(field!.internalId).toBe('FORM_FIELD_000001');
133
+
134
+ // Test with no match
135
+ const noMatch = await pdf.page(0).selectFormFieldByName('nonExistent');
136
+ expect(noMatch).toBeNull();
137
+ });
138
+
139
+ test('selectFieldByName returns first field by name or null', async () => {
140
+ const [baseUrl, token, pdfData] = await requireEnvAndFixture('mixed-form-types.pdf');
141
+ const pdf = await PDFDancer.open(pdfData, token, baseUrl);
142
+
143
+ const field = await pdf.selectFieldByName('firstName');
144
+ expect(field).not.toBeNull();
145
+ expect(field!.name).toBe('firstName');
146
+ expect(field!.internalId).toBe('FORM_FIELD_000001');
147
+
148
+ // Test with no match
149
+ const noMatch = await pdf.selectFieldByName('nonExistent');
150
+ expect(noMatch).toBeNull();
151
+ });
152
+
153
+ test('selectFormFieldAt returns first field at position or null', async () => {
154
+ const [baseUrl, token, pdfData] = await requireEnvAndFixture('mixed-form-types.pdf');
155
+ const pdf = await PDFDancer.open(pdfData, token, baseUrl);
156
+
157
+ const field = await pdf.page(0).selectFormFieldAt(280, 455, 1);
158
+ expect(field).not.toBeNull();
159
+ expect(field!.type).toBe('RADIO_BUTTON');
160
+ expect(field!.internalId).toBe('FORM_FIELD_000008');
161
+
162
+ // Test with no match
163
+ const noMatch = await pdf.page(0).selectFormFieldAt(1000, 1000, 1);
164
+ expect(noMatch).toBeNull();
165
+ });
108
166
  });
@@ -55,4 +55,33 @@ describe('Form E2E Tests (v2 API)', () => {
55
55
  const assertions = await PDFAssertions.create(pdf);
56
56
  await assertions.assertNumberOfFormXObjects(0);
57
57
  });
58
+
59
+ // Tests for singular select methods
60
+ test('selectForm returns first form or null', async () => {
61
+ const [baseUrl, token, pdfData] = await requireEnvAndFixture('form-xobject-example.pdf');
62
+ const pdf = await PDFDancer.open(pdfData, token, baseUrl);
63
+
64
+ // Test with results
65
+ const form = await pdf.page(0).selectForm();
66
+ expect(form).not.toBeNull();
67
+ expect(form!.internalId).toBe('FORM_000001');
68
+
69
+ // Test with PDFDancer class
70
+ const formFromPdf = await pdf.selectForm();
71
+ expect(formFromPdf).not.toBeNull();
72
+ expect(formFromPdf!.internalId).toBe('FORM_000001');
73
+ });
74
+
75
+ test('selectFormAt returns first form at position or null', async () => {
76
+ const [baseUrl, token, pdfData] = await requireEnvAndFixture('form-xobject-example.pdf');
77
+ const pdf = await PDFDancer.open(pdfData, token, baseUrl);
78
+
79
+ const form = await pdf.page(0).selectFormAt(321, 601, 1);
80
+ expect(form).not.toBeNull();
81
+ expect(form!.internalId).toBe('FORM_000005');
82
+
83
+ // Test with no match
84
+ const noMatch = await pdf.page(0).selectFormAt(0, 0);
85
+ expect(noMatch).toBeNull();
86
+ });
58
87
  });
@@ -6,7 +6,7 @@ import {PDFAssertions} from './pdf-assertions';
6
6
  describe('Image E2E Tests (Showcase)', () => {
7
7
  test('find images', async () => {
8
8
  const [baseUrl, token, pdfData] = await requireEnvAndFixture('Showcase.pdf');
9
- const pdf = await PDFDancer.open(pdfData, token, baseUrl, 30000);
9
+ const pdf = await PDFDancer.open(pdfData, token, baseUrl);
10
10
 
11
11
  const images = await pdf.selectImages();
12
12
  expect(images.length).toBe(12);
@@ -18,7 +18,7 @@ describe('Image E2E Tests (Showcase)', () => {
18
18
 
19
19
  test('delete all images', async () => {
20
20
  const [baseUrl, token, pdfData] = await requireEnvAndFixture('Showcase.pdf');
21
- const pdf = await PDFDancer.open(pdfData, token, baseUrl, 30000);
21
+ const pdf = await PDFDancer.open(pdfData, token, baseUrl);
22
22
 
23
23
  const images = await pdf.selectImages();
24
24
  expect(images.length).toBe(12);
@@ -36,7 +36,7 @@ describe('Image E2E Tests (Showcase)', () => {
36
36
 
37
37
  test('move image', async () => {
38
38
  const [baseUrl, token, pdfData] = await requireEnvAndFixture('Showcase.pdf');
39
- const pdf = await PDFDancer.open(pdfData, token, baseUrl, 30000);
39
+ const pdf = await PDFDancer.open(pdfData, token, baseUrl);
40
40
 
41
41
  const images = await pdf.selectImages();
42
42
  const image = images[10];
@@ -61,7 +61,7 @@ describe('Image E2E Tests (Showcase)', () => {
61
61
 
62
62
  test('find image by position', async () => {
63
63
  const [baseUrl, token, pdfData] = await requireEnvAndFixture('Showcase.pdf');
64
- const pdf = await PDFDancer.open(pdfData, token, baseUrl, 30000);
64
+ const pdf = await PDFDancer.open(pdfData, token, baseUrl);
65
65
 
66
66
  const none = await pdf.page(5).selectImagesAt(0, 0);
67
67
  expect(none.length).toBe(0);
@@ -73,7 +73,7 @@ describe('Image E2E Tests (Showcase)', () => {
73
73
 
74
74
  test('add image via document builder', async () => {
75
75
  const [baseUrl, token, pdfData] = await requireEnvAndFixture('Showcase.pdf');
76
- const pdf = await PDFDancer.open(pdfData, token, baseUrl, 30000);
76
+ const pdf = await PDFDancer.open(pdfData, token, baseUrl);
77
77
 
78
78
  expect(await pdf.selectImages()).toHaveLength(12);
79
79
  expect(await pdf.page(6).selectImages()).toHaveLength(1);
@@ -103,7 +103,7 @@ describe('Image E2E Tests (Showcase)', () => {
103
103
 
104
104
  test('add image via page builder', async () => {
105
105
  const [baseUrl, token, pdfData] = await requireEnvAndFixture('Showcase.pdf');
106
- const pdf = await PDFDancer.open(pdfData, token, baseUrl, 30000);
106
+ const pdf = await PDFDancer.open(pdfData, token, baseUrl);
107
107
 
108
108
  expect(await pdf.selectImages()).toHaveLength(12);
109
109
  expect(await pdf.page(6).selectImages()).toHaveLength(1);
@@ -12,7 +12,7 @@ describe('Image E2E Tests (v2 API)', () => {
12
12
 
13
13
  test('find images', async () => {
14
14
  const [baseUrl, token, pdfData] = await requireEnvAndFixture('ObviouslyAwesome.pdf');
15
- const pdf = await PDFDancer.open(pdfData, token, baseUrl, 30000);
15
+ const pdf = await PDFDancer.open(pdfData, token, baseUrl);
16
16
 
17
17
  const images = await pdf.selectImages();
18
18
  expect(images).toHaveLength(3);
@@ -24,7 +24,7 @@ describe('Image E2E Tests (v2 API)', () => {
24
24
 
25
25
  test('delete images', async () => {
26
26
  const [baseUrl, token, pdfData] = await requireEnvAndFixture('ObviouslyAwesome.pdf');
27
- const pdf = await PDFDancer.open(pdfData, token, baseUrl, 30000);
27
+ const pdf = await PDFDancer.open(pdfData, token, baseUrl);
28
28
 
29
29
  const images = await pdf.selectImages();
30
30
  expect(images).toHaveLength(3);
@@ -50,7 +50,7 @@ describe('Image E2E Tests (v2 API)', () => {
50
50
 
51
51
  test('move image', async () => {
52
52
  const [baseUrl, token, pdfData] = await requireEnvAndFixture('ObviouslyAwesome.pdf');
53
- const pdf = await PDFDancer.open(pdfData, token, baseUrl, 30000);
53
+ const pdf = await PDFDancer.open(pdfData, token, baseUrl);
54
54
 
55
55
  const images = await pdf.selectImages();
56
56
  const image = images[2];
@@ -79,7 +79,7 @@ describe('Image E2E Tests (v2 API)', () => {
79
79
 
80
80
  test('find image by position', async () => {
81
81
  const [baseUrl, token, pdfData] = await requireEnvAndFixture('ObviouslyAwesome.pdf');
82
- const pdf = await PDFDancer.open(pdfData, token, baseUrl, 30000);
82
+ const pdf = await PDFDancer.open(pdfData, token, baseUrl);
83
83
 
84
84
  const none = await pdf.page(11).selectImagesAt(0, 0);
85
85
  expect(none).toHaveLength(0);
@@ -91,7 +91,7 @@ describe('Image E2E Tests (v2 API)', () => {
91
91
 
92
92
  test('add image', async () => {
93
93
  const [baseUrl, token, pdfData] = await requireEnvAndFixture('ObviouslyAwesome.pdf');
94
- const pdf = await PDFDancer.open(pdfData, token, baseUrl, 30000);
94
+ const pdf = await PDFDancer.open(pdfData, token, baseUrl);
95
95
 
96
96
  const before = await pdf.selectImages();
97
97
  expect(before).toHaveLength(3);
@@ -110,4 +110,38 @@ describe('Image E2E Tests (v2 API)', () => {
110
110
  await assertions.assertImageAt(50.1, 98.0, 6);
111
111
  await assertions.assertNumberOfImages(1, 6);
112
112
  });
113
+
114
+ // Tests for singular select methods
115
+ test('selectImage returns first image or null', async () => {
116
+ const [baseUrl, token, pdfData] = await requireEnvAndFixture('ObviouslyAwesome.pdf');
117
+ const pdf = await PDFDancer.open(pdfData, token, baseUrl);
118
+
119
+ // Test with results - page 11 has images
120
+ const image = await pdf.page(11).selectImage();
121
+ expect(image).not.toBeNull();
122
+ expect(image!.internalId).toBe('IMAGE_000003');
123
+
124
+ // Test with PDFDancer class
125
+ const imageFromPdf = await pdf.selectImage();
126
+ expect(imageFromPdf).not.toBeNull();
127
+ expect(imageFromPdf!.internalId).toBe('IMAGE_000001');
128
+
129
+ // Test page 0 also has images (2 images)
130
+ const imageOnPage0 = await pdf.page(0).selectImage();
131
+ expect(imageOnPage0).not.toBeNull();
132
+ expect(imageOnPage0!.internalId).toBe('IMAGE_000001');
133
+ });
134
+
135
+ test('selectImageAt returns first image at position or null', async () => {
136
+ const [baseUrl, token, pdfData] = await requireEnvAndFixture('ObviouslyAwesome.pdf');
137
+ const pdf = await PDFDancer.open(pdfData, token, baseUrl);
138
+
139
+ const image = await pdf.page(11).selectImageAt(54, 300, 1);
140
+ expect(image).not.toBeNull();
141
+ expect(image!.internalId).toBe('IMAGE_000003');
142
+
143
+ // Test with no match
144
+ const noMatch = await pdf.page(11).selectImageAt(0, 0);
145
+ expect(noMatch).toBeNull();
146
+ });
113
147
  });
@@ -7,7 +7,7 @@ const SAMPLE_PARAGRAPH = 'This is regular Sans text showing alignment and styles
7
7
  describe('Text Line E2E Tests (Showcase)', () => {
8
8
  test('find lines by position multi', async () => {
9
9
  const [baseUrl, token, pdfData] = await requireEnvAndFixture('Showcase.pdf');
10
- const pdf = await PDFDancer.open(pdfData, token, baseUrl, 30000);
10
+ const pdf = await PDFDancer.open(pdfData, token, baseUrl);
11
11
 
12
12
  for (let i = 0; i < 10; i++) {
13
13
  const lines = await pdf.selectTextLines();
@@ -15,14 +15,13 @@ describe('Text Line E2E Tests (Showcase)', () => {
15
15
  const status = line.objectRef().status;
16
16
  expect(status).toBeDefined();
17
17
  expect(status?.isModified()).toBe(false);
18
- expect(status?.isEncodable()).toBe(true);
19
18
  }
20
19
  }
21
20
  });
22
21
 
23
22
  test('find lines by position', async () => {
24
23
  const [baseUrl, token, pdfData] = await requireEnvAndFixture('Showcase.pdf');
25
- const pdf = await PDFDancer.open(pdfData, token, baseUrl, 30000);
24
+ const pdf = await PDFDancer.open(pdfData, token, baseUrl);
26
25
 
27
26
  const lines = await pdf.selectTextLines();
28
27
  expect(lines.length).toBe(36);
@@ -33,19 +32,17 @@ describe('Text Line E2E Tests (Showcase)', () => {
33
32
  expect(Math.abs(first.position.getX()! - 180)).toBeLessThanOrEqual(1);
34
33
  expect(Math.abs(first.position.getY()! - 750)).toBeLessThanOrEqual(1);
35
34
  expect(first.objectRef().status?.isModified()).toBe(false);
36
- expect(first.objectRef().status?.isEncodable()).toBe(true);
37
35
 
38
36
  const last = lines[lines.length - 1];
39
37
  expect(last.internalId).toBe('TEXTLINE_000036');
40
38
  expect(Math.abs(last.position.getX()! - 69.3)).toBeLessThanOrEqual(2);
41
39
  expect(Math.abs(last.position.getY()! - 45)).toBeLessThanOrEqual(2);
42
40
  expect(last.objectRef().status?.isModified()).toBe(false);
43
- expect(last.objectRef().status?.isEncodable()).toBe(true);
44
41
  });
45
42
 
46
43
  test('find lines by text', async () => {
47
44
  const [baseUrl, token, pdfData] = await requireEnvAndFixture('Showcase.pdf');
48
- const pdf = await PDFDancer.open(pdfData, token, baseUrl, 30000);
45
+ const pdf = await PDFDancer.open(pdfData, token, baseUrl);
49
46
 
50
47
  const lines = await pdf.page(0).selectTextLinesStartingWith(SAMPLE_PARAGRAPH);
51
48
  expect(lines.length).toBe(1);
@@ -58,7 +55,7 @@ describe('Text Line E2E Tests (Showcase)', () => {
58
55
 
59
56
  test('delete line', async () => {
60
57
  const [baseUrl, token, pdfData] = await requireEnvAndFixture('Showcase.pdf');
61
- const pdf = await PDFDancer.open(pdfData, token, baseUrl, 30000);
58
+ const pdf = await PDFDancer.open(pdfData, token, baseUrl);
62
59
 
63
60
  const [line] = await pdf.page(0).selectTextLinesStartingWith(SAMPLE_PARAGRAPH);
64
61
  await line.delete();
@@ -72,7 +69,7 @@ describe('Text Line E2E Tests (Showcase)', () => {
72
69
 
73
70
  test('move line', async () => {
74
71
  const [baseUrl, token, pdfData] = await requireEnvAndFixture('Showcase.pdf');
75
- const pdf = await PDFDancer.open(pdfData, token, baseUrl, 30000);
72
+ const pdf = await PDFDancer.open(pdfData, token, baseUrl);
76
73
 
77
74
  const [line] = await pdf.page(0).selectTextLinesStartingWith(SAMPLE_PARAGRAPH);
78
75
  const pos = line.position;
@@ -84,7 +81,6 @@ describe('Text Line E2E Tests (Showcase)', () => {
84
81
  const moved = (await pdf.page(0).selectTextLinesAt(newX, newY, 1))[0];
85
82
  const status = moved.objectRef().status;
86
83
  expect(status).toBeDefined();
87
- expect(status?.isEncodable()).toBe(true);
88
84
  expect(status?.getFontType()).toBe(FontType.EMBEDDED);
89
85
  expect(status?.isModified()).toBe(false);
90
86
 
@@ -94,7 +90,7 @@ describe('Text Line E2E Tests (Showcase)', () => {
94
90
 
95
91
  test('modify line', async () => {
96
92
  const [baseUrl, token, pdfData] = await requireEnvAndFixture('Showcase.pdf');
97
- const pdf = await PDFDancer.open(pdfData, token, baseUrl, 30000);
93
+ const pdf = await PDFDancer.open(pdfData, token, baseUrl);
98
94
 
99
95
  const [line] = await pdf.page(0).selectTextLinesStartingWith(SAMPLE_PARAGRAPH);
100
96
  await line.edit().text(' replaced ').apply();
@@ -106,7 +102,6 @@ describe('Text Line E2E Tests (Showcase)', () => {
106
102
  expect(lines.length).toBeGreaterThan(0);
107
103
  const status = lines[0].objectRef().status;
108
104
  expect(status).toBeDefined();
109
- expect(status?.isEncodable()).toBe(true);
110
105
  expect(status?.getFontType()).toBe(FontType.EMBEDDED);
111
106
  expect(status?.isModified()).toBe(true);
112
107
 
@@ -24,7 +24,6 @@ describe('Text Line E2E Tests (v2 API)', () => {
24
24
  expectWithin(first.position.boundingRect?.y, 706, 1);
25
25
  expect(first.objectRef().status).toBeDefined();
26
26
  expect(first.objectRef().status?.isModified()).toBe(false);
27
- expect(first.objectRef().status?.isEncodable()).toBe(true);
28
27
 
29
28
  const last = lines[lines.length - 1];
30
29
  expect(last.internalId).toBe('TEXTLINE_000340');
@@ -33,7 +32,6 @@ describe('Text Line E2E Tests (v2 API)', () => {
33
32
  expectWithin(last.position.boundingRect?.y, 35, 1);
34
33
  expect(last.objectRef().status).toBeDefined();
35
34
  expect(last.objectRef().status?.isModified()).toBe(false);
36
- expect(last.objectRef().status?.isEncodable()).toBe(true);
37
35
  });
38
36
 
39
37
  test('find lines on page', async () => {
@@ -107,17 +105,15 @@ describe('Text Line E2E Tests (v2 API)', () => {
107
105
  const [line] = await pdf.page(0).selectTextLinesStartingWith('The Complete');
108
106
  const result = await line.edit().text(' replaced ').apply();
109
107
 
110
- // This should issue a warning about an embedded font modification
111
- expect(result.warning).toBeDefined();
112
- expect(result.warning).toContain('You are using an embedded font and modified the text.');
108
+ expect(result.warning).toBeDefined(); // This should issue a warning about an embedded font modification
109
+ expect(result.warning).toContain('Text is not encodable with your current font, we are using \'Poppins-Bold\' as a fallback font instead.');
113
110
 
114
111
  const stillOld = await pdf.page(0).selectParagraphsStartingWith('The Complete');
115
112
  expect(stillOld).toHaveLength(0);
116
113
 
117
- const lines = await pdf.page(0).selectTextLinesStartingWith(' replaced ');
114
+ const lines = await pdf.page(0).selectTextLinesMatching('.*replaced.*');
118
115
  expect(lines.length).toBeGreaterThan(0);
119
116
  expect(lines[0].objectRef().status).toBeDefined();
120
- expect(lines[0].objectRef().status?.isEncodable()).toBe(true);
121
117
  expect(lines[0].objectRef().status?.getFontType()).toBe(FontType.EMBEDDED);
122
118
  expect(lines[0].objectRef().status?.isModified()).toBe(true);
123
119
 
@@ -130,4 +126,64 @@ describe('Text Line E2E Tests (v2 API)', () => {
130
126
  const assertions = await PDFAssertions.create(pdf);
131
127
  await assertions.assertTextlineExists(' replaced ');
132
128
  });
129
+
130
+ // Tests for singular select methods
131
+ test('selectTextLine returns first line or null', async () => {
132
+ const [baseUrl, token, pdfData] = await requireEnvAndFixture('ObviouslyAwesome.pdf');
133
+ const pdf = await PDFDancer.open(pdfData, token, baseUrl);
134
+
135
+ // Test with results
136
+ const line = await pdf.page(1).selectTextLine();
137
+ expect(line).not.toBeNull();
138
+ expect(line!.internalId).toBe('TEXTLINE_000005');
139
+
140
+ // Test with PDFDancer class
141
+ const lineFromPdf = await pdf.selectTextLine();
142
+ expect(lineFromPdf).not.toBeNull();
143
+ expect(lineFromPdf!.internalId).toBe('TEXTLINE_000001');
144
+
145
+ // Test alias selectLine
146
+ const lineAlias = await pdf.selectLine();
147
+ expect(lineAlias).not.toBeNull();
148
+ expect(lineAlias!.internalId).toBe('TEXTLINE_000001');
149
+ });
150
+
151
+ test('selectTextLineStartingWith returns first match or null', async () => {
152
+ const [baseUrl, token, pdfData] = await requireEnvAndFixture('ObviouslyAwesome.pdf');
153
+ const pdf = await PDFDancer.open(pdfData, token, baseUrl);
154
+
155
+ const line = await pdf.page(0).selectTextLineStartingWith('the complete');
156
+ expect(line).not.toBeNull();
157
+ expect(line!.internalId).toBe('TEXTLINE_000002');
158
+
159
+ // Test with no match
160
+ const noMatch = await pdf.page(0).selectTextLineStartingWith('NoMatch');
161
+ expect(noMatch).toBeNull();
162
+ });
163
+
164
+ test('selectTextLineMatching returns first match or null', async () => {
165
+ const [baseUrl, token, pdfData] = await requireEnvAndFixture('ObviouslyAwesome.pdf');
166
+ const pdf = await PDFDancer.open(pdfData, token, baseUrl);
167
+
168
+ const line = await pdf.page(0).selectTextLineMatching('.*Complete.*');
169
+ expect(line).not.toBeNull();
170
+ expect(line!.internalId).toBe('TEXTLINE_000002');
171
+
172
+ // Test with no match
173
+ const noMatch = await pdf.page(0).selectTextLineMatching('.*NOT FOUND.*');
174
+ expect(noMatch).toBeNull();
175
+ });
176
+
177
+ test('selectTextLineAt returns first line at position or null', async () => {
178
+ const [baseUrl, token, pdfData] = await requireEnvAndFixture('ObviouslyAwesome.pdf');
179
+ const pdf = await PDFDancer.open(pdfData, token, baseUrl);
180
+
181
+ const line = await pdf.page(0).selectTextLineAt(54, 606, 10);
182
+ expect(line).not.toBeNull();
183
+ expect(line!.internalId).toBe('TEXTLINE_000002');
184
+
185
+ // Test with no match
186
+ const noMatch = await pdf.page(0).selectTextLineAt(1000, 1000, 1);
187
+ expect(noMatch).toBeNull();
188
+ });
133
189
  });
@@ -5,7 +5,7 @@ import {PDFAssertions} from './pdf-assertions';
5
5
  describe('Page E2E Tests (Showcase)', () => {
6
6
  test('get all elements', async () => {
7
7
  const [baseUrl, token, pdfData] = await requireEnvAndFixture('Showcase.pdf');
8
- const pdf = await PDFDancer.open(pdfData, token, baseUrl, 30000);
8
+ const pdf = await PDFDancer.open(pdfData, token, baseUrl);
9
9
 
10
10
  const elements = await pdf.selectElements();
11
11
  expect(elements.length).toBe(99);
@@ -20,7 +20,7 @@ describe('Page E2E Tests (Showcase)', () => {
20
20
 
21
21
  test('get pages', async () => {
22
22
  const [baseUrl, token, pdfData] = await requireEnvAndFixture('Showcase.pdf');
23
- const pdf = await PDFDancer.open(pdfData, token, baseUrl, 30000);
23
+ const pdf = await PDFDancer.open(pdfData, token, baseUrl);
24
24
 
25
25
  const pages = await pdf.pages();
26
26
  expect(pages).toBeDefined();
@@ -30,7 +30,7 @@ describe('Page E2E Tests (Showcase)', () => {
30
30
 
31
31
  test('get page', async () => {
32
32
  const [baseUrl, token, pdfData] = await requireEnvAndFixture('Showcase.pdf');
33
- const pdf = await PDFDancer.open(pdfData, token, baseUrl, 30000);
33
+ const pdf = await PDFDancer.open(pdfData, token, baseUrl);
34
34
 
35
35
  const page = pdf.page(2);
36
36
  expect(page).toBeDefined();
@@ -40,7 +40,7 @@ describe('Page E2E Tests (Showcase)', () => {
40
40
 
41
41
  test('delete page', async () => {
42
42
  const [baseUrl, token, pdfData] = await requireEnvAndFixture('Showcase.pdf');
43
- const pdf = await PDFDancer.open(pdfData, token, baseUrl, 30000);
43
+ const pdf = await PDFDancer.open(pdfData, token, baseUrl);
44
44
 
45
45
  const page3 = pdf.page(3);
46
46
  await page3.delete();
@@ -54,7 +54,7 @@ describe('Page E2E Tests (Showcase)', () => {
54
54
 
55
55
  test('move page', async () => {
56
56
  const [baseUrl, token, pdfData] = await requireEnvAndFixture('Showcase.pdf');
57
- const pdf = await PDFDancer.open(pdfData, token, baseUrl, 30000);
57
+ const pdf = await PDFDancer.open(pdfData, token, baseUrl);
58
58
 
59
59
  const pagesBefore = await pdf.pages();
60
60
  expect(pagesBefore.length).toBe(7);
@@ -68,7 +68,7 @@ describe('Page E2E Tests (Showcase)', () => {
68
68
 
69
69
  test('add page', async () => {
70
70
  const [baseUrl, token, pdfData] = await requireEnvAndFixture('Showcase.pdf');
71
- const pdf = await PDFDancer.open(pdfData, token, baseUrl, 30000);
71
+ const pdf = await PDFDancer.open(pdfData, token, baseUrl);
72
72
 
73
73
  const pagesBefore = await pdf.pages();
74
74
  expect(pagesBefore.length).toBe(7);
@@ -83,7 +83,7 @@ describe('Page E2E Tests (Showcase)', () => {
83
83
 
84
84
  test('add page with builder default', async () => {
85
85
  const [baseUrl, token, pdfData] = await requireEnvAndFixture('Showcase.pdf');
86
- const pdf = await PDFDancer.open(pdfData, token, baseUrl, 30000);
86
+ const pdf = await PDFDancer.open(pdfData, token, baseUrl);
87
87
 
88
88
  expect((await pdf.pages()).length).toBe(7);
89
89
 
@@ -94,7 +94,7 @@ describe('Page E2E Tests (Showcase)', () => {
94
94
 
95
95
  test('add page with builder A4 portrait', async () => {
96
96
  const [baseUrl, token, pdfData] = await requireEnvAndFixture('Showcase.pdf');
97
- const pdf = await PDFDancer.open(pdfData, token, baseUrl, 30000);
97
+ const pdf = await PDFDancer.open(pdfData, token, baseUrl);
98
98
 
99
99
  expect((await pdf.pages()).length).toBe(7);
100
100
 
@@ -105,7 +105,7 @@ describe('Page E2E Tests (Showcase)', () => {
105
105
 
106
106
  test('add page with builder letter landscape', async () => {
107
107
  const [baseUrl, token, pdfData] = await requireEnvAndFixture('Showcase.pdf');
108
- const pdf = await PDFDancer.open(pdfData, token, baseUrl, 30000);
108
+ const pdf = await PDFDancer.open(pdfData, token, baseUrl);
109
109
 
110
110
  expect((await pdf.pages()).length).toBe(7);
111
111
 
@@ -116,7 +116,7 @@ describe('Page E2E Tests (Showcase)', () => {
116
116
 
117
117
  test('add page with builder at index', async () => {
118
118
  const [baseUrl, token, pdfData] = await requireEnvAndFixture('Showcase.pdf');
119
- const pdf = await PDFDancer.open(pdfData, token, baseUrl, 30000);
119
+ const pdf = await PDFDancer.open(pdfData, token, baseUrl);
120
120
 
121
121
  expect((await pdf.pages()).length).toBe(7);
122
122
 
@@ -132,7 +132,7 @@ describe('Page E2E Tests (Showcase)', () => {
132
132
 
133
133
  test('add page with builder custom size', async () => {
134
134
  const [baseUrl, token, pdfData] = await requireEnvAndFixture('Showcase.pdf');
135
- const pdf = await PDFDancer.open(pdfData, token, baseUrl, 30000);
135
+ const pdf = await PDFDancer.open(pdfData, token, baseUrl);
136
136
 
137
137
  expect((await pdf.pages()).length).toBe(7);
138
138
 
@@ -143,7 +143,7 @@ describe('Page E2E Tests (Showcase)', () => {
143
143
 
144
144
  test('add page with builder all options', async () => {
145
145
  const [baseUrl, token, pdfData] = await requireEnvAndFixture('Showcase.pdf');
146
- const pdf = await PDFDancer.open(pdfData, token, baseUrl, 30000);
146
+ const pdf = await PDFDancer.open(pdfData, token, baseUrl);
147
147
 
148
148
  expect((await pdf.pages()).length).toBe(7);
149
149
 
@@ -11,7 +11,7 @@ describe('Page E2E Tests', () => {
11
11
 
12
12
  test('get pages', async () => {
13
13
  const [baseUrl, token, pdfData] = await requireEnvAndFixture('ObviouslyAwesome.pdf');
14
- const client = await PDFDancer.open(pdfData, token, baseUrl, 30000);
14
+ const client = await PDFDancer.open(pdfData, token, baseUrl);
15
15
 
16
16
  const pages = await client.pages();
17
17
  expect(pages).toBeDefined();
@@ -21,7 +21,7 @@ describe('Page E2E Tests', () => {
21
21
 
22
22
  test('get page', async () => {
23
23
  const [baseUrl, token, pdfData] = await requireEnvAndFixture('ObviouslyAwesome.pdf');
24
- const client = await PDFDancer.open(pdfData, token, baseUrl, 30000);
24
+ const client = await PDFDancer.open(pdfData, token, baseUrl);
25
25
 
26
26
  const page = client.page(2);
27
27
  expect(page).toBeDefined();
@@ -31,7 +31,7 @@ describe('Page E2E Tests', () => {
31
31
 
32
32
  test('delete page', async () => {
33
33
  const [baseUrl, token, pdfData] = await requireEnvAndFixture('ObviouslyAwesome.pdf');
34
- const client = await PDFDancer.open(pdfData, token, baseUrl, 30000);
34
+ const client = await PDFDancer.open(pdfData, token, baseUrl);
35
35
 
36
36
  expect(await client.pages()).toHaveLength(12);
37
37
  const page3 = client.page(3);
@@ -28,7 +28,6 @@ describe('Paragraph E2E Tests (Showcase)', () => {
28
28
 
29
29
  const status = last.objectRef().status;
30
30
  expect(status).toBeDefined();
31
- expect(status?.isEncodable()).toBe(true);
32
31
  expect(status?.getFontType()).toBe(FontType.EMBEDDED);
33
32
  expect(status?.isModified()).toBe(false);
34
33
  });
@@ -137,7 +136,6 @@ describe('Paragraph E2E Tests (Showcase)', () => {
137
136
  const [moved] = await pdf.page(0).selectParagraphsStartingWith(SAMPLE_PARAGRAPH);
138
137
  const status = moved.objectRef().status;
139
138
  expect(status).toBeDefined();
140
- expect(status?.isEncodable()).toBe(true);
141
139
  expect(status?.getFontType()).toBe(FontType.EMBEDDED);
142
140
  expect(status?.isModified()).toBe(false);
143
141
 
@@ -181,7 +179,6 @@ describe('Paragraph E2E Tests (Showcase)', () => {
181
179
  const moved = (await pdf.page(0).selectParagraphsAt(300.1, 500))[0];
182
180
  const status = moved.objectRef().status;
183
181
  expect(status).toBeDefined();
184
- expect(status?.isEncodable()).toBe(true);
185
182
  expect(status?.getFontType()).toBe(FontType.STANDARD);
186
183
  expect(status?.isModified()).toBe(true);
187
184
 
@@ -242,7 +239,6 @@ describe('Paragraph E2E Tests (Showcase)', () => {
242
239
  const [updated] = await pdf.page(0).selectParagraphsStartingWith(SAMPLE_PARAGRAPH);
243
240
  const status = updated.objectRef().status;
244
241
  expect(status).toBeDefined();
245
- expect(status?.isEncodable()).toBe(true);
246
242
  expect(status?.getFontType()).toBe(FontType.EMBEDDED);
247
243
  expect(status?.isModified()).toBe(false);
248
244
 
@@ -261,7 +257,6 @@ describe('Paragraph E2E Tests (Showcase)', () => {
261
257
  const [updated] = await pdf.page(0).selectParagraphsStartingWith('lorem');
262
258
  const status = updated.objectRef().status;
263
259
  expect(status).toBeDefined();
264
- expect(status?.isEncodable()).toBe(true);
265
260
  expect(status?.getFontType()).toBe(FontType.EMBEDDED);
266
261
  expect(status?.isModified()).toBe(true);
267
262
 
@@ -282,7 +277,6 @@ describe('Paragraph E2E Tests (Showcase)', () => {
282
277
  const [updated] = await pdf.page(0).selectParagraphsStartingWith(SAMPLE_PARAGRAPH);
283
278
  const status = updated.objectRef().status;
284
279
  expect(status).toBeDefined();
285
- expect(status?.isEncodable()).toBe(true);
286
280
  expect(status?.getFontType()).toBe(FontType.STANDARD);
287
281
  expect(status?.isModified()).toBe(true);
288
282
 
@@ -300,7 +294,6 @@ describe('Paragraph E2E Tests (Showcase)', () => {
300
294
  const [updated] = await pdf.page(0).selectParagraphsStartingWith(SAMPLE_PARAGRAPH);
301
295
  const status = updated.objectRef().status;
302
296
  expect(status).toBeDefined();
303
- expect(status?.isEncodable()).toBe(true);
304
297
  expect(status?.getFontType()).toBe(FontType.EMBEDDED);
305
298
  expect(status?.isModified()).toBe(false);
306
299
 
@@ -517,7 +510,6 @@ describe('Paragraph E2E Tests (Showcase)', () => {
517
510
 
518
511
  const status = moved[0].objectRef().status;
519
512
  expect(status).toBeDefined();
520
- expect(status?.isEncodable()).toBe(true);
521
513
  expect(status?.getFontType()).toBe(FontType.EMBEDDED);
522
514
  expect(status?.isModified()).toBe(false);
523
515
  });