selectMultipleOptions function infrastructure ✓ 81.3%
Last updated: 2026-03-04T23:21:38.386Z
Metrics
LOC: 107
Complexity: 17
Params: 4
Coverage: 81.3% (26/32 lines, 0x executed)
Signature
selectMultipleOptions(
wrapper: HTMLElement,
value: string,
listboxId: string | null = null,
): : Promise<boolean>
Summary
Selects multiple options from an open ant-select-multiple dropdown. Strategy: 1. If value contains comma-separated strings, try to match each one. 2. Otherwise, pick 1–3 random non-selected options from the dropdown. 3. Close the dropdown by pressing Escape after all selections. listboxId — the value of aria-controls on the combobox input. Used to scope ALL dropdown queries to THIS wrapper's portal so concurrent fills of multiple
Architecture violations
- [warning] max-cyclomatic-complexity: 'selectMultipleOptions' has cyclomatic complexity 17 (max 10)
- [warning] max-lines: 'selectMultipleOptions' has 107 lines (max 80)
Source Code
async function selectMultipleOptions(
wrapper: HTMLElement,
value: string,
listboxId: string | null = null,
): Promise<boolean> {
// Wait for options to load before attempting to click — handles AJAX-loaded selects.
await waitForElement(
".ant-select-dropdown:not(.ant-select-dropdown-hidden) .ant-select-item-option",
2000,
);
/**
* Returns the dropdown portal that belongs to THIS wrapper.
* Primary: resolves via aria-controls → listbox element → closest dropdown.
* Fallback: first visible dropdown (legacy / SSR builds that omit aria attrs).
* Scoping here prevents the race condition where a previous select's dropdown
* is still animating closed when this fill begins.
*/
function getOwnDropdown(): HTMLElement | null {
if (listboxId) {
const lb = document.getElementById(listboxId);
if (lb) {
const dd = lb.closest<HTMLElement>(".ant-select-dropdown");
if (dd && !dd.classList.contains("ant-select-dropdown-hidden"))
return dd;
}
}
return document.querySelector<HTMLElement>(
".ant-select-dropdown:not(.ant-select-dropdown-hidden)",
);
}
const dropdown = getOwnDropdown();
if (!dropdown) {
log.warn(
`selectMultipleOptions — dropdown não encontrado para: ${getUniqueSelector(wrapper)}`,
);
return false;
}
const allOptions = Array.from(
dropdown.querySelectorAll<HTMLElement>(
".ant-select-item-option:not(.ant-select-item-option-disabled)",
),
);
let selected = false;
if (allOptions.length > 0) {
// Collect desired values from comma-separated input (e.g. "Option A, Option B")
const desiredValues = value
? value
.split(",")
.map((v) => v.trim())
.filter(Boolean)
: [];
const optionsToClick: HTMLElement[] = [];
if (desiredValues.length > 0) {
// Try to find each desired value
for (const desired of desiredValues) {
const match = allOptions.find((opt) => {
const title =
opt.getAttribute("title") ?? opt.textContent?.trim() ?? "";
return (
title.toLowerCase() === desired.toLowerCase() ||
title.toLowerCase().includes(desired.toLowerCase())
);
});
if (match) optionsToClick.push(match);
}
}
// If nothing matched (or no value provided), pick 1–3 random options
if (optionsToClick.length === 0) {
const count = Math.min(
Math.floor(Math.random() * 3) + 1,
allOptions.length,
);
const shuffled = [...allOptions].sort(() => Math.random() - 0.5);
optionsToClick.push(...shuffled.slice(0, count));
}
for (const opt of optionsToClick) {
simulateClick(opt);
selected = true;
}
}
// Close the dropdown by pressing Escape on the search input
const searchInput = wrapper.querySelector<HTMLInputElement>(
".ant-select-selection-search-input, .ant-select-input",
);
if (searchInput) {
searchInput.dispatchEvent(
new KeyboardEvent("keydown", {
key: "Escape",
code: "Escape",
bubbles: true,
}),
);
}
return selected;
}
Members
| Name | Kind | Visibility | Status | Signature |
|---|---|---|---|---|
| getOwnDropdown | function | - | getOwnDropdown(): : HTMLElement | null |
Dependencies (Outgoing)
| Target | Type |
|---|---|
| waitForElement | calls |
| getOwnDropdown | calls |
| simulateClick | calls |
Impact (Incoming)
| Source | Type |
|---|---|
| fill | calls |