Files
site-builder/tests/helpers.js
Josh Knapp a71b58c2c7 Initial commit: Site Builder with PHP API backend
Visual drag-and-drop website builder using GrapesJS with:
- Multi-page editor with live preview
- File-based asset storage via PHP API (no localStorage base64)
- Template library, Docker support, and Playwright test suite

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 19:25:42 +00:00

107 lines
3.2 KiB
JavaScript

/**
* 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,
};