import { test, expect } from '@playwright/test'; 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'); }); 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 }); 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'); }); 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'); }); await page.click('button.btn-success[title="Add environment"]'); await page.waitForTimeout(500); // Create 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(); }); 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 }) => { 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); }); });