diff --git a/global-setup.ts b/global-setup.ts new file mode 100644 index 0000000..71a2737 --- /dev/null +++ b/global-setup.ts @@ -0,0 +1,71 @@ +import { chromium } from '@playwright/test'; + +const WIZARD_URL = process.env.WIZARD_URL || 'http://wizard:8080/wizard'; +const WIZARD_API_URL = process.env.WIZARD_API_URL || 'http://wizard:8080'; + +async function setupWizard() { + console.log('🔧 Running global setup: Configure wizard...'); + + const browser = await chromium.launch(); + const page = await browser.newPage(); + + try { + // Navigate to frontend - should redirect to wizard since not configured + const frontendURL = process.env.FRONTEND_URL || 'http://frontend:3000'; + console.log(`📱 Navigating to ${frontendURL}...`); + + await page.goto(frontendURL); + await page.waitForLoadState('networkidle'); + + // Step 0: Welcome + await page.waitForSelector('h1:has-text("HarborForge")', { timeout: 10000 }); + + const connectButton = page.locator('button:has-text("Connect to Wizard")'); + if (await connectButton.isVisible().catch(() => false)) { + console.log('🔗 Clicking Connect to Wizard...'); + await connectButton.click(); + + // Wait for step 1: Database + console.log('📝 Filling Database configuration...'); + await page.waitForSelector('h2:has-text("Database configuration")', { timeout: 10000 }); + await page.locator('label:has-text("Host") input').fill('mysql'); + await page.locator('label:has-text("Port") input').fill('3306'); + await page.locator('label:has-text("Username") input').fill('harborforge'); + await page.locator('label:has-text("Password") input').fill('harborforge_pass'); + await page.locator('label:has-text("Database") input').fill('harborforge'); + await page.click('button:has-text("Next")'); + + // Wait for step 2: Admin + console.log('📝 Filling Admin account...'); + await page.waitForSelector('h2:has-text("Admin account")', { timeout: 10000 }); + await page.locator('label:has-text("Password") input').fill('admin123'); + await page.locator('label:has-text("Email") input').fill('admin@test.com'); + await page.locator('label:has-text("Full name") input').fill('Test Admin'); + await page.click('button:has-text("Next")'); + + // Wait for step 3: Backend URL + console.log('📝 Filling Backend URL...'); + await page.waitForSelector('h2:has-text("Backend URL")', { timeout: 10000 }); + const backendURL = process.env.BACKEND_URL || 'http://backend:8000'; + await page.locator('label:has-text("Backend Base URL") input').fill(backendURL); + await page.click('button:has-text("Finish setup")'); + + // Wait for step 4: Complete + console.log('✅ Waiting for setup complete...'); + await page.waitForSelector('h2:has-text("Setup complete!")', { timeout: 10000 }); + + console.log('✅ Wizard configured successfully!'); + } else { + console.log('⚠️ Wizard already configured or on main page'); + } + + await browser.close(); + return; + } catch (error) { + console.error('❌ Wizard setup failed:', error); + await browser.close(); + throw error; + } +} + +export default setupWizard; diff --git a/playwright.config.ts b/playwright.config.ts index 216fee0..3dd484b 100644 --- a/playwright.config.ts +++ b/playwright.config.ts @@ -1,4 +1,5 @@ import { defineConfig, devices } from '@playwright/test'; +import path from 'path'; const baseURL = process.env.FRONTEND_URL || 'http://frontend:3000'; @@ -19,5 +20,8 @@ export default defineConfig({ use: { ...devices['Desktop Chrome'] }, }, ], - // Don't start webServer - services are started via docker-compose + // Global setup runs before all tests - configure wizard once + globalSetup: path.join(__dirname, 'global-setup.ts'), + // Global teardown runs after all tests + globalTeardown: undefined, }); diff --git a/tests/wizard.spec.ts b/tests/wizard.spec.ts index 5079d02..783de1c 100644 --- a/tests/wizard.spec.ts +++ b/tests/wizard.spec.ts @@ -3,52 +3,13 @@ import { test, expect } from '@playwright/test'; const FRONTEND_URL = process.env.FRONTEND_URL || 'http://frontend:3000'; test.describe('Setup Wizard', () => { - test('complete wizard flow through frontend', async ({ page }) => { - // Navigate to frontend - await page.goto(FRONTEND_URL); + test('frontend loads and shows main page after wizard configuration', async ({ page }) => { + // Navigate to frontend - wizard should be configured by globalSetup + await page.goto(FRONTEND_URL); await page.waitForLoadState('networkidle'); - // Step 0: Welcome + // Should now show main page (not wizard redirect) + // After wizard config, frontend should load normally await expect(page.locator('h1')).toContainText('HarborForge', { timeout: 10000 }); - - const connectButton = page.locator('button:has-text("Connect to Wizard")'); - if (await connectButton.isVisible().catch(() => false)) { - await connectButton.click(); - - // Wait for step 1: Database - await page.waitForSelector('h2:has-text("Database configuration")', { timeout: 10000 }); - await page.locator('label:has-text("Host") input').fill('mysql'); - await page.locator('label:has-text("Port") input').fill('3306'); - await page.locator('label:has-text("Username") input').fill('harborforge'); - await page.locator('label:has-text("Password") input').fill('harborforge_pass'); - await page.locator('label:has-text("Database") input').fill('harborforge'); - await page.click('button:has-text("Next")'); - - // Wait for step 2: Admin - await page.waitForSelector('h2:has-text("Admin account")', { timeout: 10000 }); - - // Debug: print page content before filling - console.log('Page URL at Admin step:', page.url()); - console.log('Page content:', await page.content()); - - await page.locator('label:has-text("Password") input').fill('admin123'); - await page.locator('label:has-text("Email") input').fill('admin@test.com'); - await page.locator('label:has-text("Full name") input').fill('Test Admin'); - - // Click Next - might fail if password is empty (validation) - await page.click('button:has-text("Next")'); - - // Wait for step 3: Backend URL - await page.waitForSelector('h2:has-text("Backend URL")', { timeout: 15000 }); - - await page.locator('label:has-text("Backend Base URL") input').fill('http://backend:8000'); - await page.click('button:has-text("Finish setup")'); - - // Wait for step 4: Complete - await expect(page.locator('h2')).toContainText('Setup complete!', { timeout: 10000 }); - } else { - // Wizard was already configured - await expect(page.locator('h1')).toContainText('HarborForge'); - } }); });