Skip to content

Commit a5434e6

Browse files
cdervclaude
andcommitted
Add test coverage for search highlight persistence (#14047, #9802)
PR #13442 removed scroll-based highlight clearing. This commit adds Playwright tests verifying: scroll events never clear marks, query-change clearing still works, and no marks appear without ?q= parameter. Restores test fixture files dropped during rebase (source files were in the skipped JS fix commit). Updates changelog to credit @jtbayly and reference both #9802 and #14047. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 2c83a84 commit a5434e6

5 files changed

Lines changed: 56 additions & 21 deletions

File tree

news/changelog-1.9.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ All changes included in 1.9:
119119
- ([#13932](https://github.com/quarto-dev/quarto-cli/pull/13932)): Add `llms-txt: true` option to generate LLM-friendly content for websites. Creates `.llms.md` markdown files alongside HTML pages and a root `llms.txt` index file following the [llms.txt](https://llmstxt.org/) specification.
120120
- ([#13951](https://github.com/quarto-dev/quarto-cli/issues/13951)): Fix `image-lazy-loading` not applying `loading="lazy"` attribute to auto-detected listing images.
121121
- ([#14003](https://github.com/quarto-dev/quarto-cli/pull/14003)): Add text fragments to search result links so browsers scroll to and highlight the matched text on the target page.
122-
- ([#14047](https://github.com/quarto-dev/quarto-cli/issues/14047)): Fix search highlights cleared before user can see them when landing on a page with `?q=` search parameter.
122+
- ([#9802](https://github.com/quarto-dev/quarto-cli/issues/9802), [#14047](https://github.com/quarto-dev/quarto-cli/issues/14047)): Fix search term highlighting disappearing on page scroll or layout events when navigating from search results. (author: @jtbayly, [#13442](https://github.com/quarto-dev/quarto-cli/pull/13442))
123123

124124
### `book`
125125

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,4 @@
11
*_files/
2-
*.html
2+
*.html
3+
/.quarto/
4+
**/*.quarto_ipynb
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
project:
2+
type: website
3+
4+
website:
5+
title: "Search Highlight Test"
6+
navbar:
7+
left:
8+
- href: index.qmd
9+
text: Home
10+
11+
format: html
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
title: "Search Highlight Test"
3+
---
4+
5+
This page contains a special keyword that we use for testing search highlighting.
6+
7+
The word special appears multiple times on this page to ensure search highlighting works correctly.
Lines changed: 34 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,53 @@
11
import { test, expect } from "@playwright/test";
22

3-
test('Search highlights persist after page load', async ({ page }) => {
4-
await page.goto('./html/search-highlight/_site/index.html?q=special');
3+
const BASE = './html/search-highlight/_site/index.html';
4+
5+
test('Search highlights not cleared by scroll events', async ({ page }) => {
6+
await page.goto(`${BASE}?q=special`);
57
const marks = page.locator('mark');
68

7-
// Marks should exist after page load
89
await expect(marks.first()).toBeVisible({ timeout: 5000 });
10+
const initialCount = await marks.count();
11+
expect(initialCount).toBeGreaterThanOrEqual(2);
912

10-
// Simulate the layout-triggered quarto-hrChanged event that clears marks
11-
// prematurely without the fix (#14047). With the fix, the listener is
12-
// registered after a delay, so early events like this are ignored.
13+
// Dispatch layout events immediately (previously cleared marks via quarto-hrChanged)
1314
await page.evaluate(() => {
1415
window.dispatchEvent(new CustomEvent('quarto-hrChanged'));
16+
window.dispatchEvent(new CustomEvent('quarto-sectionChanged'));
1517
});
18+
await expect(marks).toHaveCount(initialCount);
1619

17-
// Marks should still be visible after the simulated layout event
18-
await expect(marks.first()).toBeVisible();
19-
await expect(marks.first()).toContainText(/special/i);
20+
// Wait and dispatch again — marks should persist at any time
21+
await page.waitForTimeout(1500);
22+
await page.evaluate(() => {
23+
window.dispatchEvent(new CustomEvent('quarto-hrChanged'));
24+
window.dispatchEvent(new CustomEvent('quarto-sectionChanged'));
25+
});
26+
await expect(marks).toHaveCount(initialCount);
2027
});
2128

22-
test('Search highlights are cleared by scroll after delay', async ({ page }) => {
23-
await page.goto('./html/search-highlight/_site/index.html?q=special');
29+
test('Search highlights cleared when query changes', async ({ page }) => {
30+
await page.goto(`${BASE}?q=special`);
2431
const marks = page.locator('mark');
2532

26-
// Marks should exist after page load
2733
await expect(marks.first()).toBeVisible({ timeout: 5000 });
2834

29-
// Wait for the delayed listener registration (1000ms in quarto-search.js)
30-
await page.waitForTimeout(1500);
35+
// Open the detached search overlay
36+
await page.locator('.aa-DetachedSearchButton').click();
37+
const input = page.locator('.aa-Input');
38+
await expect(input).toBeVisible({ timeout: 2000 });
3139

32-
// Now quarto-hrChanged should clear marks (listener is registered)
33-
await page.evaluate(() => {
34-
window.dispatchEvent(new CustomEvent('quarto-hrChanged'));
35-
});
40+
// Type a different query — triggers onStateChange which clears marks
41+
await input.fill('different');
42+
await expect(page.locator('main mark')).toHaveCount(0, { timeout: 2000 });
43+
});
44+
45+
test('No highlights without search query', async ({ page }) => {
46+
await page.goto(BASE);
47+
48+
// Wait for page to fully load
49+
await expect(page.locator('main')).toBeVisible();
3650

37-
await expect(marks).toHaveCount(0);
51+
// No marks should exist without ?q= parameter
52+
await expect(page.locator('mark')).toHaveCount(0);
3853
});

0 commit comments

Comments
 (0)