ai #1

Merged
ssa merged 17 commits from ai into main 2026-02-18 22:44:42 +03:00
2 changed files with 68 additions and 9 deletions
Showing only changes of commit f262c785aa - Show all commits

View File

@@ -70,4 +70,39 @@ test.describe('Environment Management', () => {
await expect(page.locator('#environments')).toBeVisible(); await expect(page.locator('#environments')).toBeVisible();
await expect(page.locator('#environments option')).toHaveCount(2); 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();
});
}); });

View File

@@ -18,17 +18,18 @@ class AppState {
static readonly Instance = new AppState(); static readonly Instance = new AppState();
public loadConfig(cfg: Config) { public loadConfig(cfg: Config) {
this.envs = [...cfg.envs];
this.config = cfg; this.config = cfg;
this.envs = cfg.envs; // Reference the same array as config
} }
public addEnv(env: Env): number { public addEnv(env: Env): number {
this.envs.push(env); this.envs.push(env);
// Also update config.envs since they reference the same array
this.config.envs = this.envs;
return this.envs.length - 1; return this.envs.length - 1;
} }
public async saveEnv(env: Env): Promise<number> { public async saveEnv(env: Env): Promise<number> {
// Create a promise that resolves after 1 second // Create a promise that resolves after 1 second
return await new Promise<number>((resolve) => { return await new Promise<number>((resolve) => {
setTimeout(() => { setTimeout(() => {
@@ -41,6 +42,21 @@ class AppState {
}, 1000); }, 1000);
}); });
} }
public removeEnv(envId: number) {
const idx = this.envs.findIndex(x => x.id === envId);
if (idx > -1) {
this.envs.splice(idx, 1);
// Also update config.envs since they reference the same array
this.config.envs = this.envs;
}
}
// Update the internal envs reference to match React state
public syncEnvs(newEnvs: Env[]) {
this.envs = newEnvs;
this.config.envs = newEnvs;
}
} }
function App() { function App() {
@@ -57,7 +73,12 @@ function App() {
let idx = AppState.Instance.envs.findIndex(x => x.id === env.id); let idx = AppState.Instance.envs.findIndex(x => x.id === env.id);
if (idx > -1) { if (idx > -1) {
AppState.Instance.envs[idx] = env; AppState.Instance.envs[idx] = env;
setEnvs([...AppState.Instance.envs]); // Also update config.envs since they reference the same array
AppState.Instance.config.envs = AppState.Instance.envs;
const newEnvs = [...AppState.Instance.envs];
setEnvs(newEnvs);
AppState.Instance.syncEnvs(newEnvs); // Keep AppState in sync with React state
setConfig(AppState.Instance.config); // Trigger re-render for config
} }
// Then do the async save (for consistency with existing behavior) // Then do the async save (for consistency with existing behavior)
@@ -70,16 +91,19 @@ function App() {
function handleEnvAdded(env: Env): number { function handleEnvAdded(env: Env): number {
const idx = AppState.Instance.addEnv(env); const idx = AppState.Instance.addEnv(env);
setEnvs([...AppState.Instance.envs]); const newEnvs = [...AppState.Instance.envs];
setEnvs(newEnvs);
AppState.Instance.syncEnvs(newEnvs); // Keep AppState in sync with React state
setConfig(AppState.Instance.config); // Trigger re-render for config
return idx; return idx;
} }
function handleEnvRemoved(envId: number) { function handleEnvRemoved(envId: number) {
const idx = AppState.Instance.envs.findIndex(x => x.id === envId); AppState.Instance.removeEnv(envId);
if (idx > -1) { const newEnvs = [...AppState.Instance.envs];
AppState.Instance.envs.splice(idx, 1); setEnvs(newEnvs);
setEnvs([...AppState.Instance.envs]); AppState.Instance.syncEnvs(newEnvs); // Keep AppState in sync with React state
} setConfig(AppState.Instance.config); // Trigger re-render for config
} }
return ( return (