refactor: complete application rewrite with modern UI

This commit is contained in:
sokol
2026-02-19 22:55:26 +03:00
parent 271b530fa1
commit a6cc5a9827
26 changed files with 3036 additions and 794 deletions

View File

@@ -4,29 +4,32 @@ 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")');
const removeButton = page.locator('button.btn-danger[title="Remove environment"]');
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("Create new")');
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.btn-success[title="Add environment"]');
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.btn-danger[title="Remove environment"]');
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("Create new")');
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.btn-success[title="Add environment"]');
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 });
@@ -38,12 +41,13 @@ test.describe('Environment Management', () => {
test('should create multiple environments and switch between them', async ({ page }) => {
await page.goto('/');
await page.click('button:has-text("Create new")');
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.btn-success[title="Add environment"]');
await page.click('button[title="Add environment"]');
await page.waitForTimeout(500);
page.once('dialog', async dialog => { await dialog.accept('env2'); });
await page.click('button.btn-success[title="Add environment"]');
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 });
@@ -57,10 +61,11 @@ 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")');
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 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();
@@ -69,48 +74,49 @@ test.describe('Environment Management', () => {
await valueInput.fill('9090');
await addButton.click();
await page.waitForTimeout(500);
await page.click('a:has-text("Content Template")');
await page.click('button:has-text("Content Template")');
await page.waitForTimeout(500);
await expect(page.locator('button:has-text("Edit")')).toBeVisible();
await page.click('button:has-text("Edit")');
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")');
await page.click('button:has-text("Save Changes")');
await page.waitForTimeout(500);
await expect(page.locator('button:has-text("Edit")')).toBeVisible();
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("Create new")');
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 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('a:has-text("Content Template")');
await page.click('button:has-text("Content Template")');
await page.waitForTimeout(500);
await page.click('button:has-text("Edit")');
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")');
await page.click('button:has-text("Save Changes")');
await page.waitForTimeout(500);
await page.click('a:has-text("Env")');
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('a:has-text("Content Template")');
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;
@@ -121,49 +127,49 @@ test.describe('Environment Management', () => {
test('should validate template with unquoted placeholders', async ({ page }) => {
await page.goto('/');
await page.click('button:has-text("Create new")');
await page.click('button:has-text("New Config")');
await page.waitForTimeout(500);
// Add a parameter
await page.click('button:has-text("✚")');
// 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="name"]');
const valueInput = page.locator('input[placeholder="value"]');
const addButton = page.locator('button:has-text("✓")');
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('a:has-text("Content Template")');
await page.click('button:has-text("Content Template")');
await page.waitForTimeout(300);
await page.click('button:has-text("Edit")');
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")');
const saveButton = page.locator('button:has-text("Save Changes")');
await expect(saveButton).toBeEnabled();
// Check that there's no JSON error
const errorAlert = page.locator('.alert-danger');
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")');
const editButton = page.locator('button:has-text("Edit Template")');
await expect(editButton).toBeVisible();
// Verify the template content is displayed correctly
const codeContent = page.locator('code');
const codeContent = page.locator('.hljs');
await expect(codeContent).toBeVisible();
const content = await codeContent.textContent();
expect(content).toContain('@port@');
@@ -171,7 +177,7 @@ test.describe('Environment Management', () => {
test('should download config file with correct filename', async ({ page }) => {
await page.goto('/');
await page.click('button:has-text("Create new")');
await page.click('button:has-text("New Config")');
await page.waitForTimeout(500);
const [download] = await Promise.all([
page.waitForEvent('download'),