Skip to content

Commit 66ddfef

Browse files
cdervclaude
andcommitted
Use Playwright role selectors instead of Pandoc-generated tab IDs in tests
Tab pane IDs like `tabset-1-2` are auto-generated by Pandoc and break if the fixture structure changes. Replace with `getByRole('tab', { name })` and `toHaveClass(/active/)`, matching the pattern used in html-tabsets.spec.ts. Section-scoped locators disambiguate duplicate tab names (R, Python). Co-Authored-By: Claude Opus 4.6 <[email protected]>
1 parent 4739866 commit 66ddfef

1 file changed

Lines changed: 16 additions & 28 deletions

File tree

tests/integration/playwright/tests/html-search-tabsets.spec.ts

Lines changed: 16 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,6 @@ import { test, expect, Page } from "@playwright/test";
22

33
const BASE = './html/search-tabsets/_site/index.html';
44

5-
// Helper: wait for search tab activation (deferred to pageshow)
6-
// and return the active pane ID for a given tab-content index.
7-
async function getActiveTabId(page: Page, tabContentIndex: number): Promise<string> {
8-
return page.evaluate((idx) => {
9-
const tabContents = document.querySelectorAll('.tab-content');
10-
const tc = tabContents[idx];
11-
if (!tc) return 'not-found';
12-
const active = tc.querySelector('.tab-pane.active');
13-
return active?.id ?? 'none';
14-
}, tabContentIndex);
15-
}
16-
175
// Helper: count marks visible (not inside an inactive tab pane)
186
async function visibleMarkCount(page: Page): Promise<number> {
197
return page.evaluate(() => {
@@ -37,9 +25,8 @@ test('Search activates inactive tab containing match', async ({ page }) => {
3725
const marks = page.locator('mark');
3826
await expect(marks.first()).toBeVisible({ timeout: 5000 });
3927

40-
// Tab Beta (tabset-1-2) should be active in the ungrouped tabset (index 0)
41-
const activeId = await getActiveTabId(page, 0);
42-
expect(activeId).toBe('tabset-1-2');
28+
// Tab Beta should be active in the ungrouped tabset
29+
await expect(page.getByRole('tab', { name: 'Tab Beta', exact: true })).toHaveClass(/active/);
4330

4431
await expect(marks).toHaveCount(1);
4532
expect(await visibleMarkCount(page)).toBe(1);
@@ -51,9 +38,9 @@ test('Search keeps active tab when it already has a match', async ({ page }) =>
5138
const marks = page.locator('mark');
5239
await expect(marks.first()).toBeVisible({ timeout: 5000 });
5340

54-
// R tab (tabset-2-1) should stay active — it already has a match
55-
const activeId = await getActiveTabId(page, 1);
56-
expect(activeId).toBe('tabset-2-1');
41+
// R tab should stay active — it already has a match
42+
const section = page.locator('#both-tabs-match');
43+
await expect(section.getByRole('tab', { name: 'R', exact: true })).toHaveClass(/active/);
5744

5845
// 2 marks total (one in each tab), only 1 visible (in active tab)
5946
await expect(marks).toHaveCount(2);
@@ -67,8 +54,9 @@ test('Search highlights outside tabs without changing tab state', async ({ page
6754
await expect(marks.first()).toBeVisible({ timeout: 5000 });
6855

6956
// All tabs should remain at their defaults (first tab active)
70-
expect(await getActiveTabId(page, 0)).toBe('tabset-1-1');
71-
expect(await getActiveTabId(page, 1)).toBe('tabset-2-1');
57+
await expect(page.getByRole('tab', { name: 'Tab Alpha', exact: true })).toHaveClass(/active/);
58+
const bothSection = page.locator('#both-tabs-match');
59+
await expect(bothSection.getByRole('tab', { name: 'R', exact: true })).toHaveClass(/active/);
7260

7361
await expect(marks).toHaveCount(1);
7462
expect(await visibleMarkCount(page)).toBe(1);
@@ -80,10 +68,9 @@ test('Search activates both outer and inner tabs for nested match', async ({ pag
8068
const marks = page.locator('mark');
8169
await expect(marks.first()).toBeVisible({ timeout: 5000 });
8270

83-
// Outer Tab B (tabset-6-2) and Inner Tab Y (tabset-5-2) should both activate.
84-
// Tabset indices: outer nested = 4, inner nested = 5
85-
expect(await getActiveTabId(page, 4)).toBe('tabset-6-2');
86-
expect(await getActiveTabId(page, 5)).toBe('tabset-5-2');
71+
// Both outer and inner tabs should activate for the nested match
72+
await expect(page.getByRole('tab', { name: 'Outer Tab B', exact: true })).toHaveClass(/active/);
73+
await expect(page.getByRole('tab', { name: 'Inner Tab Y', exact: true })).toHaveClass(/active/);
8774

8875
await expect(marks).toHaveCount(1);
8976
expect(await visibleMarkCount(page)).toBe(1);
@@ -105,12 +92,13 @@ test('Search activation overrides localStorage tab preference', async ({ page })
10592
const marks = page.locator('mark');
10693
await expect(marks.first()).toBeVisible({ timeout: 5000 });
10794

108-
// Python tab (tabset-3-2) should be active despite localStorage saying "R"
109-
const activeId = await getActiveTabId(page, 2);
110-
expect(activeId).toBe('tabset-3-2');
95+
// Python tab should be active despite localStorage saying "R"
96+
const groupedSection = page.locator('#grouped-tabset');
97+
await expect(groupedSection.getByRole('tab', { name: 'Python', exact: true })).toHaveClass(/active/);
11198

11299
// Second grouped tabset should remain on R (no search match there)
113-
expect(await getActiveTabId(page, 3)).toBe('tabset-4-1');
100+
const secondGrouped = page.locator('#second-grouped-tabset');
101+
await expect(secondGrouped.getByRole('tab', { name: 'R', exact: true })).toHaveClass(/active/);
114102

115103
await expect(marks).toHaveCount(1);
116104
expect(await visibleMarkCount(page)).toBe(1);

0 commit comments

Comments
 (0)