Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Adds test id to flashbar dom selector #2955

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ exports[`test-utils selectors 1`] = `
],
"anchor-navigation": [
"awsui_anchor-item--active_17oho",
"awsui_anchor-item_17oho",
Copy link
Contributor Author

@orangevolon orangevolon Nov 8, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is residual snapshot change from #2855.

Since we are merging to the project branch feat/test-utils-project-m2 rather than main, this wasn't caught by the Github checks.

You can ignore this one.

"awsui_anchor-link-info_17oho",
"awsui_anchor-link-text_17oho",
"awsui_anchor-link_17oho",
Expand Down
79 changes: 79 additions & 0 deletions src/flashbar/__tests__/collapsible.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,85 @@ describe('Collapsible Flashbar', () => {
});
});

test('assigns data-testid to flash items', () => {
const wrapper = renderFlashbar({
items: [
{
testId: 'flash-item-1',
content: 'first flash item',
},
{
testId: 'flash-item-2',
content: 'second flash item',
},
],
});
findNotificationBar(wrapper)!.click();
const flashbarItemsTestIds = wrapper
.findItems()
.map(flashbar => flashbar.getElement()!.getAttribute('data-testid'));

expect(flashbarItemsTestIds).toEqual(['flash-item-1', 'flash-item-2']);
});

test('findItemByTestId', () => {
const wrapper = renderFlashbar({
items: [
{
testId: 'flash-item-1',
content: 'first flash item',
},
{
testId: 'flash-item-2',
content: 'second flash item',
},
],
});
findNotificationBar(wrapper)!.click();
const secondFlashItemFromTestId = wrapper.findItemByTestId('flash-item-2')!.getElement();

expect(secondFlashItemFromTestId).toHaveTextContent('second flash item');
});

test('findItemByTestId returns the item even if the test ID contains double quotes', () => {
const wrapper = renderFlashbar({
items: [
{
testId: '"flash-item-1"',
content: 'first flash item',
},
{
testId: '"flash-item-2"',
content: 'second flash item',
},
],
});
findNotificationBar(wrapper)!.click();
const flashItem = wrapper.findItemByTestId('"flash-item-1"')!.getElement();

expect(flashItem).toHaveTextContent('first flash item');
});

test('findItemByTestId doesn not return the next items if the collapsible is not expanded', () => {
const wrapper = renderFlashbar({
items: [
{
testId: 'flash-item-1',
content: 'first flash item',
},
{
testId: 'flash-item-2',
content: 'second flash item',
},
],
});
const fistFlashItem = wrapper.findItemByTestId('flash-item-1');
const secondFlashItem = wrapper.findItemByTestId('flash-item-2');

expect(fistFlashItem).toBeTruthy();
expect(secondFlashItem).not.toBeTruthy();
});

test('findItemsByType', () => {
{
const wrapper = createFlashbarWrapper(
Expand Down
61 changes: 61 additions & 0 deletions src/flashbar/__tests__/flashbar.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,67 @@ describe('Flashbar component', () => {
}
});

test('assigns data-testid to flash items', () => {
const { container } = reactRender(
<Flashbar
items={[
{
testId: 'flash-item-1',
content: 'first flash item',
},
{
testId: 'flash-item-2',
content: 'second flash item',
},
]}
/>
);
const wrapper = createWrapper(container);
const flashbarItemsTestIds = wrapper
.findFlashbar()!
.findItems()
.map(flashbar => flashbar.getElement()!.getAttribute('data-testid'));

expect(flashbarItemsTestIds).toEqual(['flash-item-1', 'flash-item-2']);
});

test('findItemByTestId', () => {
const { container } = reactRender(
<Flashbar
items={[
{
testId: 'flash-item-1',
content: 'first flash item',
},
{
testId: 'flash-item-2',
content: 'second flash item',
},
]}
/>
);
const wrapper = createWrapper(container);
const secondFlashItemFromTestId = wrapper.findFlashbar()!.findItemByTestId('flash-item-2')!.getElement();
expect(secondFlashItemFromTestId).toHaveTextContent('second flash item');
});

test('findItemByTestId returns the item even if the test ID contains double quotes', () => {
const { container } = reactRender(
<Flashbar
items={[
{
testId: '"flash-item-test-id"',
content: 'flash item',
},
]}
/>
);
const wrapper = createWrapper(container);
const flashItem = wrapper.findFlashbar()?.findItemByTestId('"flash-item-test-id"')!.getElement();

expect(flashItem).toHaveTextContent('flash item');
});

test('findItemsByType', () => {
const wrapper = createFlashbarWrapper(
<Flashbar
Expand Down
1 change: 1 addition & 0 deletions src/flashbar/collapsible-flashbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,7 @@ export default function CollapsibleFlashbar({ items, ...restProps }: FlashbarPro
{(state: string, transitionRootElement: React.Ref<HTMLDivElement> | undefined) => (
<li
aria-hidden={!showInnerContent(item)}
data-testid={item.testId}
className={
showInnerContent(item)
? clsx(
Expand Down
2 changes: 1 addition & 1 deletion src/flashbar/flash.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ export const focusFlashById = throttle(
{ trailing: false }
);

export interface FlashProps extends FlashbarProps.MessageDefinition {
export interface FlashProps extends Omit<FlashbarProps.MessageDefinition, 'testId'> {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's a bit of an inconsistency when it comes to FlashWrapper.

FlashWrapper should point to the list item and not the flash component itself:

static rootSelector: string = styles['flash-list-item'];

But the existing findFlashByType returns the flash rather than the parent <li />:

return this.findAll(`.${styles['flash-list-item']} .${styles[`flash-type-${type}`]}`).map(

To make sure than this mistake doesn't happen with testId I omitted that from the FlashProps so that it is not assigned by mistake in the future.

className: string;
transitionState?: string;
i18nStrings?: FlashbarProps.I18nStrings;
Expand Down
7 changes: 7 additions & 0 deletions src/flashbar/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,13 @@ export namespace FlashbarProps {
buttonText?: ButtonProps['children'];
onButtonClick?: ButtonProps['onClick'];
onDismiss?: ButtonProps['onClick'];

/**
* Test ID of the flash list item.
* Assigns this value to the `data-testid` attribute of the flash list item.
* Flash component is the direct child of the flash list item.
*/
testId?: string;
}

export interface I18nStrings {
Expand Down
3 changes: 2 additions & 1 deletion src/flashbar/non-collapsible-flashbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ export default function NonCollapsibleFlashbar({ items, i18nStrings, ...restProp
in={true}
>
{(state: string, transitionRootElement: React.Ref<HTMLDivElement> | undefined) => (
<li className={styles['flash-list-item']}>
<li className={styles['flash-list-item']} data-testid={item.testId}>
{renderItem(item, item.id ?? index, transitionRootElement, state)}
</li>
)}
Expand Down Expand Up @@ -91,6 +91,7 @@ export default function NonCollapsibleFlashbar({ items, i18nStrings, ...restProp
<li
key={item.id ?? index}
className={styles['flash-list-item']}
data-testid={item.testId}
{...getAnalyticsMetadataAttribute(getItemAnalyticsMetadata(index + 1, item.type || 'info', item.id))}
>
{renderItem(item, item.id ?? index)}
Expand Down
7 changes: 3 additions & 4 deletions src/test-utils/dom/anchor-navigation/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
import { ComponentWrapper, ElementWrapper, usesDom } from '@cloudscape-design/test-utils-core/dom';
import { escapeSelector } from '@cloudscape-design/test-utils-core/utils.js';

import testUtilStyles from '../../../anchor-navigation/test-classes/styles.selectors.js';

Expand Down Expand Up @@ -42,10 +43,8 @@ export default class AnchorNavigationWrapper extends ComponentWrapper {
* @returns {AnchorItemWrapper | null}
*/
findAnchorByTestId(testId: string): AnchorItemWrapper | null {
return this.findComponent(
`.${testUtilStyles['anchor-item']}[data-testid="${CSS.escape(testId)}"]`,
AnchorItemWrapper
);
const escapedTestId = escapeSelector(testId);
return this.findComponent(`.${testUtilStyles['anchor-item']}[data-testid="${escapedTestId}"]`, AnchorItemWrapper);
}
}

Expand Down
16 changes: 16 additions & 0 deletions src/test-utils/dom/flashbar/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
import { ComponentWrapper, ElementWrapper } from '@cloudscape-design/test-utils-core/dom';
import { escapeSelector } from '@cloudscape-design/test-utils-core/utils';

import FlashWrapper from './flash';

Expand Down Expand Up @@ -31,6 +32,21 @@ export default class FlashbarWrapper extends ComponentWrapper {
);
}

/**
* Returns the wrapper of the first flash list item that matches the specified test ID.
* If the items are stacked, the hidden items will not be returned.
*
* Looks for the `data-testid` attribute that is assigned via `items` prop.
* If no matching flash list item is found, returns `null`.
*
* @param {string} testId
* @returns {FlashbarWrapper | null}
*/
findItemByTestId(testId: string): FlashWrapper | null {
const escapedTestId = escapeSelector(testId);
return this.findComponent(`.${styles['flash-list-item']}[data-testid="${escapedTestId}"]`, FlashWrapper);
}

/**
* Returns the toggle button that expands and collapses stacked notifications.
*/
Expand Down