Skip to content

Commit 9a61fd1

Browse files
chore(Popover): Include OUIAProps for Popover (#12572)
* chore(Popover): Include OUIAProps for Popover Add OUIA attribute support to Popover for better test automation. OUIA attributes are applied to the FocusTrap dialog root. Co-authored-by: Cursor <cursoragent@cursor.com> * Update snapshots for datepicker --------- Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent 329549e commit 9a61fd1

4 files changed

Lines changed: 69 additions & 15 deletions

File tree

packages/react-core/src/components/DatePicker/__tests__/__snapshots__/DatePicker.test.tsx.snap

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ exports[`With popover opened 1`] = `
2121
<input
2222
aria-invalid="false"
2323
aria-label="Date picker"
24-
data-ouia-component-id="OUIA-Generated-TextInputBase-:rq:"
24+
data-ouia-component-id="OUIA-Generated-TextInputBase-:r11:"
2525
data-ouia-component-type="PF6/TextInput"
2626
data-ouia-safe="true"
2727
placeholder="YYYY-MM-DD"
@@ -37,7 +37,7 @@ exports[`With popover opened 1`] = `
3737
aria-haspopup="dialog"
3838
aria-label="Toggle date picker"
3939
class="pf-v6-c-button pf-m-control"
40-
data-ouia-component-id="OUIA-Generated-Button-control-:rr:"
40+
data-ouia-component-id="OUIA-Generated-Button-control-:r12:"
4141
data-ouia-component-type="PF6/Button"
4242
data-ouia-safe="true"
4343
type="button"
@@ -64,10 +64,13 @@ exports[`With popover opened 1`] = `
6464
</div>
6565
</div>
6666
<div
67-
aria-describedby="popover-pf-:ro:-body"
67+
aria-describedby="popover-pf-:ru:-body"
6868
aria-label=""
6969
aria-modal="true"
7070
class="pf-v6-c-popover pf-m-no-padding pf-m-width-auto pf-m-bottom"
71+
data-ouia-component-id="OUIA-Generated-Popover-:rv:"
72+
data-ouia-component-type="PF6/Popover"
73+
data-ouia-safe="true"
7174
data-popper-escaped="true"
7275
data-popper-placement="bottom"
7376
data-popper-reference-hidden="true"
@@ -82,7 +85,7 @@ exports[`With popover opened 1`] = `
8285
>
8386
<div
8487
class="pf-v6-c-popover__body"
85-
id="popover-pf-:ro:-body"
88+
id="popover-pf-:ru:-body"
8689
>
8790
<div
8891
class="pf-v6-c-calendar-month"
@@ -96,7 +99,7 @@ exports[`With popover opened 1`] = `
9699
<button
97100
aria-label="Previous month"
98101
class="pf-v6-c-button pf-m-plain"
99-
data-ouia-component-id="OUIA-Generated-Button-plain-:rt:"
102+
data-ouia-component-id="OUIA-Generated-Button-plain-:r14:"
100103
data-ouia-component-type="PF6/Button"
101104
data-ouia-safe="true"
102105
type="button"
@@ -131,15 +134,15 @@ exports[`With popover opened 1`] = `
131134
>
132135
<span
133136
hidden=""
134-
id="hidden-month-span:rs:"
137+
id="hidden-month-span:r13:"
135138
>
136139
Month
137140
</span>
138141
<button
139142
aria-expanded="false"
140143
aria-haspopup="menu"
141144
class="pf-v6-c-menu-toggle"
142-
data-ouia-component-id="OUIA-Generated-MenuToggle-:r10:"
145+
data-ouia-component-id="OUIA-Generated-MenuToggle-:r17:"
143146
data-ouia-component-type="PF6/MenuToggle"
144147
data-ouia-safe="true"
145148
style="width: 140px;"
@@ -186,7 +189,7 @@ exports[`With popover opened 1`] = `
186189
<input
187190
aria-invalid="false"
188191
aria-label="Select year"
189-
data-ouia-component-id="OUIA-Generated-TextInputBase-:r12:"
192+
data-ouia-component-id="OUIA-Generated-TextInputBase-:r19:"
190193
data-ouia-component-type="PF6/TextInput"
191194
data-ouia-safe="true"
192195
type="number"
@@ -202,7 +205,7 @@ exports[`With popover opened 1`] = `
202205
<button
203206
aria-label="Next month"
204207
class="pf-v6-c-button pf-m-plain"
205-
data-ouia-component-id="OUIA-Generated-Button-plain-:r13:"
208+
data-ouia-component-id="OUIA-Generated-Button-plain-:r1a:"
206209
data-ouia-component-type="PF6/Button"
207210
data-ouia-safe="true"
208211
type="button"
@@ -813,7 +816,7 @@ exports[`disabled date picker 1`] = `
813816
<input
814817
aria-invalid="false"
815818
aria-label="disabled date picker"
816-
data-ouia-component-id="OUIA-Generated-TextInputBase-:r2:"
819+
data-ouia-component-id="OUIA-Generated-TextInputBase-:r3:"
817820
data-ouia-component-type="PF6/TextInput"
818821
data-ouia-safe="true"
819822
disabled=""
@@ -830,7 +833,7 @@ exports[`disabled date picker 1`] = `
830833
aria-haspopup="dialog"
831834
aria-label="Toggle date picker"
832835
class="pf-v6-c-button pf-m-control"
833-
data-ouia-component-id="OUIA-Generated-Button-control-:r3:"
836+
data-ouia-component-id="OUIA-Generated-Button-control-:r4:"
834837
data-ouia-component-type="PF6/Button"
835838
data-ouia-safe="true"
836839
disabled=""

packages/react-core/src/components/Popover/Popover.tsx

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,8 @@ import { PopoverCloseButton } from './PopoverCloseButton';
1111
import { PopoverArrow } from './PopoverArrow';
1212
import popoverMaxWidth from '@patternfly/react-tokens/dist/esm/c_popover_MaxWidth';
1313
import popoverMinWidth from '@patternfly/react-tokens/dist/esm/c_popover_MinWidth';
14-
import { FocusTrap } from '../../helpers';
14+
import { FocusTrap, useSSRSafeId, useOUIAProps, OUIAProps } from '../../helpers';
1515
import { Popper } from '../../helpers/Popper/Popper';
16-
import { useSSRSafeId } from '../../helpers';
1716

1817
export enum PopoverPosition {
1918
auto = 'auto',
@@ -35,7 +34,7 @@ export enum PopoverPosition {
3534
* that has a property specifically for passing in popover properties.
3635
*/
3736

38-
export interface PopoverProps {
37+
export interface PopoverProps extends OUIAProps {
3938
/** Text announced by screen reader when alert severity variant is set to indicate
4039
* severity level.
4140
*/
@@ -213,6 +212,10 @@ export interface PopoverProps {
213212
withFocusTrap?: boolean;
214213
/** The z-index of the popover. */
215214
zIndex?: number;
215+
/** Value to overwrite the randomly generated data-ouia-component-id.*/
216+
ouiaId?: number | string;
217+
/** Set the value of data-ouia-safe. Only set to true when the component is in a static state, i.e. no animations are occurring. At all other times, this value must be false. */
218+
ouiaSafe?: boolean;
216219
}
217220

218221
const alertStyle = {
@@ -274,12 +277,15 @@ export const Popover: React.FunctionComponent<PopoverProps> = ({
274277
hasNoPadding = false,
275278
hasAutoWidth = false,
276279
elementToFocus,
280+
ouiaId,
281+
ouiaSafe = true,
277282
...rest
278283
}: PopoverProps) => {
279284
// could make this a prop in the future (true | false | 'toggle')
280285
// const hideOnClick = true;
281286
const generatedId = useSSRSafeId();
282287
const uniqueId = id || generatedId;
288+
const ouiaProps = useOUIAProps(Popover.displayName, ouiaId, ouiaSafe);
283289
const triggerManually = isVisible !== null;
284290
const [visible, setVisible] = useState(false);
285291
const [focusTrapActive, setFocusTrapActive] = useState(Boolean(propWithFocusTrap));
@@ -475,6 +481,7 @@ export const Popover: React.FunctionComponent<PopoverProps> = ({
475481
maxWidth: hasCustomMaxWidth ? maxWidth : null
476482
}}
477483
{...rest}
484+
{...ouiaProps}
478485
>
479486
<PopoverArrow />
480487
<PopoverContent>

packages/react-core/src/components/Popover/__tests__/Popover.test.tsx

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { StrictMode } from 'react';
2-
import { render } from '@testing-library/react';
2+
import { render, screen } from '@testing-library/react';
33
import { Popover, PopoverPosition } from '../Popover';
44

55
test('popover renders close-button, header and body', () => {
@@ -9,6 +9,7 @@ test('popover renders close-button, header and body', () => {
99
position="top"
1010
isVisible
1111
hideOnOutsideClick
12+
ouiaId="ouia-id"
1213
headerContent={<div>Popover Header</div>}
1314
bodyContent={
1415
<div>
@@ -114,3 +115,45 @@ test('popover renders in strict mode', () => {
114115
expect(consoleError).not.toHaveBeenCalled();
115116
expect(asFragment()).toMatchSnapshot();
116117
});
118+
119+
test('Renders with custom ouiaId', () => {
120+
render(
121+
<Popover isVisible ouiaId="test-id" headerContent={<div>Popover Header</div>} bodyContent={<div>Popover body</div>}>
122+
<div>Toggle Popover</div>
123+
</Popover>
124+
);
125+
expect(screen.getByRole('dialog')).toHaveAttribute('data-ouia-component-id', 'test-id');
126+
});
127+
128+
test('Renders with expected ouia component type', () => {
129+
render(
130+
<Popover isVisible ouiaId="test-id" headerContent={<div>Popover Header</div>} bodyContent={<div>Popover body</div>}>
131+
<div>Toggle Popover</div>
132+
</Popover>
133+
);
134+
expect(screen.getByRole('dialog')).toHaveAttribute('data-ouia-component-type', 'PF6/Popover');
135+
});
136+
137+
test('Renders with ouiaSafe defaulting to true', () => {
138+
render(
139+
<Popover isVisible ouiaId="test-id" headerContent={<div>Popover Header</div>} bodyContent={<div>Popover body</div>}>
140+
<div>Toggle Popover</div>
141+
</Popover>
142+
);
143+
expect(screen.getByRole('dialog')).toHaveAttribute('data-ouia-safe', 'true');
144+
});
145+
146+
test('Renders with ouiaSafe=false when specified', () => {
147+
render(
148+
<Popover
149+
isVisible
150+
ouiaId="test-id"
151+
ouiaSafe={false}
152+
headerContent={<div>Popover Header</div>}
153+
bodyContent={<div>Popover body</div>}
154+
>
155+
<div>Toggle Popover</div>
156+
</Popover>
157+
);
158+
expect(screen.getByRole('dialog')).toHaveAttribute('data-ouia-safe', 'false');
159+
});

packages/react-core/src/helpers/OUIA/OUIA.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ component.
7171
* [NavExpandable](/components/navigation)
7272
* [NavItem](/components/navigation)
7373
* [Pagination](/components/pagination)
74+
* [Popover](/components/popover)
7475
* [Progress](/components/progress)
7576
* [Radio](/components/forms/radio)
7677
* [Select](/components/menus/select)

0 commit comments

Comments
 (0)