@link-assistant/web-capture 1.10.0 → 1.10.1

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/CHANGELOG.md CHANGED
@@ -1,5 +1,15 @@
1
1
  # @link-assistant/web-capture
2
2
 
3
+ ## 1.10.1
4
+
5
+ ### Patch Changes
6
+
7
+ - 31b93a8: Add a live integration test that downloads the Wikipedia page
8
+ (https://en.wikipedia.org/wiki/Wikipedia) as both Markdown and an image (PNG
9
+ screenshot) using every supported browser engine — Puppeteer and Playwright
10
+ (issue #8). The suite is gated behind `WIKIPEDIA_INTEGRATION=true` so default
11
+ offline runs stay deterministic, and is wired into CI as a dedicated live step.
12
+
3
13
  ## 1.10.0
4
14
 
5
15
  ### Minor Changes
package/README.md CHANGED
@@ -456,6 +456,18 @@ npm run test:e2e # Run end-to-end tests
456
456
  npm run test:all # Run all tests including build
457
457
  ```
458
458
 
459
+ Some integration suites hit live servers and are skipped by default. Enable them
460
+ with environment variables:
461
+
462
+ ```bash
463
+ # Download the Wikipedia page (markdown + image) in every supported engine
464
+ WIKIPEDIA_INTEGRATION=true npm test -- --testPathPattern="wikipedia-download"
465
+
466
+ # Habr articles and public Google Docs live suites
467
+ HABR_INTEGRATION=true npm test -- --testPathPattern="habr-article"
468
+ GDOCS_INTEGRATION=true npm test -- --testPathPattern="gdocs-public-doc"
469
+ ```
470
+
459
471
  ## Built With
460
472
 
461
473
  - Express.js for the web server
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@link-assistant/web-capture",
3
- "version": "1.10.0",
3
+ "version": "1.10.1",
4
4
  "description": "CLI and microservice to render web pages as HTML, Markdown, or PNG",
5
5
  "main": "src/index.js",
6
6
  "bin": {
@@ -0,0 +1,142 @@
1
+ /**
2
+ * Integration tests for downloading the Wikipedia page (issue #8).
3
+ *
4
+ * Verifies that web-capture can actually download the Wikipedia article about
5
+ * Wikipedia itself (https://en.wikipedia.org/wiki/Wikipedia) as both Markdown
6
+ * and an image (PNG screenshot) using every supported browser engine
7
+ * (Puppeteer and Playwright).
8
+ *
9
+ * These tests hit the live Wikipedia servers. Set WIKIPEDIA_INTEGRATION=true to
10
+ * run them. In CI they are enabled via the workflow environment variable. When
11
+ * the variable is unset the suite is skipped so default/offline runs stay
12
+ * deterministic.
13
+ *
14
+ * Navigation uses retry with exponential backoff to absorb transient network
15
+ * failures, mirroring the Habr integration suite.
16
+ */
17
+
18
+ import { jest } from '@jest/globals';
19
+ import { createBrowser } from '../../src/browser.js';
20
+ import { convertHtmlToMarkdown } from '../../src/lib.js';
21
+ import { retry } from '../../src/retry.js';
22
+
23
+ const WIKIPEDIA_URL = 'https://en.wikipedia.org/wiki/Wikipedia';
24
+
25
+ // PNG magic number (89 50 4E 47 0D 0A 1A 0A).
26
+ const PNG_SIGNATURE = Buffer.from([
27
+ 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a,
28
+ ]);
29
+
30
+ const SKIP_LIVE =
31
+ !process.env.WIKIPEDIA_INTEGRATION ||
32
+ process.env.WIKIPEDIA_INTEGRATION === 'false';
33
+ const describeIfLive = SKIP_LIVE ? describe.skip : describe;
34
+
35
+ // These tests hit live servers and may take a while.
36
+ jest.setTimeout(120000);
37
+
38
+ // Navigate with retry + exponential backoff, then give the page a moment to
39
+ // settle so late-loading content and images are present before we capture.
40
+ async function navigateWithRetry(page, url) {
41
+ await retry(
42
+ async () => {
43
+ await page.goto(url, {
44
+ waitUntil: 'networkidle0',
45
+ timeout: 60000,
46
+ });
47
+ },
48
+ {
49
+ retries: 3,
50
+ baseDelay: 2000,
51
+ onRetry: (err, attempt, delay) => {
52
+ console.log(
53
+ `Navigation retry ${attempt} for ${url} after ${delay}ms: ${err.message}`
54
+ );
55
+ },
56
+ }
57
+ );
58
+ await new Promise((resolve) => setTimeout(resolve, 5000));
59
+ }
60
+
61
+ // Run the full matrix (Markdown + image) once per supported engine.
62
+ describe.each(['puppeteer', 'playwright'])(
63
+ 'Wikipedia Page Download (%s engine)',
64
+ (engine) => {
65
+ describeIfLive(`${engine}`, () => {
66
+ let browser;
67
+ let page;
68
+
69
+ beforeAll(async () => {
70
+ browser = await createBrowser(engine);
71
+ page = await browser.newPage();
72
+ await page.setViewport({ width: 1280, height: 800 });
73
+ await navigateWithRetry(page, WIKIPEDIA_URL);
74
+ });
75
+
76
+ afterAll(async () => {
77
+ if (browser) {
78
+ await browser.close();
79
+ }
80
+ });
81
+
82
+ it('downloads the Wikipedia page as Markdown', async () => {
83
+ const html = await page.content();
84
+ expect(html).toMatch(/<html/i);
85
+ expect(html.length).toBeGreaterThan(1000);
86
+
87
+ const markdown = convertHtmlToMarkdown(html, WIKIPEDIA_URL);
88
+
89
+ // Markdown should carry the page's real content...
90
+ expect(markdown).toContain('Wikipedia');
91
+ expect(markdown.length).toBeGreaterThan(500);
92
+ // ...and should contain markdown structure (headings and/or links)...
93
+ expect(markdown).toMatch(/(^#{1,6}\s)|(\[.*?\]\(.*?\))/m);
94
+ // ...but no longer be raw HTML document scaffolding.
95
+ expect(markdown).not.toMatch(/<html/i);
96
+ expect(markdown).not.toMatch(/<head[\s>]/i);
97
+ });
98
+
99
+ it('downloads the Wikipedia page as an image (PNG screenshot)', async () => {
100
+ const screenshot = await page.screenshot({ type: 'png' });
101
+
102
+ expect(screenshot).toBeInstanceOf(Buffer);
103
+ expect(screenshot.length).toBeGreaterThan(1000);
104
+ // Verify the PNG signature so we know it is a real image.
105
+ expect(screenshot.slice(0, 8)).toEqual(PNG_SIGNATURE);
106
+ });
107
+ });
108
+ }
109
+ );
110
+
111
+ describeIfLive('Wikipedia Page Download (engine parity)', () => {
112
+ it('both engines download Markdown and an image for the Wikipedia page', async () => {
113
+ const engines = ['puppeteer', 'playwright'];
114
+ const results = [];
115
+
116
+ for (const engine of engines) {
117
+ const browser = await createBrowser(engine);
118
+ try {
119
+ const page = await browser.newPage();
120
+ await page.setViewport({ width: 1280, height: 800 });
121
+ await navigateWithRetry(page, WIKIPEDIA_URL);
122
+
123
+ const html = await page.content();
124
+ const markdown = convertHtmlToMarkdown(html, WIKIPEDIA_URL);
125
+ const screenshot = await page.screenshot({ type: 'png' });
126
+
127
+ results.push({ engine, markdown, screenshot });
128
+ } finally {
129
+ await browser.close();
130
+ }
131
+ }
132
+
133
+ for (const { markdown, screenshot } of results) {
134
+ // Markdown captured from both engines.
135
+ expect(markdown).toContain('Wikipedia');
136
+ expect(markdown.length).toBeGreaterThan(500);
137
+ // Image captured from both engines.
138
+ expect(screenshot.slice(0, 8)).toEqual(PNG_SIGNATURE);
139
+ expect(screenshot.length).toBeGreaterThan(1000);
140
+ }
141
+ }, 180000);
142
+ });