Skip to content

Instantly share code, notes, and snippets.

@icorbrey
Created August 18, 2021 21:41
Show Gist options
  • Save icorbrey/ee029f276115ee737414536ca985327c to your computer and use it in GitHub Desktop.
Save icorbrey/ee029f276115ee737414536ca985327c to your computer and use it in GitHub Desktop.
declare var _screen: Screen & {
queryByRole: (role: string, options: { name: string }) => HTMLElement
queryByTestId: (testId: string) => HTMLElement
}
declare var fireEvent: {
click: (element: HTMLElement) => void
type: (element: HTMLElement, text: string) => void
}
declare var act: (fn: () => Promise<void>) => Promise<void>
/***********************************************************************/
type Option<T> = Some<T> | None
type Some<T> = {
_tag: 'some'
value: T
}
type None = {
_tag: 'none'
}
const some = <T>(value: T): Some<T> => ({
_tag: 'some',
value,
})
const none = (): None => ({
_tag: 'none',
})
const isSome = <T>(option: Option<T>): option is Some<T> =>
option._tag === 'some'
const isNone = <T>(option: Option<T>): option is None =>
option._tag === 'none'
const fromNullable = <T>(value: T): Option<T> =>
value !== undefined && value !== null
? some(value)
: none()
const fold = <T, R>(onSome: (value: T) => R, onNone: () => R) =>
(option: Option<T>) =>
isSome(option)
? onSome(option.value)
: onNone()
/***********************************************************************/
type QueryScreen = {
(): Option<HTMLElement>
click: () => Promise<void>
type: (text: string) => Promise<void>
role: string
id: string
}
const queryByRole = (role: string) => (ariaLabel: string) => fromNullable(
_screen.queryByRole(role, {
name: ariaLabel
})
)
const queryByTestId = (testId: string) => fromNullable(
_screen.queryByTestId(testId)
)
const actOn = async (queryScreen: QueryScreen, fn: (element: HTMLElement) => void) =>
{
await act(async () =>
{
fold(fn, () => {
throw new Error(
`Could not find element with role '${queryScreen.role}'`
+ ` and aria-label or data-testid '${queryScreen.id}'`
)
})(queryScreen())
})
}
const query = (role: string) => (id: string): QueryScreen =>
{
const queryScreen = () =>
fold<HTMLElement, Option<HTMLElement>>(
element => some(element),
() => queryByTestId(id)
)(queryByRole(role)(id))
queryScreen.id = id
queryScreen.role = role
queryScreen.click = async () => {
await actOn(queryScreen, element => {
fireEvent.click(element)
})
}
queryScreen.type = async (text: string) => {
await actOn(queryScreen, element => {
fireEvent.type(element, text)
})
}
return queryScreen
}
const el = {
img: query('img'),
log: query('log'),
row: query('row'),
tab: query('tab'),
cell: query('cell'),
feed: query('feed'),
form: query('form'),
grid: query('grid'),
link: query('link'),
list: query('list'),
main: query('main'),
math: query('math'),
menu: query('menu'),
none: query('none'),
note: query('note'),
term: query('term'),
tree: query('tree'),
alert: query('alert'),
group: query('group'),
radio: query('radio'),
table: query('table'),
timer: query('timer'),
banner: query('banner'),
button: query('button'),
dialog: query('dialog'),
figure: query('figure'),
option: query('option'),
region: query('region'),
search: query('search'),
slider: query('slider'),
status: query('status'),
switch: query('switch'),
article: query('article'),
heading: query('heading'),
listbox: query('listbox'),
marquee: query('marquee'),
menubar: query('menubar'),
tablist: query('tablist'),
textbox: query('textbox'),
toolbar: query('toolbar'),
tooltip: query('tooltip'),
checkbox: query('checkbox'),
combobox: query('combobox'),
gridcell: query('gridcell'),
document: query('document'),
listitem: query('listitem'),
menuitem: query('menuitem'),
rowgroup: query('rowgroup'),
tabpanel: query('tabpanel'),
treegrid: query('treegrid'),
treeitem: query('treeitem'),
directory: query('directory'),
rowheader: query('rowheader'),
scrollbar: query('scrollbar'),
searchbox: query('searchbox'),
separator: query('separator'),
definition: query('definition'),
navigation: query('navigation'),
radiogroup: query('radiogroup'),
spinbutton: query('spinbutton'),
alertdialog: query('alertdialog'),
application: query('application'),
contentinfo: query('contentinfo'),
progressbar: query('progressbar'),
columnheader: query('columnheader'),
presentation: query('presentation'),
complementary: query('complementary'),
menuitemradio: query('menuitemradio'),
menuitemcheckbox: query('menuitemcheckbox'),
}
/***********************************************************************/
el.button('@assessments/add').click()
el.textbox('@assessments/title').type('New Assessment')
el.button('@assessments/save').click()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment