sync: update from private repo (2336949a)
CI / build-and-test (push) Canceled after 0s

This commit is contained in:
oss-sync
2026-09-17 11:29:31 +00:00
parent 28f74c4e37
commit 57702b4f34
2139 changed files with 321270 additions and 17494 deletions
+46 -3
View File
@@ -2,7 +2,6 @@ import { test, expect, type Page } from '@playwright/test';
import { createRequire } from 'node:module';
import { fileURLToPath } from 'node:url';
import { dirname, resolve, join } from 'node:path';
import { tmpdir } from 'node:os';
// ── Local-auth ADMIN USER MANAGEMENT E2E ──────────────────────────────────────
//
@@ -29,7 +28,8 @@ const require = createRequire(import.meta.url);
const repoRoot = resolve(__dirname, '..', '..');
// Same deterministic DB the webServer opens (see playwright.auth.config.ts).
const e2eTmp = join(tmpdir(), 'maestro-e2e-auth');
const e2eTmp = process.env.E2E_AUTH_TMP;
if (!e2eTmp) throw new Error('E2E_AUTH_TMP must be set by playwright.auth.config.ts');
const DB_PATH = join(e2eTmp, 'e2e-auth.db');
// The bootstrap admin from config.e2e-auth.yaml.
@@ -167,10 +167,50 @@ test('admin can list users, promote a member to admin, and approve a pending use
expect(fatalErrors, `fatal errors:\n${fatalErrors.join('\n')}`).toEqual([]);
});
test('system admin opens the event log and filters its results', async ({ page }) => {
const fatalErrors = trackFatalErrors(page);
const resourceId = `e2e-event-log-${Date.now()}`;
const { Repository } = require(resolve(repoRoot, 'dist/db/repository.js')) as {
Repository: new (dbPath: string) => {
recordEvent: (input: Record<string, unknown>) => { id: number };
close?: () => void;
};
};
const repo = new Repository(DB_PATH);
try {
repo.recordEvent({
eventType: 'task.failed', resourceType: 'task', resourceId, result: 'failed',
dedupeKey: crypto.randomUUID(), correlationId: crypto.randomUUID(),
});
} finally {
repo.close?.();
}
await login(page, ADMIN.email, ADMIN.password);
await page.goto('/ui?page=users');
await page.getByRole('tab', { name: /イベントログ|Event log/ }).click();
await expect(page.getByRole('heading', { name: /イベントログ|Event log/ })).toBeVisible();
// 絞り込みはイベントログの領域の中だけを見る。上の帯にも「検索」という名前の
// ボタン(shell-search)があり、ページ全体から探すと 2 つ当たって落ちる。
// AdminEventLogPage の <section aria-labelledby="admin-event-log-title"> が
// この領域(role=region)。
const eventLog = page.getByRole('region', { name: /イベントログ|Event log/ });
await eventLog.getByLabel(/種別|Type/).selectOption('task.failed');
await eventLog.getByLabel(/リソースID|Resource ID/).fill(resourceId);
await eventLog.getByRole('button', { name: /検索|Search/ }).click();
const row = page.getByRole('row').filter({ hasText: resourceId });
await expect(row).toBeVisible();
await expect(row).toContainText('task.failed');
await expect(row).toContainText('failed');
expect(fatalErrors, `fatal errors:\n${fatalErrors.join('\n')}`).toEqual([]);
});
// Negative/visibility: a regular member gets NO Users tab and is denied the
// admin API. The 403/401 is fetched via page.request (NOT navigation), so the
// navigation-scoped fatal tracker never observes the expected denial.
test('a non-admin member sees no Users tab and is denied /api/admin/users', async ({ page }) => {
test('a non-admin member sees no admin tabs and is denied admin APIs', async ({ page }) => {
const fatalErrors = trackFatalErrors(page);
// OUTSIDER is a plain 'user' that no test promotes, so the non-admin denial
@@ -180,10 +220,13 @@ test('a non-admin member sees no Users tab and is denied /api/admin/users', asyn
// The Users tab is admin+auth gated; a regular user never sees it.
await expect(page.getByTestId('nav-users')).toHaveCount(0);
await expect(page.getByRole('tab', { name: /イベントログ|Event log/ })).toHaveCount(0);
// Admin-only API is denied for a regular user (401 or 403 depending on guard).
const denied = await page.request.get('/api/admin/users');
expect([401, 403]).toContain(denied.status());
const eventLogDenied = await page.request.get('/api/admin/event-log');
expect(eventLogDenied.status()).toBe(403);
expect(fatalErrors, `fatal errors (DOM navigation only):\n${fatalErrors.join('\n')}`).toEqual([]);
});