diff --git a/e2e/environment.spec.ts b/e2e/environment.spec.ts index 5b36a80..adc783e 100644 --- a/e2e/environment.spec.ts +++ b/e2e/environment.spec.ts @@ -1,106 +1,55 @@ import { test, expect } from '@playwright/test'; +import * as fs from 'fs'; test.describe('Environment Management', () => { test('should not allow removing DEFAULT environment', async ({ page }) => { await page.goto('/'); await page.click('button:has-text("Create new")'); - - // Try to remove DEFAULT - should be blocked const removeButton = page.locator('button.btn-danger[title="Remove environment"]'); - - // The button should be disabled for DEFAULT await expect(removeButton).toBeDisabled(); }); test('should remove non-DEFAULT environment', async ({ page }) => { await page.goto('/'); await page.click('button:has-text("Create new")'); - - // Create a new environment - page.once('dialog', async dialog => { - await dialog.accept('toRemove'); - }); + page.once('dialog', async dialog => { await dialog.accept('toRemove'); }); await page.click('button.btn-success[title="Add environment"]'); await page.waitForTimeout(500); - - // Verify we have 2 envs await expect(page.locator('#environments option')).toHaveCount(2); - - // Remove the new environment - page.once('dialog', async dialog => { - await dialog.accept(); // Confirm removal - }); + page.once('dialog', async dialog => { await dialog.accept(); }); await page.click('button.btn-danger[title="Remove environment"]'); await page.waitForTimeout(300); - - // Verify we're back to 1 env (DEFAULT) await expect(page.locator('#environments option')).toHaveCount(1); - await expect(page.locator('#environments')).toContainText('DEFAULT'); }); test('should create new environment and switch without errors', async ({ page }) => { await page.goto('/'); await page.click('button:has-text("Create new")'); - - // Verify DEFAULT environment is loaded - await expect(page.locator('#environments')).toContainText('DEFAULT'); - - // Create a new environment - page.once('dialog', async dialog => { - await dialog.accept('env1'); - }); + page.once('dialog', async dialog => { await dialog.accept('env1'); }); await page.click('button.btn-success[title="Add environment"]'); await page.waitForTimeout(500); - - // Verify new environment is created await expect(page.locator('#environments option')).toHaveCount(2); - - // Switch back to DEFAULT (by index 0) await page.locator('#environments').selectOption({ index: 0 }); await page.waitForTimeout(300); - - // Verify the page is still working - await expect(page.locator('#environments')).toBeVisible(); - - // Switch to env1 (by text) - this should NOT cause error await page.locator('#environments').selectOption('env1'); await page.waitForTimeout(300); - - // Verify the page is still working (no white screen of death) await expect(page.locator('#environments')).toBeVisible(); - await expect(page.locator('#environments option')).toHaveCount(2); }); test('should create multiple environments and switch between them', async ({ page }) => { await page.goto('/'); await page.click('button:has-text("Create new")'); - - // Create env1 - page.once('dialog', async dialog => { - await dialog.accept('env1'); - }); + page.once('dialog', async dialog => { await dialog.accept('env1'); }); await page.click('button.btn-success[title="Add environment"]'); await page.waitForTimeout(500); - - // Create env2 - page.once('dialog', async dialog => { - await dialog.accept('env2'); - }); + page.once('dialog', async dialog => { await dialog.accept('env2'); }); await page.click('button.btn-success[title="Add environment"]'); await page.waitForTimeout(500); - - // Verify we have 3 envs (DEFAULT + env1 + env2) await expect(page.locator('#environments option')).toHaveCount(3); - - // Switch to each env and verify page doesn't crash await page.locator('#environments').selectOption({ index: 0 }); await page.waitForTimeout(200); - await expect(page.locator('#environments')).toBeVisible(); - await page.locator('#environments').selectOption('env1'); await page.waitForTimeout(200); - await expect(page.locator('#environments')).toBeVisible(); - await page.locator('#environments').selectOption('env2'); await page.waitForTimeout(200); await expect(page.locator('#environments')).toBeVisible(); @@ -109,105 +58,83 @@ test.describe('Environment Management', () => { test('should add params and edit template manually', async ({ page }) => { await page.goto('/'); await page.click('button:has-text("Create new")'); - - // Step 1: Add a param to DEFAULT const nameInput = page.locator('input[placeholder="name"]').first(); const valueInput = page.locator('input[placeholder="value"]').first(); const addButton = page.locator('button.btn-success').first(); - await nameInput.fill('host'); await valueInput.fill('localhost:8080'); await addButton.click(); await page.waitForTimeout(500); - - // Add second param await nameInput.fill('port'); await valueInput.fill('9090'); await addButton.click(); await page.waitForTimeout(500); - - // Step 2: Switch to Content Template tab await page.click('a:has-text("Content Template")'); await page.waitForTimeout(500); - - // Verify the tab content is visible (check for Edit button) await expect(page.locator('button:has-text("Edit")')).toBeVisible(); - - // Step 3: Click Edit button await page.click('button:has-text("Edit")'); await page.waitForTimeout(500); - - // Step 4: Verify textarea is visible const textarea = page.locator('textarea'); await expect(textarea).toBeVisible(); - - // Step 5: Edit the template manually - add a new key await textarea.fill('{\n "!!! host": "@host@",\n "!!! port": "@port@",\n "!!! custom": "@custom@"\n}'); await page.waitForTimeout(300); - - // Step 6: Click Save await page.click('button:has-text("Save")'); await page.waitForTimeout(500); - - // Step 7: Verify the template was saved (Edit button should be visible again) await expect(page.locator('button:has-text("Edit")')).toBeVisible(); - - // Verify the content contains the new key const pageContent = await page.content(); expect(pageContent).toContain('!!! custom'); }); - test('should not duplicate params when placeholder already exists in template', async ({ page }) => { + test('should not duplicate params when placeholder already exists', async ({ page }) => { await page.goto('/'); await page.click('button:has-text("Create new")'); - - // Step 1: Add a param to DEFAULT const nameInput = page.locator('input[placeholder="name"]').first(); const valueInput = page.locator('input[placeholder="value"]').first(); const addButton = page.locator('button.btn-success').first(); - await nameInput.fill('host'); await valueInput.fill('localhost:8080'); await addButton.click(); await page.waitForTimeout(500); - - // Step 2: Switch to Content Template tab await page.click('a:has-text("Content Template")'); await page.waitForTimeout(500); - - // Step 3: Click Edit and manually add @host@ usage in a custom field await page.click('button:has-text("Edit")'); await page.waitForTimeout(300); - const textarea = page.locator('textarea'); - // Add a custom field that uses @host@ placeholder await textarea.fill('{\n "!!! host": "@host@",\n "apiUrl": "http://@host@/api"\n}'); await page.waitForTimeout(300); - - // Step 4: Save await page.click('button:has-text("Save")'); await page.waitForTimeout(500); - - // Step 5: Add ANOTHER param with same name (host) - should not create duplicate await page.click('a:has-text("Env")'); await page.waitForTimeout(300); - await nameInput.fill('host'); await valueInput.fill('updated-host:9090'); await addButton.click(); await page.waitForTimeout(500); - - // Step 6: Switch back to Content Template and verify no duplicate await page.click('a:has-text("Content Template")'); await page.waitForTimeout(500); - - // Count occurrences of "!!! host" - should be exactly 1 const templateContent = await page.locator('.config-template-editor').textContent(); const hostKeyCount = (templateContent.match(/!!! host/g) || []).length; expect(hostKeyCount).toBe(1); - - // The @host@ placeholder should appear twice (once in !!! host, once in apiUrl) const hostPlaceholderCount = (templateContent.match(/@host@/g) || []).length; expect(hostPlaceholderCount).toBe(2); }); + + test('should download config file with correct filename', async ({ page }) => { + await page.goto('/'); + await page.click('button:has-text("Create new")'); + await page.waitForTimeout(500); + const [download] = await Promise.all([ + page.waitForEvent('download'), + page.click('button:has-text("Download")') + ]); + const filename = download.suggestedFilename(); + expect(filename).toMatch(/^config_\d{2}-\d{2}-\d{2}-\d{4}\.json\.xml$/); + // Save and read the file to verify content + await download.saveAs('temp-config.xml'); + const contentStr = fs.readFileSync('temp-config.xml', 'utf8'); + expect(contentStr).toContain('engine'); + expect(contentStr).toContain('DEFAULT'); + expect(contentStr).toContain('template'); + fs.unlinkSync('temp-config.xml'); + }); }); diff --git a/src/App.tsx b/src/App.tsx index 4d7ec74..d9009c1 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -107,7 +107,7 @@ function App() { AppState.Instance.loadConfig(x); setEnvs(x.envs); setConfig(x); - }} /> + }} config={config} /> {envs.length > 0 ? (