@link-assistant/web-capture 2.0.0 → 2.0.2

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 (117) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/bin/web-capture.js +2 -5
  3. package/package.json +36 -23
  4. package/src/archive.js +0 -1
  5. package/src/binary-download.js +0 -1
  6. package/src/docx.js +13 -10
  7. package/src/fetch.js +0 -1
  8. package/src/gdocs-images.js +0 -1
  9. package/src/gdocs.js +0 -1
  10. package/src/github.js +0 -1
  11. package/src/lib.js +0 -1
  12. package/src/markdown.js +0 -1
  13. package/src/shared-dialog.js +0 -1
  14. package/src/stream.js +0 -1
  15. package/src/transport.js +23 -5
  16. package/src/txt.js +0 -1
  17. package/.changeset/README.md +0 -8
  18. package/.changeset/config.json +0 -11
  19. package/.dockerignore +0 -6
  20. package/.jscpd.json +0 -19
  21. package/.lenv +0 -8
  22. package/.prettierignore +0 -8
  23. package/.prettierrc +0 -10
  24. package/Dockerfile +0 -52
  25. package/docker-compose.yml +0 -11
  26. package/eslint.config.js +0 -112
  27. package/examples/js/capture_cache.js +0 -12
  28. package/examples/js/engine_comparison.js +0 -39
  29. package/examples/js/html_download.js +0 -23
  30. package/examples/js/image_download.js +0 -36
  31. package/examples/js/markdown_download.js +0 -23
  32. package/examples/js/playwright_example.js +0 -23
  33. package/examples/python/capture_client.py +0 -20
  34. package/examples/python/html_download.py +0 -3
  35. package/examples/python/image_download.py +0 -16
  36. package/examples/python/markdown_download.py +0 -3
  37. package/examples/python/playwright_example.py +0 -22
  38. package/jest.config.mjs +0 -17
  39. package/tests/ci/dependency-freshness.test.js +0 -74
  40. package/tests/ci/detect-code-changes.test.js +0 -187
  41. package/tests/ci/docker-install.test.js +0 -31
  42. package/tests/ci/rust-dockerfile.test.js +0 -54
  43. package/tests/ci/workflow-policy.test.js +0 -79
  44. package/tests/e2e/docker.test.js +0 -186
  45. package/tests/e2e/process.test.js +0 -215
  46. package/tests/fixtures/bold-coalesce-and-leakage.html +0 -27
  47. package/tests/fixtures/deepwiki/deepwiki-full-page.png +0 -0
  48. package/tests/fixtures/deepwiki/index.md +0 -1500
  49. package/tests/fixtures/deepwiki/part-1.md +0 -776
  50. package/tests/fixtures/habr-articles.js +0 -45
  51. package/tests/fixtures/heading-numbering.html +0 -19
  52. package/tests/fixtures/list-item-with-br.html +0 -8
  53. package/tests/fixtures/ol-continuous-numbering.html +0 -12
  54. package/tests/fixtures/paragraph-vs-line-break.html +0 -11
  55. package/tests/helpers/nock.js +0 -10
  56. package/tests/helpers/screenshot.js +0 -10
  57. package/tests/helpers/search-fixture.cjs +0 -17
  58. package/tests/helpers/temporary-directory.js +0 -12
  59. package/tests/integration/api-endpoints.test.js +0 -418
  60. package/tests/integration/archive-default-layout.test.js +0 -37
  61. package/tests/integration/browser-engines.test.js +0 -80
  62. package/tests/integration/browser-packaged-path.test.js +0 -45
  63. package/tests/integration/deepwiki-download.test.js +0 -144
  64. package/tests/integration/deepwiki-rendered-page.mock.test.js +0 -121
  65. package/tests/integration/formalai-contract.test.js +0 -214
  66. package/tests/integration/gdocs-public-doc.test.js +0 -315
  67. package/tests/integration/github-readme.test.js +0 -133
  68. package/tests/integration/google-drive-image.test.js +0 -246
  69. package/tests/integration/habr-article.test.js +0 -337
  70. package/tests/integration/search-endpoint.test.js +0 -88
  71. package/tests/integration/stackoverflow-download.test.js +0 -173
  72. package/tests/integration/wikipedia-download.test.js +0 -134
  73. package/tests/jest.setup.mjs +0 -7
  74. package/tests/mock/index.test.js +0 -225
  75. package/tests/unit/animation.test.js +0 -33
  76. package/tests/unit/batch.test.js +0 -114
  77. package/tests/unit/bold-coalesce-and-leakage.test.js +0 -54
  78. package/tests/unit/browser-launch-options.test.js +0 -42
  79. package/tests/unit/browser.test.js +0 -172
  80. package/tests/unit/cache.test.js +0 -182
  81. package/tests/unit/cli.test.js +0 -399
  82. package/tests/unit/convertGoogleDriveUrl.test.js +0 -89
  83. package/tests/unit/convertRelativeUrls.test.js +0 -34
  84. package/tests/unit/extract-images.test.js +0 -259
  85. package/tests/unit/fetch-html.test.js +0 -54
  86. package/tests/unit/figures.test.js +0 -74
  87. package/tests/unit/gdocs-export-headers.test.js +0 -28
  88. package/tests/unit/gdocs-preprocess.test.js +0 -36
  89. package/tests/unit/gdocs.test.js +0 -1490
  90. package/tests/unit/github.test.js +0 -156
  91. package/tests/unit/heading-image.test.js +0 -49
  92. package/tests/unit/heading-numbering.test.js +0 -28
  93. package/tests/unit/html2md-br-in-list-item.test.js +0 -23
  94. package/tests/unit/html2md-ol-numbering.test.js +0 -20
  95. package/tests/unit/html2md.test.js +0 -695
  96. package/tests/unit/image-mode-defaults.test.js +0 -54
  97. package/tests/unit/kreuzberg.test.js +0 -249
  98. package/tests/unit/latex.test.js +0 -123
  99. package/tests/unit/localize-images.test.js +0 -114
  100. package/tests/unit/markdown.test.js +0 -36
  101. package/tests/unit/metadata.test.js +0 -140
  102. package/tests/unit/package-runtime-dependencies.test.js +0 -74
  103. package/tests/unit/paragraph-vs-line-break.test.js +0 -56
  104. package/tests/unit/postprocess.test.js +0 -110
  105. package/tests/unit/proxy-headers.test.js +0 -100
  106. package/tests/unit/publish-verification.test.js +0 -54
  107. package/tests/unit/retry.test.js +0 -111
  108. package/tests/unit/search.test.js +0 -339
  109. package/tests/unit/shared-dialog.test.js +0 -173
  110. package/tests/unit/stackoverflow.test.js +0 -32
  111. package/tests/unit/stream.test.js +0 -83
  112. package/tests/unit/verify.test.js +0 -182
  113. package/tests/xpaste/xpaste-screenshot-markdown.mock.test.js +0 -375
  114. package/tests/xpaste/xpaste.e2e.test.js +0 -36
  115. package/tests/xpaste/xpaste.integration.test.js +0 -41
  116. package/tests/xpaste/xpaste.mock.test.js +0 -261
  117. package/tests/xpaste/xpaste.unit.test.js +0 -119
