test(ui): stabilize browser-mode test harnesses (#12301)

This commit is contained in:
Pablo Fernandez Guerra (PFE)
2026-08-05 11:37:58 +02:00
committed by GitHub
parent 5285d25cfd
commit 34431b5b88
6 changed files with 195 additions and 25 deletions
@@ -30,8 +30,10 @@ export const QuerySelector = ({
<SelectValue placeholder="Choose a query" />
</SelectTrigger>
<SelectContent>
{/* Radix drops `value` from the DOM; `data-value` is what tests
select an option by. */}
{queries.map((query) => (
<SelectItem key={query.id} value={query.id}>
<SelectItem key={query.id} value={query.id} data-value={query.id}>
<div className="flex flex-col gap-1">
<span className="font-medium">{query.attributes.name}</span>
<span className="text-xs text-gray-500">
@@ -384,23 +384,49 @@ export class AttackPathPageHarness extends BrowserHarness<PageFixture> {
'button[role="combobox"]',
),
10000,
"the query selector trigger",
);
await this.user.click(trigger);
const targetId = queryId ?? this.fixture.queryId;
const targetName = this.fixture.queries.find((q) => q.id === targetId)
?.attributes.name;
const option = await this.waitFor<HTMLElement>(
() =>
document.querySelector<HTMLElement>(
`[role="option"][data-value="${targetId}"]`,
) ??
Array.from(
document.querySelectorAll<HTMLElement>('[role="option"]'),
).find((el) => targetName && el.textContent?.includes(targetName)),
10000,
// Id match is exact (`QuerySelector` emits `data-value`); the name fallback
// is loose, since `textContent` also covers the option's description.
const findOption = (): HTMLElement | null =>
document.querySelector<HTMLElement>(
`[role="option"][data-value="${targetId}"]`,
) ??
Array.from(
document.querySelectorAll<HTMLElement>('[role="option"]'),
).find((el) => targetName && el.textContent?.includes(targetName)) ??
null;
await this.user.click(trigger);
// A re-render landing mid-gesture makes Radix drop the open state, leaving
// the trigger focused and the listbox unmounted. Re-open from the keyboard,
// which acts on the focused trigger — but only when no option mounted at
// all, so a merely slow runner does not get a second gesture.
let option = await this.waitForOrNull(
findOption,
2000,
`option ${targetId}`,
);
if (!option && document.querySelector('[role="option"]') === null) {
await this.user.keyboard("{Enter}");
option = await this.waitForOrNull(findOption, 8000, `option ${targetId}`);
}
if (!option) {
throw new Error(
`selectQuery: no option matching id "${targetId}"` +
(targetName
? ` or name "${targetName}"`
: " (id not in the fixture)"),
);
}
await this.user.click(option);
await this.waitForTransition();
}
@@ -1,5 +1,5 @@
import { listScanConfigurations } from "@/actions/scan-configurations";
import { ProvidersAccountsView } from "@/components/providers";
import { ProvidersAccountsView } from "@/components/providers/providers-accounts-view";
import { isCloud } from "@/lib/shared/env";
import { SearchParamsProps } from "@/types";
import {