Last active
November 30, 2023 21:07
-
-
Save diegohaz/6e3e253af14c213c5ec816badd3c369e to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { | |
queryByLabelText, | |
queryByRole, | |
queryByText, | |
} from "@testing-library/dom"; | |
import type { ByRoleOptions, Matcher } from "@testing-library/dom"; | |
const roles = [ | |
"alert", | |
"alertdialog", | |
"application", | |
"article", | |
"banner", | |
"blockquote", | |
"button", | |
"caption", | |
"cell", | |
"checkbox", | |
"code", | |
"columnheader", | |
"combobox", | |
"complementary", | |
"contentinfo", | |
"definition", | |
"deletion", | |
"dialog", | |
"directory", | |
"document", | |
"emphasis", | |
"feed", | |
"figure", | |
"form", | |
"generic", | |
"grid", | |
"gridcell", | |
"group", | |
"heading", | |
"img", | |
"insertion", | |
"link", | |
"list", | |
"listbox", | |
"listitem", | |
"log", | |
"main", | |
"marquee", | |
"math", | |
"menu", | |
"menubar", | |
"menuitem", | |
"menuitemcheckbox", | |
"menuitemradio", | |
"meter", | |
"navigation", | |
"none", | |
"note", | |
"option", | |
"paragraph", | |
"presentation", | |
"progressbar", | |
"radio", | |
"radiogroup", | |
"region", | |
"row", | |
"rowgroup", | |
"rowheader", | |
"scrollbar", | |
"search", | |
"searchbox", | |
"separator", | |
"slider", | |
"spinbutton", | |
"status", | |
"strong", | |
"subscript", | |
"superscript", | |
"switch", | |
"tab", | |
"table", | |
"tablist", | |
"tabpanel", | |
"term", | |
"textbox", | |
"time", | |
"timer", | |
"toolbar", | |
"tooltip", | |
"tree", | |
"treegrid", | |
"treeitem", | |
] as const; | |
type AriaRole = (typeof roles)[number]; | |
type RoleQueries = Record<AriaRole, ReturnType<typeof createRoleQuery>>; | |
function createRoleQuery(role: AriaRole) { | |
const fn = (name?: string | RegExp, options?: ByRoleOptions) => { | |
if (!name) { | |
return queryByRole(document.body, role, options); | |
} | |
const matchName = (accessibleName: string) => { | |
if (typeof name === "string") { | |
return accessibleName === name; | |
} | |
return name.test(accessibleName); | |
}; | |
return queryByRole(document.body, role, { | |
name(accessibleName, element) { | |
if (matchName(accessibleName)) return true; | |
const labeledBy = element.getAttribute("aria-labelledby"); | |
if (!labeledBy) return false; | |
const label = document.getElementById(labeledBy); | |
if (!label?.textContent) return false; | |
return matchName(label.textContent); | |
}, | |
...options, | |
}); | |
}; | |
const includesHidden = (name?: string | RegExp, options?: ByRoleOptions) => | |
fn(name, { hidden: true, ...options }); | |
return Object.assign(fn, { includesHidden }); | |
} | |
const roleQueries = roles.reduce((acc, role) => { | |
acc[role] = createRoleQuery(role); | |
return acc; | |
}, {} as RoleQueries); | |
export const query = { | |
...roleQueries, | |
text: (text: Matcher) => queryByText(document.body, text), | |
labeled: (label: Matcher) => queryByLabelText(document.body, label), | |
}; | |
export const q = query; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment