feat: complete Epic 1 production foundation

This commit is contained in:
2026-08-25 01:24:11 +03:00
parent 767428436d
commit 182bde8ac0
298 changed files with 35719 additions and 5299 deletions
+131
View File
@@ -84,3 +84,134 @@ test('generic json secret modal stays inside compact viewport', async ({ page })
await expect(page.locator('[data-testid="secret-name-input"]')).toBeVisible();
await expect(page.locator('[data-testid="secret-submit-button"]')).toBeVisible();
});
test('secret modal clears sensitive values and locks duplicate submit while saving', async ({ page }) => {
await login(page);
await page.goto('/secrets');
await page.locator('[data-testid="secret-create-button"]').click();
await page.locator('[data-testid="secret-name-input"]').fill(uniqueName('ui_secret_guard'));
await page.locator('[data-testid="secret-value-input"]').fill('ui-secret-canary-close');
await page.locator('#secret-modal-cancel-btn').click();
await page.locator('[data-testid="secret-create-button"]').click();
await expect(page.locator('[data-testid="secret-name-input"]')).toHaveValue('');
await expect(page.locator('[data-testid="secret-value-input"]')).toHaveValue('');
let releaseCreate;
const createReleased = new Promise((resolve) => {
releaseCreate = resolve;
});
let createPosts = 0;
await page.route(/\/api\/admin\/workspaces\/[^/]+\/secrets$/, async (route) => {
if (route.request().method() !== 'POST') {
await route.continue();
return;
}
createPosts += 1;
await createReleased;
await route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify({
id: 'secret_ui_guard',
workspace_id: 'ws_test',
name: 'ui_secret_guard',
kind: 'token',
status: 'active',
current_version: 1,
created_at: '2026-08-15T00:00:00Z',
updated_at: '2026-08-15T00:00:00Z',
last_used_at: null,
}),
});
});
await page.locator('[data-testid="secret-name-input"]').fill(uniqueName('ui_secret_guard'));
await page.locator('[data-testid="secret-value-input"]').fill('ui-secret-canary-submit');
const submit = page.locator('[data-testid="secret-submit-button"]');
await submit.click();
await expect(submit).toBeDisabled();
await submit.click({ force: true });
expect(createPosts).toBe(1);
releaseCreate();
await expect(page.locator('[data-testid="secret-create-modal"]')).toBeHidden();
expect(createPosts).toBe(1);
});
test('stale secret rotation cannot close or report success for a newer modal context', async ({ page }) => {
await login(page);
const workspace = await getCurrentWorkspace(page);
const firstName = uniqueName('rotate_stale_first');
const secondName = uniqueName('rotate_stale_second');
const firstSecret = await browserJson(
page,
'POST',
`/api/admin/workspaces/${encodeURIComponent(workspace.id)}/secrets`,
{ name: firstName, kind: 'token', value: 'rotate-stale-first-value' },
);
await browserJson(
page,
'POST',
`/api/admin/workspaces/${encodeURIComponent(workspace.id)}/secrets`,
{ name: secondName, kind: 'token', value: 'rotate-stale-second-value' },
);
let releaseRotate;
const rotateReleased = new Promise((resolve) => {
releaseRotate = resolve;
});
let secretListRequests = 0;
await page.route(/\/api\/admin\/workspaces\/[^/]+\/secrets(?:\/[^/]+\/rotate)?$/, async (route) => {
const request = route.request();
if (request.method() === 'GET') {
secretListRequests += 1;
await route.continue();
return;
}
if (request.method() === 'POST' && /\/rotate$/.test(request.url())) {
await rotateReleased;
await route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify({
id: firstSecret.id,
workspace_id: workspace.id,
name: firstName,
kind: 'token',
status: 'active',
current_version: 2,
created_at: '2026-08-15T00:00:00Z',
updated_at: '2026-08-15T00:00:00Z',
last_used_at: null,
}),
});
return;
}
await route.continue();
});
await page.goto('/secrets');
const firstRow = page.locator('#secrets-tbody tr').filter({ hasText: firstName }).first();
const secondRow = page.locator('#secrets-tbody tr').filter({ hasText: secondName }).first();
await expect(firstRow).toBeVisible();
await expect(secondRow).toBeVisible();
const listRequestsBeforeRelease = secretListRequests;
await firstRow.getByTestId('secret-rotate-action').click();
await page.locator('[data-testid="secret-value-input"]').fill('rotate-stale-first-new-value');
await page.locator('[data-testid="secret-submit-button"]').click();
await expect(page.locator('[data-testid="secret-submit-button"]')).toBeDisabled();
await page.locator('#secret-modal-cancel-btn').click();
await expect(page.getByTestId('secret-rotate-modal')).toBeHidden();
await secondRow.getByTestId('secret-rotate-action').click();
await expect(page.getByTestId('secret-rotate-modal')).toBeVisible();
await expect(page.locator('[data-testid="secret-name-input"]')).toHaveValue(secondName);
releaseRotate();
await page.waitForTimeout(150);
await expect(page.getByTestId('secret-rotate-modal')).toBeVisible();
await expect(page.locator('[data-testid="secret-name-input"]')).toHaveValue(secondName);
await expect(page.locator('.toast-success')).toHaveCount(0);
expect(secretListRequests).toBe(listRequestsBeforeRelease);
});