media-url-extract.test.mjs
189 lines 6.8 KB
Raw
sha256:8d46372e39d2d5a54fd93a8b1c27922fe0d9b22a72197345f1d2c71701cc4ce2 feat(auth): persistent login system + C7 session introspection Human minor ⚠ breaking 16 days ago
1 /**
2 * Tests for lib/media-url-extract.mjs — image and video URL extraction from markdown.
3 */
4 import { describe, it } from 'node:test';
5 import assert from 'node:assert';
6 import { extractImageUrls, extractVideoUrls, MAX_URLS_PER_NOTE } from '../lib/media-url-extract.mjs';
7
8 describe('extractImageUrls', () => {
9 it('extracts a basic markdown image', () => {
10 const body = 'Some text\n![my alt](https://example.com/img.png)\nmore text';
11 const result = extractImageUrls(body);
12 assert.strictEqual(result.length, 1);
13 assert.strictEqual(result[0].alt, 'my alt');
14 assert.strictEqual(result[0].url, 'https://example.com/img.png');
15 assert.strictEqual(result[0].mimeType, 'image/png');
16 });
17
18 it('extracts multiple images', () => {
19 const body = [
20 '![a](https://ex.com/a.png)',
21 '![b](https://ex.com/b.jpg)',
22 '![c](https://ex.com/c.gif)',
23 ].join('\n');
24 const result = extractImageUrls(body);
25 assert.strictEqual(result.length, 3);
26 assert.strictEqual(result[0].mimeType, 'image/png');
27 assert.strictEqual(result[1].mimeType, 'image/jpeg');
28 assert.strictEqual(result[2].mimeType, 'image/gif');
29 });
30
31 it('deduplicates same URL referenced twice', () => {
32 const body = '![a](https://ex.com/img.png)\n![b](https://ex.com/img.png)';
33 const result = extractImageUrls(body);
34 assert.strictEqual(result.length, 1);
35 });
36
37 it('preserves query strings but detects extension correctly', () => {
38 const body = '![](https://ex.com/img.png?token=abc&size=large)';
39 const result = extractImageUrls(body);
40 assert.strictEqual(result.length, 1);
41 assert.strictEqual(result[0].mimeType, 'image/png');
42 assert.ok(result[0].url.includes('?token=abc'));
43 });
44
45 it('handles .jpg and .jpeg as image/jpeg', () => {
46 const body = '![](https://ex.com/a.jpg)\n![](https://ex.com/b.jpeg)';
47 const result = extractImageUrls(body);
48 assert.strictEqual(result.length, 2);
49 assert.strictEqual(result[0].mimeType, 'image/jpeg');
50 assert.strictEqual(result[1].mimeType, 'image/jpeg');
51 });
52
53 it('handles .webp as image/webp', () => {
54 const body = '![](https://ex.com/photo.webp)';
55 const result = extractImageUrls(body);
56 assert.strictEqual(result.length, 1);
57 assert.strictEqual(result[0].mimeType, 'image/webp');
58 });
59
60 it('returns empty array when no images', () => {
61 const body = 'Just plain text\nwith no images at all.';
62 const result = extractImageUrls(body);
63 assert.strictEqual(result.length, 0);
64 });
65
66 it('extracts bare image URL on its own line', () => {
67 const body = 'Text before\nhttps://example.com/photo.jpg\nText after';
68 const result = extractImageUrls(body);
69 assert.strictEqual(result.length, 1);
70 assert.strictEqual(result[0].url, 'https://example.com/photo.jpg');
71 assert.strictEqual(result[0].alt, '');
72 });
73
74 it('caps at MAX_URLS_PER_NOTE', () => {
75 const lines = [];
76 for (let i = 0; i < 60; i++) {
77 lines.push(`![img${i}](https://ex.com/img${i}.png)`);
78 }
79 const result = extractImageUrls(lines.join('\n'));
80 assert.strictEqual(result.length, MAX_URLS_PER_NOTE);
81 });
82
83 it('ignores data: URIs', () => {
84 const body = '![](data:image/png;base64,iVBORw0KGgoAAAANSUhEUg==)';
85 const result = extractImageUrls(body);
86 assert.strictEqual(result.length, 0);
87 });
88
89 it('does not extract video extensions as images', () => {
90 const body = '![](https://ex.com/clip.mp4)';
91 const result = extractImageUrls(body);
92 assert.strictEqual(result.length, 0);
93 });
94
95 it('returns empty for null/undefined input', () => {
96 assert.deepStrictEqual(extractImageUrls(null), []);
97 assert.deepStrictEqual(extractImageUrls(undefined), []);
98 assert.deepStrictEqual(extractImageUrls(''), []);
99 });
100
101 it('handles URLs with fragment identifiers', () => {
102 const body = '![](https://ex.com/img.png#section)';
103 const result = extractImageUrls(body);
104 assert.strictEqual(result.length, 1);
105 assert.strictEqual(result[0].mimeType, 'image/png');
106 });
107
108 it('does not extract non-image bare URLs', () => {
109 const body = 'https://example.com/page.html\nhttps://example.com/file.pdf';
110 const result = extractImageUrls(body);
111 assert.strictEqual(result.length, 0);
112 });
113 });
114
115 describe('extractVideoUrls', () => {
116 it('extracts .mp4 URL', () => {
117 const body = 'Check this out\nhttps://ex.com/clip.mp4\nnice';
118 const result = extractVideoUrls(body);
119 assert.strictEqual(result.length, 1);
120 assert.strictEqual(result[0].url, 'https://ex.com/clip.mp4');
121 assert.strictEqual(result[0].mimeType, 'video/mp4');
122 });
123
124 it('extracts .webm URL', () => {
125 const body = 'https://ex.com/clip.webm';
126 const result = extractVideoUrls(body);
127 assert.strictEqual(result.length, 1);
128 assert.strictEqual(result[0].mimeType, 'video/webm');
129 });
130
131 it('extracts .mov URL', () => {
132 const body = 'https://ex.com/clip.mov';
133 const result = extractVideoUrls(body);
134 assert.strictEqual(result.length, 1);
135 assert.strictEqual(result[0].mimeType, 'video/quicktime');
136 });
137
138 it('returns empty when no video URLs', () => {
139 const body = 'Just text and ![](https://ex.com/img.png)';
140 const result = extractVideoUrls(body);
141 assert.strictEqual(result.length, 0);
142 });
143
144 it('extracts video URL inside image markdown syntax', () => {
145 const body = '![demo](https://ex.com/clip.mp4)';
146 const result = extractVideoUrls(body);
147 assert.strictEqual(result.length, 1);
148 assert.strictEqual(result[0].url, 'https://ex.com/clip.mp4');
149 });
150
151 it('deduplicates video URLs', () => {
152 const body = 'https://ex.com/clip.mp4\nhttps://ex.com/clip.mp4';
153 const result = extractVideoUrls(body);
154 assert.strictEqual(result.length, 1);
155 });
156
157 it('returns empty for null/undefined', () => {
158 assert.deepStrictEqual(extractVideoUrls(null), []);
159 assert.deepStrictEqual(extractVideoUrls(undefined), []);
160 assert.deepStrictEqual(extractVideoUrls(''), []);
161 });
162
163 it('handles video URL with query string', () => {
164 const body = 'https://ex.com/clip.mp4?token=xyz';
165 const result = extractVideoUrls(body);
166 assert.strictEqual(result.length, 1);
167 assert.strictEqual(result[0].mimeType, 'video/mp4');
168 assert.ok(result[0].url.includes('?token=xyz'));
169 });
170 });
171
172 describe('mixed content', () => {
173 it('separates images and videos correctly', () => {
174 const body = [
175 '![photo](https://ex.com/photo.jpg)',
176 'https://ex.com/demo.mp4',
177 '![diagram](https://ex.com/diagram.png)',
178 'https://ex.com/screen.webm',
179 ].join('\n');
180 const images = extractImageUrls(body);
181 const videos = extractVideoUrls(body);
182 assert.strictEqual(images.length, 2);
183 assert.strictEqual(videos.length, 2);
184 assert.strictEqual(images[0].mimeType, 'image/jpeg');
185 assert.strictEqual(images[1].mimeType, 'image/png');
186 assert.strictEqual(videos[0].mimeType, 'video/mp4');
187 assert.strictEqual(videos[1].mimeType, 'video/webm');
188 });
189 });
File History 2 commits
sha256:8d46372e39d2d5a54fd93a8b1c27922fe0d9b22a72197345f1d2c71701cc4ce2 feat(auth): persistent login system + C7 session introspection Human minor 16 days ago