Includes new page templates (fitness-gym, nonprofit, online-course, photography-studio, real-estate, startup-company, travel-blog, wedding-invitation) with thumbnail SVGs, test specs, documentation files, and minor updates to index.html, router.php, and playwright config. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
131 lines
5.3 KiB
JavaScript
131 lines
5.3 KiB
JavaScript
const { test, expect } = require('@playwright/test');
|
|
const { waitForEditor, addBlockById, clearCanvas } = require('./helpers');
|
|
|
|
test.describe('YouTube Embed Fix (Error 153)', () => {
|
|
test.beforeEach(async ({ page }) => {
|
|
await waitForEditor(page);
|
|
await clearCanvas(page);
|
|
});
|
|
|
|
test('should use youtube-nocookie.com domain for YouTube embeds', async ({ page }) => {
|
|
// Add Video block via API
|
|
const result = await addBlockById(page, 'video-block');
|
|
expect(result.success).toBe(true);
|
|
await page.waitForTimeout(500);
|
|
|
|
// Select the video wrapper via API
|
|
await page.evaluate(() => {
|
|
const editor = window.editor;
|
|
const wrapper = editor.getWrapper();
|
|
const videoWrapper = wrapper.find('[data-video-wrapper]')[0];
|
|
if (videoWrapper) editor.select(videoWrapper);
|
|
});
|
|
await page.waitForTimeout(500);
|
|
|
|
// Open Settings tab
|
|
await page.locator('button[data-panel="traits"]').click();
|
|
await page.waitForTimeout(500);
|
|
|
|
// Find Video URL input in traits container
|
|
const videoUrlInput = page.locator('#traits-container input[placeholder*="YouTube"]');
|
|
await expect(videoUrlInput).toBeVisible({ timeout: 5000 });
|
|
|
|
const testYouTubeUrl = 'https://www.youtube.com/watch?v=dQw4w9WgXcQ';
|
|
await videoUrlInput.fill(testYouTubeUrl);
|
|
await videoUrlInput.press('Enter');
|
|
await page.waitForTimeout(1000);
|
|
|
|
// Click "Apply Video" button if present
|
|
const applyBtn = page.locator('#traits-container button:has-text("Apply Video")');
|
|
if (await applyBtn.isVisible({ timeout: 1000 }).catch(() => false)) {
|
|
await applyBtn.click();
|
|
await page.waitForTimeout(1000);
|
|
}
|
|
|
|
// Verify via editor HTML output (canvas renders iframes as divs)
|
|
const html = await page.evaluate(() => window.editor.getHtml());
|
|
expect(html).toContain('youtube-nocookie.com');
|
|
expect(html).toContain('embed/dQw4w9WgXcQ');
|
|
expect(html).not.toContain('www.youtube.com/embed');
|
|
});
|
|
|
|
test('should have correct referrerpolicy attribute', async ({ page }) => {
|
|
// Add Video block and check via editor HTML
|
|
const result = await addBlockById(page, 'video-block');
|
|
expect(result.success).toBe(true);
|
|
await page.waitForTimeout(500);
|
|
|
|
const html = await page.evaluate(() => window.editor.getHtml());
|
|
expect(html).toContain('referrerpolicy="strict-origin-when-cross-origin"');
|
|
});
|
|
|
|
test('should have required allow attributes', async ({ page }) => {
|
|
// Add Video block and check via editor HTML
|
|
const result = await addBlockById(page, 'video-block');
|
|
expect(result.success).toBe(true);
|
|
await page.waitForTimeout(500);
|
|
|
|
const html = await page.evaluate(() => window.editor.getHtml());
|
|
expect(html).toContain('accelerometer');
|
|
expect(html).toContain('encrypted-media');
|
|
expect(html).toContain('gyroscope');
|
|
expect(html).toContain('picture-in-picture');
|
|
});
|
|
|
|
test('should work with youtu.be short URLs', async ({ page }) => {
|
|
// Add Video block
|
|
const result = await addBlockById(page, 'video-block');
|
|
expect(result.success).toBe(true);
|
|
await page.waitForTimeout(500);
|
|
|
|
// Select the wrapper
|
|
await page.evaluate(() => {
|
|
const editor = window.editor;
|
|
const wrapper = editor.getWrapper();
|
|
const videoWrapper = wrapper.find('[data-video-wrapper]')[0];
|
|
if (videoWrapper) editor.select(videoWrapper);
|
|
});
|
|
await page.waitForTimeout(500);
|
|
|
|
// Open Settings
|
|
await page.locator('button[data-panel="traits"]').click();
|
|
await page.waitForTimeout(500);
|
|
|
|
// Fill URL
|
|
const videoUrlInput = page.locator('#traits-container input[placeholder*="YouTube"]');
|
|
await expect(videoUrlInput).toBeVisible({ timeout: 5000 });
|
|
|
|
await videoUrlInput.fill('https://youtu.be/dQw4w9WgXcQ');
|
|
await videoUrlInput.press('Enter');
|
|
await page.waitForTimeout(1000);
|
|
|
|
// Click Apply if present
|
|
const applyBtn = page.locator('#traits-container button:has-text("Apply Video")');
|
|
if (await applyBtn.isVisible({ timeout: 1000 }).catch(() => false)) {
|
|
await applyBtn.click();
|
|
await page.waitForTimeout(1000);
|
|
}
|
|
|
|
// Verify via editor HTML
|
|
const html = await page.evaluate(() => window.editor.getHtml());
|
|
expect(html).toContain('youtube-nocookie.com');
|
|
expect(html).toContain('embed/dQw4w9WgXcQ');
|
|
});
|
|
|
|
test('video block uses unified Video element with iframe and video tags', async ({ page }) => {
|
|
// Add Video block and verify structure via editor HTML
|
|
const result = await addBlockById(page, 'video-block');
|
|
expect(result.success).toBe(true);
|
|
await page.waitForTimeout(500);
|
|
|
|
const html = await page.evaluate(() => window.editor.getHtml());
|
|
|
|
// The block should contain both iframe and video elements
|
|
expect(html).toContain('<iframe');
|
|
expect(html).toContain('class="video-frame"');
|
|
expect(html).toContain('<video');
|
|
expect(html).toContain('class="video-player"');
|
|
expect(html).toContain('class="video-wrapper"');
|
|
});
|
|
});
|