From 06fa31193f96fbb8754e20e81bf122af77332999 Mon Sep 17 00:00:00 2001 From: Helge Sverre Date: Wed, 8 Jul 2026 18:19:18 +0200 Subject: [PATCH] test(e2e): convert remaining brittle selectors to getByTestId; add stats-grid testid --- e2e/tests/admin.spec.ts | 26 +++++++++++------------ e2e/tests/publisher.spec.ts | 12 +++++------ e2e/tests/tokens.spec.ts | 42 ++++++++++++++++++------------------- templates/admin.html | 2 +- 4 files changed, 41 insertions(+), 41 deletions(-) diff --git a/e2e/tests/admin.spec.ts b/e2e/tests/admin.spec.ts index d175d64..b4252df 100644 --- a/e2e/tests/admin.spec.ts +++ b/e2e/tests/admin.spec.ts @@ -43,8 +43,8 @@ test.describe('Admin Panel', () => { await page.goto('/admin'); await expect(page).toHaveURL(/\/admin/); // Wait for stats grid to be visible — proves dashboard tab loaded with data - await page.waitForSelector('.stats-grid', { state: 'visible', timeout: 15000 }); - await expect(page.locator('.stats-grid')).toBeVisible(); + await expect(page.getByTestId('stats-grid')).toBeVisible({ timeout: 15000 }); + await expect(page.getByTestId('stats-grid')).toBeVisible(); }); // ──────────────────────────────────────────── @@ -97,7 +97,7 @@ test.describe('Admin Panel', () => { // Navigate and wait for stats to render await page.goto('/admin'); - await page.waitForSelector('.stats-grid', { state: 'visible', timeout: 15000 }); + await expect(page.getByTestId('stats-grid')).toBeVisible({ timeout: 15000 }); // Stat values should be visible and numeric const totalUsers = page.getByTestId('stat-users'); @@ -129,7 +129,7 @@ test.describe('Admin Panel', () => { await api.setSession(page.context(), adminSession); await page.goto('/admin'); - await page.waitForSelector('.stats-grid', { state: 'visible', timeout: 15000 }); + await expect(page.getByTestId('stats-grid')).toBeVisible({ timeout: 15000 }); // Switch to Users tab and wait for table rows to appear await page.getByTestId('nav-users').click(); @@ -177,7 +177,7 @@ test.describe('Admin Panel', () => { await api.setSession(page.context(), adminSession); await page.goto('/admin'); - await page.waitForSelector('.stats-grid', { state: 'visible', timeout: 15000 }); + await expect(page.getByTestId('stats-grid')).toBeVisible({ timeout: 15000 }); // Navigate to Users tab and wait for table to load await page.getByTestId('nav-users').click(); @@ -243,7 +243,7 @@ test.describe('Admin Panel', () => { await api.setSession(page.context(), adminSession); await page.goto('/admin'); - await page.waitForSelector('.stats-grid', { state: 'visible', timeout: 15000 }); + await expect(page.getByTestId('stats-grid')).toBeVisible({ timeout: 15000 }); // Navigate to Packages tab and wait for table rows await page.getByTestId('nav-packages').click(); @@ -291,7 +291,7 @@ test.describe('Admin Panel', () => { await api.setSession(page.context(), adminSession); await page.goto('/admin'); - await page.waitForSelector('.stats-grid', { state: 'visible', timeout: 15000 }); + await expect(page.getByTestId('stats-grid')).toBeVisible({ timeout: 15000 }); // Navigate to Packages tab and wait for table rows await page.getByTestId('nav-packages').click(); @@ -354,7 +354,7 @@ test.describe('Admin Panel', () => { await api.setSession(page.context(), adminSession); await page.goto('/admin'); - await page.waitForSelector('.stats-grid', { state: 'visible', timeout: 15000 }); + await expect(page.getByTestId('stats-grid')).toBeVisible({ timeout: 15000 }); // Switch to Audit Log tab await page.getByTestId('nav-audit').click(); @@ -367,7 +367,7 @@ test.describe('Admin Panel', () => { ).toBeVisible({ timeout: 10000 }); // Wait for at least one entry to render - const entries = page.locator('[data-testid="audit-entry"]:visible'); + const entries = page.getByTestId('audit-entry').filter({ visible: true }); await expect(entries.first()).toBeVisible({ timeout: 10000 }); const count = await entries.count(); expect(count).toBeGreaterThanOrEqual(1); @@ -407,7 +407,7 @@ test.describe('Admin Panel', () => { await api.setSession(page.context(), adminSession); await page.goto('/admin'); - await page.waitForSelector('.stats-grid', { state: 'visible', timeout: 15000 }); + await expect(page.getByTestId('stats-grid')).toBeVisible({ timeout: 15000 }); // Switch to Reports tab and wait for report content to appear await page.getByTestId('nav-reports').click(); @@ -455,7 +455,7 @@ test.describe('Admin Panel', () => { await api.setSession(page.context(), adminSession); await page.goto('/admin'); - await page.waitForSelector('.stats-grid', { state: 'visible', timeout: 15000 }); + await expect(page.getByTestId('stats-grid')).toBeVisible({ timeout: 15000 }); // Switch to Reports tab and wait for report content to appear await page.getByTestId('nav-reports').click(); @@ -542,7 +542,7 @@ test.describe('Admin Panel', () => { await api.setSession(page.context(), adminSession); await page.goto('/admin'); - await page.waitForSelector('.stats-grid', { state: 'visible', timeout: 15000 }); + await expect(page.getByTestId('stats-grid')).toBeVisible({ timeout: 15000 }); // Navigate to Users tab await page.getByTestId('nav-users').click(); @@ -657,7 +657,7 @@ test.describe('Admin Panel', () => { await api.setSession(page.context(), adminSession); await page.goto('/admin'); - await page.waitForSelector('.stats-grid', { state: 'visible', timeout: 15000 }); + await expect(page.getByTestId('stats-grid')).toBeVisible({ timeout: 15000 }); // Navigate to Users tab await page.getByTestId('nav-users').click(); diff --git a/e2e/tests/publisher.spec.ts b/e2e/tests/publisher.spec.ts index 31c8582..4522400 100644 --- a/e2e/tests/publisher.spec.ts +++ b/e2e/tests/publisher.spec.ts @@ -7,7 +7,7 @@ test.describe('Publisher — publish packages via API, verify on web UI', () => await publishPackage(request, apiToken, name, '1.0.0'); await authedPage.goto('/'); - const recent = authedPage.locator('[data-testid="recent-packages"]'); + const recent = authedPage.getByTestId('recent-packages'); await expect(recent).toContainText(name); }); @@ -21,8 +21,8 @@ test.describe('Publisher — publish packages via API, verify on web UI', () => await publishPackage(request, apiToken, name, '1.0.0', description); await authedPage.goto(`/packages/${name}`); - await expect(authedPage.locator('[data-testid="pkg-name"]')).toHaveText(name); - await expect(authedPage.locator('[data-testid="versions-table"]')).toContainText('1.0.0'); + await expect(authedPage.getByTestId('pkg-name')).toHaveText(name); + await expect(authedPage.getByTestId('versions-table')).toContainText('1.0.0'); await expect(authedPage.locator('body')).toContainText(description); }); @@ -36,7 +36,7 @@ test.describe('Publisher — publish packages via API, verify on web UI', () => await publishPackage(request, apiToken, name, '2.0.0'); await authedPage.goto(`/packages/${name}`); - const table = authedPage.locator('[data-testid="versions-table"]'); + const table = authedPage.getByTestId('versions-table'); await expect(table).toContainText('1.0.0'); await expect(table).toContainText('2.0.0'); }); @@ -50,7 +50,7 @@ test.describe('Publisher — publish packages via API, verify on web UI', () => await publishPackage(request, apiToken, name, '1.0.0'); await authedPage.goto('/account'); - const section = authedPage.locator('[data-testid="section-packages"]'); + const section = authedPage.getByTestId('section-packages'); await expect(section).toContainText(name); }); @@ -60,7 +60,7 @@ test.describe('Publisher — publish packages via API, verify on web UI', () => await yankVersion(request, apiToken, name, '1.0.0'); await authedPage.goto(`/packages/${name}`); - const table = authedPage.locator('[data-testid="versions-table"]'); + const table = authedPage.getByTestId('versions-table'); await expect(table).toContainText('yanked'); }); }); diff --git a/e2e/tests/tokens.spec.ts b/e2e/tests/tokens.spec.ts index 86e2d44..e9cd8cd 100644 --- a/e2e/tests/tokens.spec.ts +++ b/e2e/tests/tokens.spec.ts @@ -4,10 +4,10 @@ test.describe('Tokens — API token CRUD lifecycle', () => { test('generate token shows token value', async ({ authedPage }) => { await authedPage.goto('/account'); - await authedPage.locator('[data-testid="token-name-input"]').locator('input').fill('my-token'); - await authedPage.locator('[data-testid="token-generate-btn"]').click(); + await authedPage.getByTestId('token-name-input').locator('input').fill('my-token'); + await authedPage.getByTestId('token-generate-btn').click(); - const display = authedPage.locator('[data-testid="token-display"]'); + const display = authedPage.getByTestId('token-display'); await expect(display).toBeVisible(); await expect(display).toContainText('sema_pat_'); }); @@ -16,12 +16,12 @@ test.describe('Tokens — API token CRUD lifecycle', () => { await authedPage.goto('/account'); const tokenName = `list-token-${Date.now()}`; - await authedPage.locator('[data-testid="token-name-input"]').locator('input').fill(tokenName); - await authedPage.locator('[data-testid="token-generate-btn"]').click(); + await authedPage.getByTestId('token-name-input').locator('input').fill(tokenName); + await authedPage.getByTestId('token-generate-btn').click(); - await expect(authedPage.locator('[data-testid="token-display"]')).toBeVisible(); + await expect(authedPage.getByTestId('token-display')).toBeVisible(); - const row = authedPage.locator('[data-testid="token-row"]', { hasText: tokenName }); + const row = authedPage.getByTestId('token-row').filter({ hasText: tokenName }); await expect(row).toBeVisible(); }); @@ -31,14 +31,14 @@ test.describe('Tokens — API token CRUD lifecycle', () => { const name1 = `multi-a-${Date.now()}`; const name2 = `multi-b-${Date.now()}`; - await authedPage.locator('[data-testid="token-name-input"]').locator('input').fill(name1); - await authedPage.locator('[data-testid="token-generate-btn"]').click(); - await expect(authedPage.locator('[data-testid="token-display"]')).toBeVisible(); + await authedPage.getByTestId('token-name-input').locator('input').fill(name1); + await authedPage.getByTestId('token-generate-btn').click(); + await expect(authedPage.getByTestId('token-display')).toBeVisible(); - await authedPage.locator('[data-testid="token-name-input"]').locator('input').fill(name2); - await authedPage.locator('[data-testid="token-generate-btn"]').click(); + await authedPage.getByTestId('token-name-input').locator('input').fill(name2); + await authedPage.getByTestId('token-generate-btn').click(); - const rows = authedPage.locator('[data-testid="token-row"]'); + const rows = authedPage.getByTestId('token-row'); // The apiToken fixture also created one, so we check for our two by name await expect(rows.filter({ hasText: name1 })).toBeVisible(); await expect(rows.filter({ hasText: name2 })).toBeVisible(); @@ -48,11 +48,11 @@ test.describe('Tokens — API token CRUD lifecycle', () => { await authedPage.goto('/account'); const tokenName = `revoke-token-${Date.now()}`; - await authedPage.locator('[data-testid="token-name-input"]').locator('input').fill(tokenName); - await authedPage.locator('[data-testid="token-generate-btn"]').click(); - await expect(authedPage.locator('[data-testid="token-display"]')).toBeVisible(); + await authedPage.getByTestId('token-name-input').locator('input').fill(tokenName); + await authedPage.getByTestId('token-generate-btn').click(); + await expect(authedPage.getByTestId('token-display')).toBeVisible(); - const row = authedPage.locator('[data-testid="token-row"]', { hasText: tokenName }); + const row = authedPage.getByTestId('token-row').filter({ hasText: tokenName }); await expect(row).toBeVisible(); // Auto-accept the confirm() dialog before clicking Revoke @@ -66,11 +66,11 @@ test.describe('Tokens — API token CRUD lifecycle', () => { await authedPage.goto('/account'); const tokenName = `exact-name-${Date.now()}`; - await authedPage.locator('[data-testid="token-name-input"]').locator('input').fill(tokenName); - await authedPage.locator('[data-testid="token-generate-btn"]').click(); - await expect(authedPage.locator('[data-testid="token-display"]')).toBeVisible(); + await authedPage.getByTestId('token-name-input').locator('input').fill(tokenName); + await authedPage.getByTestId('token-generate-btn').click(); + await expect(authedPage.getByTestId('token-display')).toBeVisible(); - const row = authedPage.locator('[data-testid="token-row"]', { hasText: tokenName }); + const row = authedPage.getByTestId('token-row').filter({ hasText: tokenName }); await expect(row).toBeVisible(); await expect(row).toContainText(tokenName); }); diff --git a/templates/admin.html b/templates/admin.html index 4e8cbe5..9e991d1 100644 --- a/templates/admin.html +++ b/templates/admin.html @@ -489,7 +489,7 @@

Dashboard

Registry overview and recent activity

-
+
Total Users