210 lines
9.4 KiB
TypeScript
210 lines
9.4 KiB
TypeScript
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("New Config")');
|
|
await page.waitForTimeout(500);
|
|
const removeButton = page.locator('button[title="Remove environment"]');
|
|
await expect(removeButton).toBeDisabled();
|
|
});
|
|
|
|
test('should remove non-DEFAULT environment', async ({ page }) => {
|
|
await page.goto('/');
|
|
await page.click('button:has-text("New Config")');
|
|
await page.waitForTimeout(500);
|
|
page.once('dialog', async dialog => { await dialog.accept('toRemove'); });
|
|
await page.click('button[title="Add environment"]');
|
|
await page.waitForTimeout(500);
|
|
await expect(page.locator('#environments option')).toHaveCount(2);
|
|
page.once('dialog', async dialog => { await dialog.accept(); });
|
|
await page.click('button[title="Remove environment"]');
|
|
await page.waitForTimeout(300);
|
|
await expect(page.locator('#environments option')).toHaveCount(1);
|
|
});
|
|
|
|
test('should create new environment and switch without errors', async ({ page }) => {
|
|
await page.goto('/');
|
|
await page.click('button:has-text("New Config")');
|
|
await page.waitForTimeout(500);
|
|
page.once('dialog', async dialog => { await dialog.accept('env1'); });
|
|
await page.click('button[title="Add environment"]');
|
|
await page.waitForTimeout(500);
|
|
await expect(page.locator('#environments option')).toHaveCount(2);
|
|
await page.locator('#environments').selectOption({ index: 0 });
|
|
await page.waitForTimeout(300);
|
|
await page.locator('#environments').selectOption('env1');
|
|
await page.waitForTimeout(300);
|
|
await expect(page.locator('#environments')).toBeVisible();
|
|
});
|
|
|
|
test('should create multiple environments and switch between them', async ({ page }) => {
|
|
await page.goto('/');
|
|
await page.click('button:has-text("New Config")');
|
|
await page.waitForTimeout(500);
|
|
page.once('dialog', async dialog => { await dialog.accept('env1'); });
|
|
await page.click('button[title="Add environment"]');
|
|
await page.waitForTimeout(500);
|
|
page.once('dialog', async dialog => { await dialog.accept('env2'); });
|
|
await page.click('button[title="Add environment"]');
|
|
await page.waitForTimeout(500);
|
|
await expect(page.locator('#environments option')).toHaveCount(3);
|
|
await page.locator('#environments').selectOption({ index: 0 });
|
|
await page.waitForTimeout(200);
|
|
await page.locator('#environments').selectOption('env1');
|
|
await page.waitForTimeout(200);
|
|
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("New Config")');
|
|
await page.waitForTimeout(500);
|
|
const nameInput = page.locator('input[placeholder="Parameter name"]').first();
|
|
const valueInput = page.locator('input[placeholder="Parameter value"]').first();
|
|
const addButton = page.locator('button[title="Add parameter"]').first();
|
|
await nameInput.fill('host');
|
|
await valueInput.fill('localhost:8080');
|
|
await addButton.click();
|
|
await page.waitForTimeout(500);
|
|
await nameInput.fill('port');
|
|
await valueInput.fill('9090');
|
|
await addButton.click();
|
|
await page.waitForTimeout(500);
|
|
await page.click('button:has-text("Content Template")');
|
|
await page.waitForTimeout(500);
|
|
await expect(page.locator('button:has-text("Edit Template")')).toBeVisible();
|
|
await page.click('button:has-text("Edit Template")');
|
|
await page.waitForTimeout(500);
|
|
const textarea = page.locator('textarea');
|
|
await expect(textarea).toBeVisible();
|
|
await textarea.fill('{\n "!!! host": "@host@",\n "!!! port": "@port@",\n "!!! custom": "@custom@"\n}');
|
|
await page.waitForTimeout(300);
|
|
await page.click('button:has-text("Save Changes")');
|
|
await page.waitForTimeout(500);
|
|
await expect(page.locator('button:has-text("Edit Template")')).toBeVisible();
|
|
const pageContent = await page.content();
|
|
expect(pageContent).toContain('!!! custom');
|
|
});
|
|
|
|
test('should not duplicate params when placeholder already exists', async ({ page }) => {
|
|
await page.goto('/');
|
|
await page.click('button:has-text("New Config")');
|
|
await page.waitForTimeout(500);
|
|
const nameInput = page.locator('input[placeholder="Parameter name"]').first();
|
|
const valueInput = page.locator('input[placeholder="Parameter value"]').first();
|
|
const addButton = page.locator('button[title="Add parameter"]').first();
|
|
await nameInput.fill('host');
|
|
await valueInput.fill('localhost:8080');
|
|
await addButton.click();
|
|
await page.waitForTimeout(500);
|
|
await page.click('button:has-text("Content Template")');
|
|
await page.waitForTimeout(500);
|
|
await page.click('button:has-text("Edit Template")');
|
|
await page.waitForTimeout(300);
|
|
const textarea = page.locator('textarea');
|
|
await textarea.fill('{\n "!!! host": "@host@",\n "apiUrl": "http://@host@/api"\n}');
|
|
await page.waitForTimeout(300);
|
|
await page.click('button:has-text("Save Changes")');
|
|
await page.waitForTimeout(500);
|
|
await page.click('button:has-text("Env")');
|
|
await page.waitForTimeout(300);
|
|
await nameInput.fill('host');
|
|
await valueInput.fill('updated-host:9090');
|
|
await addButton.click();
|
|
await page.waitForTimeout(500);
|
|
await page.click('button:has-text("Content Template")');
|
|
await page.waitForTimeout(500);
|
|
const templateContent = await page.locator('.config-template-editor').textContent();
|
|
const hostKeyCount = (templateContent.match(/!!! host/g) || []).length;
|
|
expect(hostKeyCount).toBe(1);
|
|
const hostPlaceholderCount = (templateContent.match(/@host@/g) || []).length;
|
|
expect(hostPlaceholderCount).toBe(2);
|
|
});
|
|
|
|
test('should validate template with unquoted placeholders', async ({ page }) => {
|
|
await page.goto('/');
|
|
await page.click('button:has-text("New Config")');
|
|
await page.waitForTimeout(500);
|
|
|
|
// Add a parameter - use first() to get the new parameter inputs
|
|
await page.click('button[title="Add parameter"]');
|
|
await page.waitForTimeout(300);
|
|
const nameInput = page.locator('input[placeholder="Parameter name"]').last();
|
|
const valueInput = page.locator('input[placeholder="Parameter value"]').last();
|
|
const addButton = page.locator('button[title="Add parameter"]').last();
|
|
await nameInput.fill('port');
|
|
await valueInput.fill('8080');
|
|
await addButton.click();
|
|
await page.waitForTimeout(500);
|
|
|
|
// Go to Content Template and edit with unquoted placeholder
|
|
await page.click('button:has-text("Content Template")');
|
|
await page.waitForTimeout(300);
|
|
await page.click('button:has-text("Edit Template")');
|
|
await page.waitForTimeout(300);
|
|
|
|
// Fill template with unquoted @port@ placeholder
|
|
const textarea = page.locator('textarea');
|
|
await textarea.fill('{\n "Host": "@host@",\n "Port": @port@,\n "Url": "http://@host@:@port@/api"\n}');
|
|
await page.waitForTimeout(300);
|
|
|
|
// Check that Save button is enabled (validation passed)
|
|
const saveButton = page.locator('button:has-text("Save Changes")');
|
|
await expect(saveButton).toBeEnabled();
|
|
|
|
// Check that there's no JSON error
|
|
const errorAlert = page.locator('.bg-red-50');
|
|
await expect(errorAlert).not.toBeVisible();
|
|
|
|
// Save the template
|
|
await saveButton.click();
|
|
await page.waitForTimeout(500);
|
|
|
|
// Verify it was saved - should be in view mode with Edit button visible
|
|
const editButton = page.locator('button:has-text("Edit Template")');
|
|
await expect(editButton).toBeVisible();
|
|
|
|
// Verify the template content is displayed correctly
|
|
const codeContent = page.locator('.hljs');
|
|
await expect(codeContent).toBeVisible();
|
|
const content = await codeContent.textContent();
|
|
expect(content).toContain('@port@');
|
|
});
|
|
|
|
test('should download config file with correct filename', async ({ page }) => {
|
|
await page.goto('/');
|
|
await page.click('button:has-text("New Config")');
|
|
await page.waitForTimeout(500);
|
|
|
|
// Add a parameter to make the config non-empty (Download button requires non-empty config)
|
|
await page.click('button[title="Add parameter"]');
|
|
await page.waitForTimeout(300);
|
|
const nameInput = page.locator('input[placeholder="Parameter name"]').last();
|
|
const valueInput = page.locator('input[placeholder="Parameter value"]').last();
|
|
const addButton = page.locator('button[title="Add parameter"]').last();
|
|
await nameInput.fill('host');
|
|
await valueInput.fill('localhost');
|
|
await addButton.click();
|
|
await page.waitForTimeout(500);
|
|
|
|
// Now download should work
|
|
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');
|
|
});
|
|
});
|