mirror of
https://github.com/getpaseo/paseo.git
synced 2026-11-08 01:14:52 +00:00
fix(website): submit plugin search text during hydration (#9059)
Read the submitted form value while hydration state is still catching up with text entered before its input listener. Cover the missed input event without relying on startup timing. Co-authored-by: paseo-bot[bot] <266920839+paseo-bot[bot]@users.noreply.github.com>
This commit is contained in:
@@ -181,6 +181,23 @@ test("keeps the directory's ranking window when searching", async ({ page }) =>
|
||||
);
|
||||
});
|
||||
|
||||
test("submits the visible search term when its input event was missed", async ({ page }) => {
|
||||
await page.goto("/plugins?window=month");
|
||||
await expect(page.getByRole("button", { name: "Language: English" }).first()).toBeEnabled();
|
||||
await fillSearchWithMissedInputEvent(page, "graphite");
|
||||
|
||||
await page.keyboard.press("Enter");
|
||||
|
||||
await expect(page).toHaveURL(/\/plugins\/all\?q=graphite&window=month$/);
|
||||
await expect(
|
||||
page.getByRole("heading", { level: 1, name: /^Results for “graphite”/ }),
|
||||
).toBeVisible();
|
||||
await expect(page.getByRole("link", { name: "This month" })).toHaveAttribute(
|
||||
"aria-current",
|
||||
"true",
|
||||
);
|
||||
});
|
||||
|
||||
test("searches for a term typed before the page finished loading", async ({ page }) => {
|
||||
const loadScripts = await holdScripts(page);
|
||||
await page.goto("/plugins?window=month", { waitUntil: "domcontentloaded" });
|
||||
@@ -419,6 +436,21 @@ async function searchPlugins(page: Page, term: string) {
|
||||
await page.getByRole("searchbox", { name: "Search plugins" }).fill(term);
|
||||
}
|
||||
|
||||
/** Reproduce text entered before hydration's input listener can observe it, without a clock race. */
|
||||
async function fillSearchWithMissedInputEvent(page: Page, term: string) {
|
||||
const search = page.getByRole("searchbox", { name: "Search plugins" });
|
||||
await search.evaluate(() => {
|
||||
for (const eventType of ["input", "change"]) {
|
||||
document.addEventListener(eventType, (event) => event.stopImmediatePropagation(), {
|
||||
capture: true,
|
||||
once: true,
|
||||
});
|
||||
}
|
||||
});
|
||||
await search.fill(term);
|
||||
await expect(search).toHaveValue(term);
|
||||
}
|
||||
|
||||
async function submitSearch(page: Page, term: string) {
|
||||
await searchPlugins(page, term);
|
||||
await page.keyboard.press("Enter");
|
||||
|
||||
@@ -68,12 +68,16 @@ export function PluginSearch({
|
||||
input.current?.focus();
|
||||
}, [edit]);
|
||||
const handleSubmit = useCallback(
|
||||
(event: FormEvent) => {
|
||||
(event: FormEvent<HTMLFormElement>) => {
|
||||
event.preventDefault();
|
||||
// Live results already show the term.
|
||||
if (!live) show(term, { replace: false });
|
||||
if (!live) {
|
||||
// Hydration can attach this handler before state adopts text already in the input.
|
||||
const submittedTerm = String(new FormData(event.currentTarget).get("q") ?? "");
|
||||
show(submittedTerm, { replace: false });
|
||||
}
|
||||
},
|
||||
[live, show, term],
|
||||
[live, show],
|
||||
);
|
||||
return (
|
||||
<form
|
||||
|
||||
Reference in New Issue
Block a user