@@ -1,399 +0,0 @@
1
- // Unit tests for CLI argument parsing and functionality
2
- import { spawn } from 'child_process';
3
- import http from 'node:http';
4
- import { mkdtempSync, readFileSync, rmSync, writeFileSync } from 'fs';
5
- import { fileURLToPath } from 'url';
6
- import { dirname, join, resolve } from 'path';
7
- import packageJson from '../../package.json' with { type: 'json' };
8
-
9
- const __filename = fileURLToPath(import.meta.url);
10
- const __dirname = dirname(__filename);
11
- const cliPath = resolve(__dirname, '../../bin/web-capture.js');
12
- const searchFixturePath = resolve(__dirname, '../helpers/search-fixture.cjs');
13
-
14
- // Helper function to run CLI and capture output
15
- function runCli(args, options = {}) {
16
- return new Promise((resolve, reject) => {
17
- const proc = spawn(process.execPath, [cliPath, ...args], {
18
- cwd: options.cwd || dirname(cliPath),
19
- env: { ...process.env, ...options.env },
20
- });
21
-
22
- let stdout = '';
23
- let stderr = '';
24
-
25
- proc.stdout.on('data', (data) => {
26
- stdout += data.toString();
27
- });
28
- proc.stderr.on('data', (data) => {
29
- stderr += data.toString();
30
- });
31
-
32
- proc.on('close', (code) => {
33
- resolve({ code, stdout, stderr });
34
- });
35
-
36
- proc.on('error', reject);
37
- });
38
- }
39
-
40
- function startFixtureServer({
41
- body = '<!doctype html><html><body><h1>Issue 68</h1><p>Captured from positional URL.</p></body></html>',
42
- contentType = 'text/html; charset=utf-8',
43
- } = {}) {
44
- return new Promise((resolve, reject) => {
45
- const server = http.createServer((req, res) => {
46
- res.writeHead(200, {
47
- 'Content-Type': contentType,
48
- 'Content-Length': Buffer.byteLength(body),
49
- });
50
- res.end(body);
51
- });
52
-
53
- server.on('error', reject);
54
- server.listen(0, '127.0.0.1', () => {
55
- const { port } = server.address();
56
- resolve({
57
- server,
58
- url: `http://127.0.0.1:${port}/article`,
59
- });
60
- });
61
- });
62
- }
63
-
64
- function stopFixtureServer(server) {
65
- return new Promise((resolve, reject) => {
66
- server.close((err) => {
67
- if (err) {
68
- reject(err);
69
- return;
70
- }
71
- resolve();
72
- });
73
- });
74
- }
75
-
76
- describe('CLI', () => {
77
- describe('--help', () => {
78
- test('shows help message with --help flag', async () => {
79
- const result = await runCli(['--help']);
80
- expect(result.code).toBe(0);
81
- expect(result.stdout).toContain('web-capture');
82
- expect(result.stdout).toContain('Usage:');
83
- expect(result.stdout).toContain('--serve');
84
- expect(result.stdout).toContain('--format');
85
- expect(result.stdout).toContain('--output');
86
- expect(result.stdout).toContain('--engine');
87
- });
88
-
89
- test('shows help message with -h flag', async () => {
90
- const result = await runCli(['-h']);
91
- expect(result.code).toBe(0);
92
- expect(result.stdout).toContain('web-capture');
93
- expect(result.stdout).toContain('Usage:');
94
- });
95
-
96
- test('shows error and exits with code 1 when no arguments provided', async () => {
97
- const result = await runCli([]);
98
- expect(result.code).toBe(1);
99
- // With lino-arguments and yargs, error messages go to stderr
100
- expect(result.stderr).toContain('Error');
101
- });
102
- });
103
-
104
- describe('--version', () => {
105
- test('shows version with --version flag', async () => {
106
- const result = await runCli(['--version']);
107
- expect(result.code).toBe(0);
108
- // yargs outputs just the version number
109
- expect(result.stdout).toMatch(/\d+\.\d+\.\d+/);
110
- });
111
-
112
- test('shows version with -v flag', async () => {
113
- const result = await runCli(['-v']);
114
- expect(result.code).toBe(0);
115
- // yargs outputs just the version number
116
- expect(result.stdout).toMatch(/\d+\.\d+\.\d+/);
117
- });
118
-
119
- test('shows web-capture version when run from another npm project', async () => {
120
- const callerProjectDir = mkdtempSync(join(process.cwd(), 'caller-'));
121
- writeFileSync(
122
- join(callerProjectDir, 'package.json'),
123
- JSON.stringify({
124
- name: 'caller-project',
125
- version: '1.0.0',
126
- })
127
- );
128
-
129
- try {
130
- const result = await runCli(['--version'], { cwd: callerProjectDir });
131
-
132
- expect(result.code).toBe(0);
133
- expect(result.stdout.trim()).toBe(packageJson.version);
134
- } finally {
135
- rmSync(callerProjectDir, { recursive: true, force: true });
136
- }
137
- });
138
- });
139
-
140
- describe('URL validation', () => {
141
- test('accepts a URL as a positional argument', async () => {
142
- const { server, url } = await startFixtureServer();
143
-
144
- try {
145
- const result = await runCli([
146
- url,
147
- '--format',
148
- 'markdown',
149
- '--output',
150
- '-',
151
- ]);
152
-
153
- expect(result.code).toBe(0);
154
- expect(result.stderr).not.toContain('Unknown argument');
155
- expect(result.stdout).toContain('Issue 68');
156
- expect(result.stdout).toContain('Captured from positional URL.');
157
- } finally {
158
- await stopFixtureServer(server);
159
- }
160
- }, 15000);
161
-
162
- test('accepts a URL after the -- argument separator', async () => {
163
- const { server, url } = await startFixtureServer();
164
-
165
- try {
166
- const result = await runCli([
167
- '--format',
168
- 'markdown',
169
- '--output',
170
- '-',
171
- '--',
172
- url,
173
- ]);
174
-
175
- expect(result.code).toBe(0);
176
- expect(result.stderr).not.toContain('Missing URL');
177
- expect(result.stdout).toContain('Issue 68');
178
- } finally {
179
- await stopFixtureServer(server);
180
- }
181
- }, 15000);
182
-
183
- test('rejects unknown options', async () => {
184
- const result = await runCli([
185
- '--unknown-option-for-issue-68',
186
- 'https://example.com',
187
- ]);
188
-
189
- expect(result.code).toBe(1);
190
- expect(result.stderr).toContain('Unknown argument');
191
- });
192
-
193
- test('rejects invalid URL', async () => {
194
- const result = await runCli(['http://[invalid-url']);
195
- // Should fail before trying to capture.
196
- expect(result.code).toBe(1);
197
- expect(result.stderr).toContain('Invalid URL');
198
- }, 15000);
199
- });
200
-
201
- describe('format options', () => {
202
- test('accepts --format html', async () => {
203
- // Just test that the argument is accepted (actual fetch would fail without network)
204
- const result = await runCli(['--help']);
205
- expect(result.stdout).toContain('--format');
206
- expect(result.stdout).toContain('html');
207
- });
208
-
209
- test('accepts --format markdown', async () => {
210
- const result = await runCli(['--help']);
211
- expect(result.stdout).toContain('markdown');
212
- });
213
-
214
- test('accepts --format image', async () => {
215
- const result = await runCli(['--help']);
216
- expect(result.stdout).toContain('image');
217
- });
218
- });
219
-
220
- describe('engine options', () => {
221
- test('help shows engine options', async () => {
222
- const result = await runCli(['--help']);
223
- expect(result.stdout).toContain('--engine');
224
- expect(result.stdout).toContain('puppeteer');
225
- expect(result.stdout).toContain('playwright');
226
- });
227
-
228
- test('accepts --engine option', async () => {
229
- const result = await runCli(['--help']);
230
- expect(result.stdout).toContain('--engine');
231
- });
232
- });
233
-
234
- describe('server mode options', () => {
235
- test('help shows --serve option', async () => {
236
- const result = await runCli(['--help']);
237
- expect(result.stdout).toContain('--serve');
238
- expect(result.stdout).toContain('-s');
239
- });
240
-
241
- test('help shows --port option', async () => {
242
- const result = await runCli(['--help']);
243
- expect(result.stdout).toContain('--port');
244
- expect(result.stdout).toContain('-p');
245
- });
246
-
247
- test('help shows API endpoints', async () => {
248
- const result = await runCli(['--help']);
249
- expect(result.stdout).toContain('/html');
250
- expect(result.stdout).toContain('/markdown');
251
- expect(result.stdout).toContain('/image');
252
- expect(result.stdout).not.toContain('/gdocs');
253
- });
254
- });
255
-
256
- describe('output options', () => {
257
- test('help shows --output option', async () => {
258
- const result = await runCli(['--help']);
259
- expect(result.stdout).toContain('--output');
260
- expect(result.stdout).toContain('-o');
261
- });
262
- });
263
-
264
- describe('FormalAI-compatible CLI contract', () => {
265
- test('writes HTML, Markdown, and text captures to stdout with -o -', async () => {
266
- const { server, url } = await startFixtureServer({
267
- body: '<!doctype html><html><body><h1>FormalAI Fixture</h1><p>Stable CLI shape.</p></body></html>',
268
- });
269
-
270
- try {
271
- const html = await runCli([url, '--format', 'html', '--output', '-']);
272
- expect(html.code).toBe(0);
273
- expect(html.stdout).toContain('<h1>FormalAI Fixture</h1>');
274
-
275
- const markdown = await runCli([
276
- url,
277
- '--format',
278
- 'markdown',
279
- '--output',
280
- '-',
281
- ]);
282
- expect(markdown.code).toBe(0);
283
- expect(markdown.stdout).toContain('FormalAI Fixture');
284
- expect(markdown.stdout).toContain('Stable CLI shape.');
285
-
286
- const text = await runCli([url, '--format', 'txt', '--output', '-']);
287
- expect(text.code).toBe(0);
288
- expect(text.stdout).toContain('FormalAI Fixture');
289
- } finally {
290
- await stopFixtureServer(server);
291
- }
292
- }, 20000);
293
-
294
- test('writes archive captures as ZIP files for binary CLI consumers', async () => {
295
- const outputDir = mkdtempSync(join(process.cwd(), 'formalai-cli-'));
296
- const outputPath = join(outputDir, 'capture.zip');
297
- const { server, url } = await startFixtureServer({
298
- body: '<!doctype html><html><body><h1>FormalAI Archive</h1></body></html>',
299
- });
300
-
301
- try {
302
- const result = await runCli([
303
- url,
304
- '--archive',
305
- 'zip',
306
- '--output',
307
- outputPath,
308
- ]);
309
-
310
- expect(result.code).toBe(0);
311
- const zipBytes = readFileSync(outputPath);
312
- expect(zipBytes.length).toBeGreaterThan(50);
313
- expect(zipBytes[0]).toBe(0x50);
314
- expect(zipBytes[1]).toBe(0x4b);
315
- } finally {
316
- await stopFixtureServer(server);
317
- rmSync(outputDir, { recursive: true, force: true });
318
- }
319
- }, 20000);
320
-
321
- test('emits normalized search JSON from the search subcommand', async () => {
322
- const nodeOptions = [
323
- process.env.NODE_OPTIONS,
324
- `--require=${searchFixturePath}`,
325
- ]
326
- .filter(Boolean)
327
- .join(' ');
328
- const result = await runCli(
329
- ['search', 'formal-ai', '--provider', 'wikipedia', '--limit', '1'],
330
- {
331
- env: { NODE_OPTIONS: nodeOptions },
332
- }
333
- );
334
-
335
- expect(result.code).toBe(0);
336
- const body = JSON.parse(result.stdout);
337
- expect(body).toMatchObject({
338
- query: 'formal-ai',
339
- provider: 'wikipedia',
340
- captureMode: 'fetch',
341
- });
342
- expect(body.results).toEqual([
343
- {
344
- rank: 1,
345
- title: 'Formal methods',
346
- url: 'https://en.wikipedia.org/wiki/Formal_methods',
347
- snippet: 'the study of formal methods',
348
- },
349
- ]);
350
- expect(body.diagnostics).toMatchObject({
351
- status: 200,
352
- blockedByCors: false,
353
- blockedByCaptcha: false,
354
- });
355
- expect(body.diagnostics.sourceUrl).toContain('en.wikipedia.org');
356
- }, 20000);
357
-
358
- test('emits shared-dialog demo_memory from the shared-dialog subcommand', async () => {
359
- const fixturePath = resolve(
360
- __dirname,
361
- '../../../docs/case-studies/issue-141/raw-data/chatgpt-share-6a3825b9.html'
362
- );
363
- const body = readFileSync(fixturePath, 'utf-8');
364
- const { server, url } = await startFixtureServer({ body });
365
- const shareUrl = url.replace(
366
- '/article',
367
- '/share/6a3825b9-8de4-83ee-9c24-52fd1eb38d24'
368
- );
369
-
370
- try {
371
- const result = await runCli(
372
- [
373
- 'shared-dialog',
374
- shareUrl,
375
- '--format',
376
- 'demo-memory',
377
- '--output',
378
- '-',
379
- ],
380
- {
381
- cwd: resolve(__dirname, '../..'),
382
- }
383
- );
384
-
385
- expect(result.code).toBe(0);
386
- expect(result.stdout.startsWith('demo_memory')).toBe(true);
387
- expect(result.stdout).toContain('demo_memory');
388
- expect(result.stdout.match(/\n {2}event "/g)).toHaveLength(4);
389
- expect(result.stdout).toContain('role "user"');
390
- expect(result.stdout).toContain('role "assistant"');
391
- expect(result.stdout).toContain(
392
- 'conversationTitle "Infinite loop script"'
393
- );
394
- } finally {
395
- await stopFixtureServer(server);
396
- }
397
- }, 20000);
398
- });
399
- });
@@ -1,89 +0,0 @@
1
- import {
2
- convertGoogleDriveUrl,
3
- getGoogleDriveFileId,
4
- googleDriveImageTextForUrl,
5
- isGoogleDriveFileUrl,
6
- } from '../../src/lib.js';
7
-
8
- const FIRST_FILE_ID = '1Cxkx6-428EQAX0-eiaq66H829ohnPp7q';
9
- const SECOND_FILE_ID = '1fgJaftjv53xCN7vgiJOaQlbfWkUqPgyd';
10
-
11
- function directDownloadUrl(fileId) {
12
- return `https://drive.google.com/uc?export=download&id=${fileId}`;
13
- }
14
-
15
- describe('Google Drive URL helpers', () => {
16
- it.each([
17
- [
18
- 'issue URL with /view',
19
- `https://drive.google.com/file/d/${FIRST_FILE_ID}/view`,
20
- FIRST_FILE_ID,
21
- ],
22
- [
23
- 'issue URL without /view',
24
- `https://drive.google.com/file/d/${FIRST_FILE_ID}`,
25
- FIRST_FILE_ID,
26
- ],
27
- [
28
- 'second issue URL with /view',
29
- `https://drive.google.com/file/d/${SECOND_FILE_ID}/view`,
30
- SECOND_FILE_ID,
31
- ],
32
- [
33
- 'second issue URL without /view',
34
- `https://drive.google.com/file/d/${SECOND_FILE_ID}`,
35
- SECOND_FILE_ID,
36
- ],
37
- [
38
- 'open?id URL',
39
- `https://drive.google.com/open?id=${FIRST_FILE_ID}`,
40
- FIRST_FILE_ID,
41
- ],
42
- [
43
- 'direct uc URL',
44
- `https://drive.google.com/uc?export=download&id=${FIRST_FILE_ID}`,
45
- FIRST_FILE_ID,
46
- ],
47
- [
48
- 'redirected usercontent URL',
49
- `https://drive.usercontent.google.com/download?id=${FIRST_FILE_ID}&export=download`,
50
- FIRST_FILE_ID,
51
- ],
52
- ])('extracts and converts %s', (_name, input, fileId) => {
53
- expect(getGoogleDriveFileId(input)).toBe(fileId);
54
- expect(isGoogleDriveFileUrl(input)).toBe(true);
55
- expect(convertGoogleDriveUrl(input)).toBe(directDownloadUrl(fileId));
56
- });
57
-
58
- it('ignores non-Google Drive URLs and malformed Drive IDs', () => {
59
- const example = 'https://example.com/image.jpg';
60
- const malformed = 'https://drive.google.com/file/d/not%20valid/view';
61
-
62
- expect(getGoogleDriveFileId(example)).toBeNull();
63
- expect(isGoogleDriveFileUrl(example)).toBe(false);
64
- expect(convertGoogleDriveUrl(example)).toBe(example);
65
- expect(getGoogleDriveFileId(malformed)).toBeNull();
66
- expect(isGoogleDriveFileUrl(malformed)).toBe(false);
67
- expect(convertGoogleDriveUrl(malformed)).toBe(malformed);
68
- });
69
-
70
- it('keeps empty or missing inputs unchanged when converting', () => {
71
- expect(convertGoogleDriveUrl(null)).toBeNull();
72
- expect(convertGoogleDriveUrl(undefined)).toBeUndefined();
73
- expect(convertGoogleDriveUrl('')).toBe('');
74
- });
75
-
76
- it('renders text output with the original file URL and direct image URL', () => {
77
- const input = `https://drive.google.com/file/d/${FIRST_FILE_ID}/view`;
78
-
79
- expect(googleDriveImageTextForUrl(input)).toContain(
80
- `Original Google Drive file: ${input}`
81
- );
82
- expect(googleDriveImageTextForUrl(input)).toContain(
83
- `Image: ${directDownloadUrl(FIRST_FILE_ID)}`
84
- );
85
- expect(
86
- googleDriveImageTextForUrl('https://example.com/image.jpg')
87
- ).toBeNull();
88
- });
89
- });
@@ -1,34 +0,0 @@
1
- import { convertRelativeUrls } from '../../src/lib.js';
2
-
3
- describe('convertRelativeUrls', () => {
4
- const baseUrl = 'https://example.com/';
5
-
6
- it('should NOT inject runtimeHook if there are no <script> tags', () => {
7
- const html = `<!DOCTYPE html><html><head><title>Test</title></head><body><h1>Hello</h1><p>World</p></body></html>`;
8
- const result = convertRelativeUrls(html, baseUrl);
9
- // Should not inject the runtimeHook
10
- expect(result).not.toMatch(/MutationObserver/);
11
- expect(result).not.toMatch(/fixAllUrls/);
12
- expect(result).not.toMatch(/runtime JS hook/);
13
- // Should not add any <script> tag
14
- expect(result.match(/<script/gi)).toBeNull();
15
- });
16
-
17
- it('should inject runtimeHook if there is a <script> tag', () => {
18
- const html = `<!DOCTYPE html><html><head><title>Test</title><script src="foo.js"></script></head><body><h1>Hello</h1></body></html>`;
19
- const result = convertRelativeUrls(html, baseUrl);
20
- // Should inject the runtimeHook
21
- expect(result).toMatch(/MutationObserver/);
22
- expect(result).toMatch(/fixAllUrls/);
23
- // Should add a <script> tag for the hook
24
- expect((result.match(/<script/gi) || []).length).toBeGreaterThan(1);
25
- });
26
-
27
- it('should inject runtimeHook if there is an inline <script>', () => {
28
- const html = `<!DOCTYPE html><html><head><title>Test</title><script>console.log('hi');</script></head><body></body></html>`;
29
- const result = convertRelativeUrls(html, baseUrl);
30
- expect(result).toMatch(/MutationObserver/);
31
- expect(result).toMatch(/fixAllUrls/);
32
- expect((result.match(/<script/gi) || []).length).toBeGreaterThan(1);
33
- });
34
- });