Skip to content

Commit 012e9e5

Browse files
committed
Add optional
1 parent 4aec8d2 commit 012e9e5

File tree

4 files changed

+26
-11
lines changed

4 files changed

+26
-11
lines changed

src/resolver.ts

+4-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { screen, waitFor } from '@testing-library/dom';
22
import user from '@testing-library/user-event';
3-
import { AllDescriptor, RoleDescriptor } from './roles/types';
3+
import { AllDescriptor, RoleDescriptor, optional } from './roles/types';
44

55
export type DescriptorResult<T> = T extends RoleDescriptor & AllDescriptor
66
? Array<HTMLElement>
@@ -33,6 +33,9 @@ export function resolverFor(
3333
if ('all' in descriptor && descriptor.all === true) {
3434
const { name } = descriptor;
3535
return source.queryAllByRole(descriptor.role, { name }) as any;
36+
} else if (optional in descriptor) {
37+
const { name, isSelected: selected } = descriptor;
38+
return source.queryByRole(descriptor.role, { name, selected }) as any;
3639
} else {
3740
const { name, isSelected: selected } = descriptor;
3841
return source.getByRole(descriptor.role, { name, selected });

src/roles/combobox.test.tsx

+4
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@ describe('Combobox', () => {
1919
expect(screenTest(Combobox())).toBeVisible();
2020
});
2121

22+
it('hides listbox', () => {
23+
expect(screenTest(Combobox.PopupListbox().optional)).toBeNull();
24+
});
25+
2226
it('renders named combobox', () => {
2327
expect(screenTest(Combobox('Person'))).toBeVisible();
2428
});

src/roles/shared.ts

+14-7
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,33 @@
11
import { prettyDOM } from '@testing-library/dom';
2-
import type { AllDescriptor, RoleDescriptor } from './types';
2+
import { optional, type AllDescriptor, type RoleDescriptor } from './types';
33

4-
export type RoleObject<SupportedEvent extends { click?: true }> = {
5-
role: string;
4+
export type RoleObject<
5+
Role extends string,
6+
SupportedEvent extends { click?: true }
7+
> = {
8+
role: Role;
69
name?: string | RegExp;
10+
optional: RoleObject<Role, SupportedEvent>;
711
all: RoleDescriptor & AllDescriptor;
812
} & (SupportedEvent['click'] extends true
913
? {
1014
click: RoleDescriptor;
1115
}
1216
: {});
1317

14-
export function role<SupportedEvent extends { click?: true }>(
15-
role: string,
16-
name?: string | RegExp
17-
): RoleObject<SupportedEvent> {
18+
export function role<
19+
Role extends string,
20+
SupportedEvent extends { click?: true }
21+
>(role: Role, name?: string | RegExp): RoleObject<Role, SupportedEvent> {
1822
return Object.freeze({
1923
role,
2024
name,
2125
get all(): RoleDescriptor & AllDescriptor {
2226
return Object.create(this, { all: { value: true } });
2327
},
28+
get optional() {
29+
return Object.create(this, { [optional]: { value: true } });
30+
},
2431
get click(): RoleDescriptor {
2532
return Object.create(this, { event: { value: 'click' } });
2633
},

src/roles/types.ts

+4-3
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,20 @@
11
import { queries, BoundFunctions, Queries } from '@testing-library/dom';
22

3+
const all = Symbol('all');
4+
export const optional = Symbol('optional');
5+
36
export interface RoleDescriptor {
47
readonly role: string;
58
readonly name?: string | RegExp;
9+
readonly [optional]?: true;
610
readonly isSelected?: boolean;
7-
// readonly all?: true;
811
readonly event?: 'click';
912
}
1013

1114
export interface AllDescriptor {
1215
readonly all: true;
1316
}
1417

15-
export interface AllRoleDescription extends RoleDescriptor, AllDescriptor {}
16-
1718
export interface SingleDescriptor<Q extends Queries = typeof queries> {
1819
get(source: BoundFunctions<Q>): HTMLElement;
1920
}

0 commit comments

Comments
 (0)