/** * Shared test helpers for Site Builder Playwright tests */ const EDITOR_LOAD_TIMEOUT = 15000; /** * Wait for the GrapesJS editor to be fully initialized */ async function waitForEditor(page) { await page.goto('/', { waitUntil: 'domcontentloaded' }); await page.waitForFunction( () => window.editor && typeof window.editor.getWrapper === 'function' && typeof window.editor.getHtml === 'function', { timeout: EDITOR_LOAD_TIMEOUT } ); await page.waitForTimeout(1000); } /** * Wait for editor with a clean localStorage state */ async function freshEditor(page) { await page.goto('/', { waitUntil: 'domcontentloaded' }); await page.evaluate(() => { localStorage.clear(); }); await page.goto('/', { waitUntil: 'domcontentloaded' }); await page.waitForFunction( () => window.editor && typeof window.editor.getWrapper === 'function' && typeof window.editor.getHtml === 'function', { timeout: 50000, polling: 1000 } ); await page.waitForTimeout(2000); } /** * Add a block to the canvas by its block ID using the GrapesJS API */ async function addBlockById(page, blockId) { return await page.evaluate((id) => { const editor = window.editor; const block = editor.BlockManager.get(id); if (!block) { return { error: `Block '${id}' not found`, blocks: editor.BlockManager.getAll().map(b => b.id) }; } editor.addComponents(block.get('content')); return { success: true }; }, blockId); } /** * Clear the editor canvas using the GrapesJS API */ async function clearCanvas(page) { await page.evaluate(() => { const editor = window.editor; const wrapper = editor.getWrapper(); wrapper.components().reset(); editor.getStyle().reset(); }); await page.waitForTimeout(500); } /** * Select a component in the canvas by CSS selector */ async function selectComponent(page, selector) { return await page.evaluate((sel) => { const editor = window.editor; const wrapper = editor.getWrapper(); const found = wrapper.find(sel); if (found.length === 0) return { error: `Component '${sel}' not found` }; editor.select(found[0]); return { success: true }; }, selector); } /** * Click the Settings tab in the right panel */ async function openSettingsTab(page) { const settingsTab = page.locator('button[data-panel="traits"]'); await settingsTab.click(); await page.waitForTimeout(300); } /** * Find and expand a block category by name, then find a block within it */ async function findBlockInCategory(page, categoryName, blockLabel) { // Scroll blocks container and click the category title const category = page.locator('.gjs-block-category').filter({ has: page.locator('.gjs-title', { hasText: categoryName }) }); await category.locator('.gjs-title').click(); await page.waitForTimeout(300); return category.locator('.gjs-block').filter({ hasText: blockLabel }); } module.exports = { EDITOR_LOAD_TIMEOUT, waitForEditor, freshEditor, addBlockById, clearCanvas, selectComponent, openSettingsTab, findBlockInCategory, };