Skip to main content
Glama
test-localStorage-injection.js7.1 kB
/** * @document Browser Automation Test for localStorage Injection * @version 1.0.0 * @status active * @author Claude Code * @created 2025-06-30 * @description Automated test to validate localStorage injection in Composer */ import { chromium } from 'playwright'; import fs from 'fs/promises'; import path from 'path'; import { fileURLToPath } from 'url'; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); // Load the injection script as a string for browser evaluation async function loadInjectionScript() { const scriptPath = path.join(__dirname, '../../tools/injection/localStorage-injection-v1.0.0.js'); const compositionPath = path.join(__dirname, '../../compositions/fotossintese-composer-json-v1.1.0.js'); // Read both files const injectionScript = await fs.readFile(scriptPath, 'utf-8'); const compositionScript = await fs.readFile(compositionPath, 'utf-8'); // Combine and adapt for browser context return ` // Define fotossintesesComposerJSON in browser context ${compositionScript.replace('export const', 'const')} // Injection functions ${injectionScript .replace(/import.*?;/g, '') // Remove imports .replace('export default', '') .replace(/export /g, '')} // Execute injection injectFotossinteseComposition(); `; } async function testLocalStorageInjection() { console.log('🎭 Starting localStorage injection test...\n'); const browser = await chromium.launch({ headless: false, // Show browser for debugging slowMo: 500 // Slow down for visibility }); try { const context = await browser.newContext({ viewport: { width: 1920, height: 1080 } }); const page = await context.newPage(); // Step 1: Navigate to Composer console.log('📍 Step 1: Navigating to Composer...'); const composerUrl = 'https://composer.euconquisto.com/composer'; await page.goto(composerUrl, { waitUntil: 'networkidle' }); // Take screenshot of initial state await page.screenshot({ path: 'logs/screenshots/injection/01-initial-composer.png', fullPage: true }); // Step 2: Execute injection script console.log('💉 Step 2: Injecting fotossíntese composition...'); const injectionScript = await loadInjectionScript(); const injectionResult = await page.evaluate(injectionScript); // Step 3: Verify localStorage content console.log('🔍 Step 3: Verifying localStorage content...'); const storageData = await page.evaluate(() => { const data = localStorage.getItem('rdp-composer-data'); if (!data) return null; try { const parsed = JSON.parse(data); return { hasData: true, compositionId: parsed.composition?.id, title: parsed.composition?.title, elementCount: parsed.composition?.elements?.length || 0, firstElement: parsed.composition?.elements?.[0]?.type }; } catch (e) { return { hasData: false, error: e.message }; } }); console.log('📦 localStorage verification:', storageData); // Take screenshot after injection await page.screenshot({ path: 'logs/screenshots/injection/02-after-injection.png', fullPage: true }); // Step 4: Navigate to editor to trigger composition load console.log('🎨 Step 4: Navigating to editor mode...'); // Try to find and click edit/new composition button // This may need adjustment based on actual Composer UI await page.waitForTimeout(2000); // Look for common editor triggers const editorTriggers = [ 'button:has-text("Nova Composição")', 'button:has-text("New Composition")', 'a[href*="/editor"]', 'button[class*="create"]', 'button[class*="new"]' ]; let foundTrigger = false; for (const selector of editorTriggers) { try { await page.click(selector, { timeout: 5000 }); foundTrigger = true; console.log(`✅ Clicked editor trigger: ${selector}`); break; } catch (e) { // Continue trying other selectors } } if (!foundTrigger) { console.log('⚠️ Could not find editor trigger, attempting direct navigation...'); // Try direct navigation to editor await page.goto(`${composerUrl}/editor`, { waitUntil: 'networkidle' }); } // Wait for potential composition load await page.waitForTimeout(3000); // Take screenshot of editor state await page.screenshot({ path: 'logs/screenshots/injection/03-editor-state.png', fullPage: true }); // Step 5: Validate composition rendering console.log('✨ Step 5: Validating composition rendering...'); // Check for composition elements const validationResult = await page.evaluate(() => { // Look for common Composer element indicators const indicators = { hasTitle: !!document.querySelector('*[class*="title"]:has-text("Fotossíntese")'), hasHeader: !!document.querySelector('*[class*="head-1"], *[class*="header"]'), hasContent: !!document.querySelector('*[class*="text-1"], *[class*="content"]'), hasWidgets: document.querySelectorAll('*[class*="widget"], *[class*="element"]').length, visibleText: document.body.innerText.includes('Fotossíntese') || document.body.innerText.includes('fotossíntese') }; return indicators; }); console.log('🎯 Validation results:', validationResult); // Take final screenshot await page.screenshot({ path: 'logs/screenshots/injection/04-final-validation.png', fullPage: true }); // Generate test report const testReport = { timestamp: new Date().toISOString(), success: !!storageData?.hasData && validationResult.visibleText, localStorage: storageData, rendering: validationResult, screenshots: [ '01-initial-composer.png', '02-after-injection.png', '03-editor-state.png', '04-final-validation.png' ] }; console.log('\n📊 Test Summary:'); console.log('================'); console.log(`✅ localStorage injection: ${storageData?.hasData ? 'SUCCESS' : 'FAILED'}`); console.log(`✅ Composition detected: ${validationResult.visibleText ? 'YES' : 'NO'}`); console.log(`📍 Composition ID: ${storageData?.compositionId || 'N/A'}`); console.log(`📝 Title: ${storageData?.title || 'N/A'}`); console.log(`🧩 Elements: ${storageData?.elementCount || 0}`); return testReport; } catch (error) { console.error('❌ Test failed:', error); throw error; } finally { await browser.close(); } } // Run the test testLocalStorageInjection() .then(report => { console.log('\n✅ Test completed successfully!'); process.exit(0); }) .catch(error => { console.error('\n❌ Test failed:', error); process.exit(1); });

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/rkm097git/euconquisto-composer-mcp-poc'

If you have feedback or need assistance with the MCP directory API, please join our Discord server