Skip to content

Commit

Permalink
test(guidepup): popover (#3010)
Browse files Browse the repository at this point in the history
* test(guidepup): popover

* refactor: updated that snapshot

* refactor: we need to harmonize specific words

* refactor: generated new test case

* refactor: prettyfication

* refactor: corrected that filename

* feat: added generated snapshot

* refactor: renamed accordingly and removed obsolete snapshot

* fix: issue with popover aria-extended

* chore: update snapshots
fix: issue with angular issue for popover trigger

---------

Co-authored-by: Nicolas Merget <[email protected]>
Co-authored-by: Nicolas Merget <[email protected]>
  • Loading branch information
3 people authored Aug 15, 2024
1 parent 82aa64b commit 6f2482d
Show file tree
Hide file tree
Showing 6 changed files with 95 additions and 6 deletions.
7 changes: 6 additions & 1 deletion packages/components/src/components/popover/model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,12 @@ export type DBPopoverProps = DBPopoverDefaultProps &
GapProps &
PopoverProps;

export interface DBPopoverDefaultState {}
export interface DBPopoverDefaultState {
isExpanded?: boolean;
getTrigger?: () => Element | undefined;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
handleLeave?: (event: any) => void;
}

export type DBPopoverState = DBPopoverDefaultState &
GlobalState &
Expand Down
53 changes: 49 additions & 4 deletions packages/components/src/components/popover/popover.lite.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,45 @@ export default function DBPopover(props: DBPopoverProps) {
// jscpd:ignore-start
const state = useStore<DBPopoverState>({
initialized: false,
isExpanded: false,
handleAutoPlacement: () => {
state.isExpanded = true;
if (!ref) return;
const article = ref.querySelector('article');
if (!article) return;
handleDataOutside(article);
},
// eslint-disable-next-line @typescript-eslint/no-explicit-any
handleLeave: (event: any) => {
const element = event.target as HTMLElement;
const parent = element.parentNode;
if (
!parent ||
(element.parentNode.querySelector(':focus') !== element &&
element.parentNode.querySelector(':focus-within') !==
element &&
element.parentNode.querySelector(':hover') !== element)
) {
state.isExpanded = false;
}
},
getTrigger: () => {
if (ref) {
const children: Element[] = Array.from(ref.children);
if (children.length >= 2) {
const firstChild = children[0];
if (firstChild.tagName.includes('-')) {
// this is a workaround for custom angular components
return firstChild.children?.length > 0
? firstChild.children[0]
: undefined;
} else {
return firstChild;
}
}
}

return undefined;
}
});

Expand All @@ -32,14 +66,23 @@ export default function DBPopover(props: DBPopoverProps) {

onUpdate(() => {
if (ref && state.initialized) {
const children: Element[] = Array.from(ref.children);
if (children.length >= 2) {
children[0].ariaHasPopup = 'true';
const child = state.getTrigger();
if (child) {
child.ariaHasPopup = 'true';
}
state.initialized = false;
}
}, [ref, state.initialized]);

onUpdate(() => {
if (ref) {
const child = state.getTrigger();
if (child) {
child.ariaExpanded = state.isExpanded.toString();
}
}
}, [ref, state.isExpanded]);

// jscpd:ignore-end

return (
Expand All @@ -48,7 +91,9 @@ export default function DBPopover(props: DBPopoverProps) {
id={props.id}
class={cls('db-popover', props.className)}
onFocus={() => state.handleAutoPlacement()}
onMouseEnter={() => state.handleAutoPlacement()}>
onBlur={(event: FocusEvent) => state.handleLeave(event)}
onMouseEnter={() => state.handleAutoPlacement()}
onMouseLeave={(event: MouseEvent) => state.handleLeave(event)}>
<Slot name="trigger" />
<article
class="db-popover-content"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
["article","list 2 items","• Popover Custom Item 1 1 of 2","• Popover Custom Item 2 2 of 2","end of list","Functional menu pop up button","end of article","(Default) Regular menu pop up button"]
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
["(Default) Regular, menu button, expanded, sub Menu","list, with 2 items, bullet Popover Custom Item 1","bullet Popover Custom Item 2","out of list, button, Popover Custom Item 3","menu button, collapsed, sub Menu, Expressive"]
6 changes: 5 additions & 1 deletion showcases/screen-reader/default.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,9 @@ const standardPhrases = [
'To select',
'To interact',
'Press Control',
'To begin interacting'
'To begin interacting',
'To display a',
'To move between items'
];

const cleanSpeakInstructions = (phraseLog: string[]): string[] =>
Expand All @@ -35,6 +37,8 @@ const cleanSpeakInstructions = (phraseLog: string[]): string[] =>
!standardPhrases.some((string) => sPhrase.includes(string))
)
.join('. ')
// We need to replace specific phrases, as they are being reported differently on localhost and within CI/CD
.replaceAll('pop-up', 'pop up')
);

export const generateSnapshot = async (
Expand Down
33 changes: 33 additions & 0 deletions showcases/screen-reader/tests/popover.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { getTest, testDefault } from '../default';

const test = getTest();
test.describe('DBPopover', () => {
testDefault({
test,
title: 'opened',
description: 'should open the popover',
url: './#/01/popover?page=density',
async testFn(voiceOver, nvda) {
if (nvda) {
await nvda?.act(); // Opening first popover
await nvda?.press('Tab'); // Tab to button inside popover
await nvda?.next(); // Navigating to default button
await nvda?.clearSpokenPhraseLog();
await nvda?.act(); // Read button + opening second popover -> should jump to article
await nvda?.next(); // Navigating to first item of list within popover
await nvda?.next(); // Navigating to section item of list within popover
await nvda?.next(); // Navigating to button within popover
await nvda?.next(); // Navigating to next button
} else if (voiceOver) {
await voiceOver?.next(); // Opening first popover and navigating to the included "article"
await voiceOver?.next(); // Navigating to list within popover
await voiceOver?.next(); // Navigating to first item of list within popover
await voiceOver?.next(); // Navigating to section item of list within popover
await voiceOver?.next(); // Navigating to end of list within popover
await voiceOver?.next(); // Navigating to button within popover
await voiceOver?.next(); // Navigating to end of article
await voiceOver?.next(); // Navigating to next button and open next popover
}
}
});
});

0 comments on commit 6f2482d

Please sign in to comment.