fix(builder): VideoBlock parses more YouTube/Vimeo URL shapes (D4)
Extend detectVideoType to handle youtube.com/shorts/ID, youtube.com/live/ID, youtube.com/watch?...&v=ID (v not the first query param), and Vimeo private-hash URLs (vimeo.com/ID/HASH -> ?h=HASH player param). Existing shapes (youtu.be/ID, youtube.com/embed/ID, youtube.com/watch?v=ID, vimeo.com/ID, direct files) keep working. The emitted embed src still passes through safeUrl unchanged. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,61 @@
|
||||
import { describe, test, expect } from 'vitest';
|
||||
import { VideoBlock } from './VideoBlock';
|
||||
|
||||
const toHtml = (VideoBlock as any).toHtml;
|
||||
|
||||
function embedSrc(videoUrl: string): string {
|
||||
const { html } = toHtml({ videoUrl }, '');
|
||||
const m = html.match(/<iframe src="([^"]+)"/) || html.match(/<video src="([^"]+)"/);
|
||||
return m ? m[1].replace(/&/g, '&') : '';
|
||||
}
|
||||
|
||||
describe('VideoBlock URL parsing (D4)', () => {
|
||||
test('youtube.com/watch?v=ID (existing case) resolves to embed URL', () => {
|
||||
expect(embedSrc('https://www.youtube.com/watch?v=dQw4w9WgXcQ')).toContain('youtube.com/embed/dQw4w9WgXcQ');
|
||||
});
|
||||
|
||||
test('youtu.be/ID resolves to embed URL', () => {
|
||||
expect(embedSrc('https://youtu.be/dQw4w9WgXcQ')).toContain('youtube.com/embed/dQw4w9WgXcQ');
|
||||
});
|
||||
|
||||
test('youtube.com/embed/ID (existing case) resolves to embed URL', () => {
|
||||
expect(embedSrc('https://www.youtube.com/embed/dQw4w9WgXcQ')).toContain('youtube.com/embed/dQw4w9WgXcQ');
|
||||
});
|
||||
|
||||
test('youtube.com/shorts/ID resolves to embed URL', () => {
|
||||
expect(embedSrc('https://www.youtube.com/shorts/dQw4w9WgXcQ')).toContain('youtube.com/embed/dQw4w9WgXcQ');
|
||||
});
|
||||
|
||||
test('youtube.com/live/ID resolves to embed URL', () => {
|
||||
expect(embedSrc('https://www.youtube.com/live/dQw4w9WgXcQ')).toContain('youtube.com/embed/dQw4w9WgXcQ');
|
||||
});
|
||||
|
||||
test('youtube.com/watch?...&v=ID (v not first param) resolves to embed URL', () => {
|
||||
expect(embedSrc('https://www.youtube.com/watch?list=PLxyz&v=dQw4w9WgXcQ&index=3')).toContain('youtube.com/embed/dQw4w9WgXcQ');
|
||||
});
|
||||
|
||||
test('vimeo.com/ID (existing case) resolves to player URL', () => {
|
||||
expect(embedSrc('https://vimeo.com/123456789')).toContain('https://player.vimeo.com/video/123456789');
|
||||
});
|
||||
|
||||
test('vimeo.com/ID/HASH (private video) resolves to player URL with hash param', () => {
|
||||
const src = embedSrc('https://vimeo.com/123456789/abcdef1234');
|
||||
expect(src).toContain('https://player.vimeo.com/video/123456789');
|
||||
expect(src).toContain('h=abcdef1234');
|
||||
});
|
||||
|
||||
test('direct .mp4 file still works', () => {
|
||||
const { html } = toHtml({ videoUrl: 'https://example.com/clip.mp4' }, '');
|
||||
expect(html).toContain('<video src="https://example.com/clip.mp4"');
|
||||
});
|
||||
|
||||
test('unrecognized URL yields no output (type "none")', () => {
|
||||
const { html } = toHtml({ videoUrl: 'not-a-real-video-url' }, '');
|
||||
expect(html).toBe('');
|
||||
});
|
||||
|
||||
test('emitted src is safeUrl-wrapped: javascript: scheme never reaches output', () => {
|
||||
const { html } = toHtml({ videoUrl: 'javascript:alert(1)' }, '');
|
||||
expect(html).not.toContain('javascript:');
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user