From 3688b4803840e9ef7fb168ff1be5093f6ed0f008 Mon Sep 17 00:00:00 2001 From: Luca Bezerra Date: Thu, 5 Aug 2021 13:42:23 -0400 Subject: [PATCH 01/16] Switch to using mountWithApp on ResourceItem tests. --- .../ResourceItem/tests/ResourceItem.test.tsx | 317 +++++++++++------- 1 file changed, 197 insertions(+), 120 deletions(-) diff --git a/src/components/ResourceItem/tests/ResourceItem.test.tsx b/src/components/ResourceItem/tests/ResourceItem.test.tsx index 3eb66f9fb10..92ed857caa6 100644 --- a/src/components/ResourceItem/tests/ResourceItem.test.tsx +++ b/src/components/ResourceItem/tests/ResourceItem.test.tsx @@ -1,10 +1,4 @@ import React from 'react'; -// eslint-disable-next-line no-restricted-imports -import { - findByTestID, - mountWithAppProvider, - trigger, -} from 'test-utilities/legacy'; import {mountWithApp} from 'test-utilities'; import { Avatar, @@ -15,8 +9,10 @@ import { Button, } from 'components'; -import {ResourceListContext} from '../../../utilities/resource-list'; import {ResourceItem} from '../ResourceItem'; +import {classNames} from '../../../utilities/css'; +import {ResourceListContext} from '../../../utilities/resource-list'; +import styles from '../ResourceItem.scss'; describe('', () => { let spy: jest.SpyInstance; @@ -77,7 +73,7 @@ describe('', () => { describe('accessibilityLabel', () => { it('is used on the for the aria-label attribute', () => { - const item = mountWithAppProvider( + const item = mountWithApp( ', () => { , ); - expect(item.find(UnstyledLink).prop('aria-label')).toBe( - accessibilityLabel, - ); + expect(item).toContainReactComponent(UnstyledLink, { + 'aria-label': accessibilityLabel, + }); }); }); describe('name', () => { it('is used as the Checkbox label', () => { - const item = mountWithAppProvider( + const item = mountWithApp( ', () => { const expectedLabel = name; - expect(item.find(Checkbox).prop('label')).toBe(expectedLabel); + expect(item).toContainReactComponent(Checkbox, {label: expectedLabel}); }); it('is used on for the aria-label attribute if an `accessibilityLabel` is not provided', () => { - const item = mountWithAppProvider( + const item = mountWithApp( , @@ -120,11 +116,13 @@ describe('', () => { const expectedLabel = `View details for ${name}`; - expect(item.find(UnstyledLink).prop('aria-label')).toBe(expectedLabel); + expect(item).toContainReactComponent(UnstyledLink, { + 'aria-label': expectedLabel, + }); }); it('is used on the disclosure action menu when there are persistent actions', () => { - const item = mountWithAppProvider( + const item = mountWithApp( ', () => { const expectedLabel = `Actions for ${name}`; - expect( - item - .find(Button) - .findWhere( - (node) => - node.prop('plain') && - node.prop('accessibilityLabel') === expectedLabel, - ), - ).toHaveLength(1); + expect(item).toContainReactComponentTimes(Button, 1, { + plain: true, + accessibilityLabel: expectedLabel, + }); }); }); describe('ResourceName.singular', () => { it('is used on for the aria-label attribute if a `name` and `accessibilityLabel` is not provided', () => { - const item = mountWithAppProvider( + const item = mountWithApp( , @@ -161,13 +154,15 @@ describe('', () => { const expectedLabel = `View details for ${mockDefaultContext.resourceName.singular}`; - expect(item.find(UnstyledLink).prop('aria-label')).toBe(expectedLabel); + expect(item).toContainReactComponent(UnstyledLink, { + 'aria-label': expectedLabel, + }); }); }); describe('url', () => { it('does not render an by default', () => { - const element = mountWithAppProvider( + const element = mountWithApp( ', () => { , ); - expect(element.find(UnstyledLink).exists()).toBe(false); + expect(element).not.toContainReactComponent(UnstyledLink); }); it('renders an ', () => { - const element = mountWithAppProvider( + const element = mountWithApp( , ); - expect(element.find(UnstyledLink).exists()).toBe(true); + expect(element).toContainReactComponent(UnstyledLink); }); it('renders an with url', () => { - const element = mountWithAppProvider( + const element = mountWithApp( , ); - expect(element.find(UnstyledLink).prop('url')).toBe(url); + expect(element).toContainReactComponent(UnstyledLink, {url}); }); it('renders an with an aria-label of ariaLabel', () => { - const element = mountWithAppProvider( + const element = mountWithApp( , ); - expect(element.find(UnstyledLink).prop('aria-label')).toBe(ariaLabel); + expect(element).toContainReactComponent(UnstyledLink, { + 'aria-label': ariaLabel, + }); }); it('adds a data-href to the wrapper element', () => { - const element = mountWithAppProvider( + const element = mountWithApp( , ); - expect(findByTestID(element, 'Item-Wrapper').prop('data-href')).toBe(url); + expect(element).toContainReactComponent('div', {'data-href': url}); }); }); describe('external', () => { it('renders an with undefined external prop', () => { - const element = mountWithAppProvider( + const element = mountWithApp( , ); - expect(element.find(UnstyledLink).prop('external')).toBeUndefined(); + expect(element).toContainReactComponent(UnstyledLink, { + external: undefined, + }); }); it('renders an with external set to true', () => { - const element = mountWithAppProvider( + const element = mountWithApp( ', () => { , ); - expect(element.find(UnstyledLink).prop('external')).toBe(true); + expect(element).toContainReactComponent(UnstyledLink, { + external: true, + }); }); it('renders an with external set to false', () => { - const element = mountWithAppProvider( + const element = mountWithApp( ', () => { , ); - expect(element.find(UnstyledLink).prop('external')).toBe(false); + expect(element).toContainReactComponent(UnstyledLink, { + external: false, + }); }); }); describe('id', () => { it('is used on the content node and for the description of a link', () => { - const item = mountWithAppProvider( + const item = mountWithApp( ', () => { , ); - expect(findByTestID(item, 'Item-Content').prop('id')).toBe(itemId); - expect(item.find(UnstyledLink).prop('aria-describedby')).toBe(itemId); + expect(item).toContainReactComponent('div', {id: itemId}); + expect(item).toContainReactComponent(UnstyledLink, { + 'aria-describedby': itemId, + }); }); }); describe('onClick()', () => { it('calls onClick when clicking on the item when onClick exists', () => { const onClick = jest.fn(); - const wrapper = mountWithAppProvider( + const wrapper = mountWithApp( ', () => { , ); - findByTestID(wrapper, 'Item-Wrapper').simulate('click'); + wrapper + .find('div', {className: styles.ResourceItem})! + .trigger('onClick', { + stopPropagation: () => {}, + nativeEvent: {}, + }); expect(onClick).toHaveBeenCalledWith(itemId); }); it('calls onClick when clicking on the item when both onClick and url exist', () => { const onClick = jest.fn(); - const wrapper = mountWithAppProvider( + const wrapper = mountWithApp( ', () => { , ); - findByTestID(wrapper, 'Item-Wrapper').simulate('click'); + wrapper + .find('div', {className: styles.ResourceItem})! + .trigger('onClick', { + stopPropagation: () => {}, + nativeEvent: {}, + }); expect(onClick).toHaveBeenCalledWith(itemId); }); it('calls window.open on metaKey + click', () => { - const wrapper = mountWithAppProvider( + const wrapper = mountWithApp( , ); - const item = findByTestID(wrapper, 'Item-Wrapper'); - trigger(item, 'onClick', { - stopPropagation: () => {}, - nativeEvent: {metaKey: true}, - }); + + wrapper + .find('div', {className: styles.ResourceItem})! + .trigger('onClick', { + stopPropagation: () => {}, + nativeEvent: {metaKey: true}, + }); expect(spy).toHaveBeenCalledWith(url, '_blank'); }); it('calls onClick when hitting keyUp on the item when onClick and URL exists', () => { const onClick = jest.fn(); - const wrapper = mountWithAppProvider( + const wrapper = mountWithApp( , ); - findByTestID(wrapper, 'Item-Wrapper').simulate('keyup', { - key: 'Enter', - }); + wrapper + .find('div', {className: styles.ResourceItem})! + .trigger('onKeyUp', {key: 'Enter'}); expect(onClick).toHaveBeenCalled(); }); it('does not call onClick when hitting keyUp on non Enter key', () => { const onClick = jest.fn(); - const wrapper = mountWithAppProvider( + const wrapper = mountWithApp( , ); - findByTestID(wrapper, 'Item-Wrapper').simulate('keyup', { - key: 'Tab', - }); + wrapper + .find('div', {className: styles.ResourceItem})! + .trigger('onKeyUp', {key: 'Tab'}); expect(onClick).not.toHaveBeenCalled(); }); it('does not call onClick when hitting keyUp on the item when no URL exists', () => { const onClick = jest.fn(); - const wrapper = mountWithAppProvider( + const wrapper = mountWithApp( , ); - findByTestID(wrapper, 'Item-Wrapper').simulate('keyup', { - key: 'Enter', - }); + wrapper + .find('div', { + className: classNames( + styles.ResourceItem, + styles.selectable, + styles.selectMode, + ), + })! + .trigger('onKeyUp', {key: 'Enter'}); expect(onClick).not.toHaveBeenCalled(); }); it('calls window.open on ctrlKey + click', () => { - const wrapper = mountWithAppProvider( + const wrapper = mountWithApp( , ); - const item = findByTestID(wrapper, 'Item-Wrapper'); - trigger(item, 'onClick', { - stopPropagation: () => {}, - nativeEvent: {ctrlKey: true}, - }); + + wrapper + .find('div', {className: styles.ResourceItem})! + .trigger('onClick', { + stopPropagation: () => {}, + nativeEvent: {ctrlKey: true}, + }); expect(spy).toHaveBeenCalledWith(url, '_blank'); }); }); @@ -391,25 +416,29 @@ describe('', () => { describe('Selectable', () => { it('does not call the Item onClick when clicking the LargerSelectionArea', () => { const onClick = jest.fn(); - const wrapper = mountWithAppProvider( + const wrapper = mountWithApp( , ); - findByTestID(wrapper, 'LargerSelectionArea').simulate('click'); + wrapper.find('div', {className: styles.Handle})!.trigger('onClick', { + stopPropagation: () => {}, + nativeEvent: {}, + }); expect(onClick).not.toHaveBeenCalled(); }); it('calls onSelectionChange with the id of the item when clicking the LargerSelectionArea', () => { const sortOrder = 0; - const wrapper = mountWithAppProvider( + const wrapper = mountWithApp( , ); - findByTestID(wrapper, 'LargerSelectionArea').simulate('click', { + wrapper.find('div', {className: styles.Handle})!.trigger('onClick', { + stopPropagation: () => {}, nativeEvent: {shiftKey: false}, }); expect(mockSelectableContext.onSelectionChange).toHaveBeenCalledWith( @@ -424,7 +453,7 @@ describe('', () => { describe('SelectMode', () => { it('calls onClick when item is clicked', () => { const onClick = jest.fn(); - const wrapper = mountWithAppProvider( + const wrapper = mountWithApp( ', () => { , ); - findByTestID(wrapper, 'Item-Wrapper').simulate('click'); + wrapper + .find('div', { + className: classNames( + styles.ResourceItem, + styles.selectable, + styles.selectMode, + ), + })! + .trigger('onClick', { + stopPropagation: () => {}, + nativeEvent: {}, + }); expect(onClick).not.toHaveBeenCalledWith(itemId); }); it('calls onSelectionChange with the id of the item even if url or onClick is present', () => { const onClick = jest.fn(); const sortOrder = 0; - const wrapper = mountWithAppProvider( + const wrapper = mountWithApp( ', () => { , ); - findByTestID(wrapper, 'Item-Wrapper').simulate('click', { - nativeEvent: {shiftKey: false}, - }); + wrapper + .find('div', { + className: classNames( + styles.ResourceItem, + styles.selectable, + styles.selectMode, + ), + })! + .trigger('onClick', { + stopPropagation: () => {}, + nativeEvent: {shiftKey: false}, + }); expect(mockSelectModeContext.onSelectionChange).toHaveBeenCalledWith( true, itemId, @@ -465,69 +514,94 @@ describe('', () => { }); it('renders a checked Checkbox if the item is in the selectedItems context', () => { - const wrapper = mountWithAppProvider( + const wrapper = mountWithApp( , ); - expect(wrapper.find(Checkbox).props().checked).toBe(true); + expect(wrapper).toContainReactComponent(Checkbox, {checked: true}); }); it('does not call window.open when clicking the item with metaKey', () => { - const wrapper = mountWithAppProvider( + const wrapper = mountWithApp( , ); - findByTestID(wrapper, 'Item-Wrapper').simulate('click', { - nativeEvent: {metaKey: true}, - }); + + wrapper + .find('div', { + className: classNames( + styles.ResourceItem, + styles.selectable, + styles.selected, + styles.selectMode, + ), + })! + .trigger('onClick', { + stopPropagation: () => {}, + nativeEvent: {metaKey: true}, + }); expect(spy).not.toHaveBeenCalled(); }); it('does not call window.open when clicking the item with ctrlKey', () => { - const wrapper = mountWithAppProvider( + const wrapper = mountWithApp( , ); - findByTestID(wrapper, 'Item-Wrapper').simulate('click', { - nativeEvent: {ctrlKey: true}, - }); + + wrapper + .find('div', { + className: classNames( + styles.ResourceItem, + styles.selectable, + styles.selected, + styles.selectMode, + ), + })! + .trigger('onClick', { + stopPropagation: () => {}, + nativeEvent: {ctrlKey: true}, + }); expect(spy).not.toHaveBeenCalled(); }); }); describe('media', () => { it('does not include media if not provided', () => { - const wrapper = mountWithAppProvider( + const wrapper = mountWithApp( , ); - expect(findByTestID(wrapper, 'Media').exists()).toBe(false); + expect(wrapper).not.toContainReactComponent('div', { + className: styles.Media, + }); }); it('renders a disabled checked Checkbox if loading context is true', () => { - const wrapper = mountWithAppProvider( + const wrapper = mountWithApp( , ); - expect(wrapper.find(Checkbox).prop('disabled')).toBe(true); + expect(wrapper).toContainReactComponent(Checkbox, {disabled: true}); }); it('includes an if one is provided', () => { - const wrapper = mountWithAppProvider( + const wrapper = mountWithApp( } /> , ); - expect(findByTestID(wrapper, 'Media').find(Avatar).exists()).toBe(true); + const media = wrapper.find('div', {className: styles.Media}); + expect(media).toContainReactComponent(Avatar); }); it('includes a if one is provided', () => { - const wrapper = mountWithAppProvider( + const wrapper = mountWithApp( ', () => { /> , ); - expect(findByTestID(wrapper, 'Media').find(Thumbnail).exists()).toBe( - true, - ); + const media = wrapper.find('div', {className: styles.Media}); + expect(media).toContainReactComponent(Thumbnail); }); }); describe('shortcutActions', () => { it('does not render shortcut actions if none are provided', () => { - const wrapper = mountWithAppProvider( + const wrapper = mountWithApp( , ); - expect(findByTestID(wrapper, 'ShortcutActions').exists()).toBe(false); + expect(wrapper).not.toContainReactComponent('div', { + className: styles.Actions, + }); }); it('renders shortcut actions when some are provided', () => { - const wrapper = mountWithAppProvider( + const wrapper = mountWithApp( ', () => { /> , ); - expect(findByTestID(wrapper, 'ShortcutActions').exists()).toBe(true); + expect(wrapper).toContainReactComponent('div', { + className: styles.Actions, + }); }); it('renders persistent shortcut actions if persistActions is true', () => { - const wrapper = mountWithAppProvider( + const wrapper = mountWithApp( ', () => { /> , ); - expect(wrapper.find(ButtonGroup).exists()).toBe(true); + expect(wrapper).toContainReactComponent(ButtonGroup); }); it('does not render while loading', () => { - const wrapper = mountWithAppProvider( + const wrapper = mountWithApp( ', () => { /> , ); - expect(wrapper.find(ButtonGroup)).toHaveLength(0); + expect(wrapper).not.toContainReactComponent(ButtonGroup); }); }); describe('accessibleMarkup', () => { it('renders with a tab index of -1 when loading is true', () => { - const wrapper = mountWithAppProvider( + const wrapper = mountWithApp( ', () => { /> , ); - expect(wrapper.find(UnstyledLink).prop('tabIndex')).toBe(-1); + expect(wrapper).toContainReactComponent(UnstyledLink, {tabIndex: -1}); }); it('renders with a tab index of 0 when loading is false', () => { - const wrapper = mountWithAppProvider( + const wrapper = mountWithApp( ', () => { /> , ); - expect(wrapper.find(UnstyledLink).prop('tabIndex')).toBe(0); + expect(wrapper).toContainReactComponent(UnstyledLink, {tabIndex: 0}); }); }); @@ -711,7 +788,7 @@ describe('', () => { describe('dataHref', () => { it('renders a data-href tag on the li when the dataHref prop is specified', () => { - const item = mountWithAppProvider( + const item = mountWithApp( ', () => { , ); - expect(item.find('li').prop('data-href')).toBe('google.com'); + expect(item).toContainReactComponent('li', {'data-href': 'google.com'}); }); it('renders a data-href tag on the li when the dataHref prop is not specified', () => { - const item = mountWithAppProvider( + const item = mountWithApp( ', () => { , ); - expect(item.find('li').prop('data-href')).toBeUndefined(); + expect(item).toContainReactComponent('li', {'data-href': undefined}); }); }); }); From c4007398831b3c62faa953087325dbddd06e0866 Mon Sep 17 00:00:00 2001 From: Luca Bezerra Date: Thu, 5 Aug 2021 13:50:04 -0400 Subject: [PATCH 02/16] Adding update to UNRELEASED.md --- UNRELEASED.md | 1 + 1 file changed, 1 insertion(+) diff --git a/UNRELEASED.md b/UNRELEASED.md index a11c7d8a097..c6dc33444cb 100644 --- a/UNRELEASED.md +++ b/UNRELEASED.md @@ -58,5 +58,6 @@ Use [the changelog guidelines](https://git.io/polaris-changelog-guidelines) to f - Modernized tests for SkeletonBodyTest, SkeletonDisplayTest, SkeletonPage, SkeletonThumbnail, and Spinner components ([#4353](https://github.com/Shopify/polaris-react/pull/4353)) - Modernized tests for Message, Menu, Search, SearchDismissOverlay, SearchField, UserMenu and TopBar components. ([#4311](https://github.com/Shopify/polaris-react/pull/4311)) +- Modernized tests for ResourceItem ([#4362](https://github.com/Shopify/polaris-react/pull/4362)) ### Deprecations From 19a60b3b7c9ba83286a19872e83c2b1ac22f62a3 Mon Sep 17 00:00:00 2001 From: Luca Bezerra Date: Thu, 5 Aug 2021 13:58:06 -0400 Subject: [PATCH 03/16] Removing testID props. --- src/components/ResourceItem/ResourceItem.tsx | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/src/components/ResourceItem/ResourceItem.tsx b/src/components/ResourceItem/ResourceItem.tsx index a514f1b84e2..b25df1af93b 100644 --- a/src/components/ResourceItem/ResourceItem.tsx +++ b/src/components/ResourceItem/ResourceItem.tsx @@ -159,9 +159,7 @@ class BaseResourceItem extends Component { let handleMarkup: React.ReactNode = null; const mediaMarkup = media ? ( -
- {media} -
+
{media}
) : null; if (selectable) { @@ -177,7 +175,6 @@ class BaseResourceItem extends Component {
{ } else { actionsMarkup = (
- + {buttonsFrom(shortcutActions, { size: 'slim', })} @@ -282,11 +279,7 @@ class BaseResourceItem extends Component { ); const containerMarkup = ( -
+
{ownedMarkup} {content} {actionsMarkup} @@ -335,7 +328,6 @@ class BaseResourceItem extends Component { onBlur={this.handleBlur} onKeyUp={this.handleKeyUp} onMouseOut={this.handleMouseOut} - testID="Item-Wrapper" data-href={url} > {accessibleMarkup} From 7244d7bea69dd17fb9ce8f5a30375382652d6981 Mon Sep 17 00:00:00 2001 From: Luca Bezerra Date: Thu, 5 Aug 2021 17:27:58 -0400 Subject: [PATCH 04/16] Fixing type-checking errors. --- .../ResourceItem/tests/ResourceItem.test.tsx | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/components/ResourceItem/tests/ResourceItem.test.tsx b/src/components/ResourceItem/tests/ResourceItem.test.tsx index 92ed857caa6..5292af4745d 100644 --- a/src/components/ResourceItem/tests/ResourceItem.test.tsx +++ b/src/components/ResourceItem/tests/ResourceItem.test.tsx @@ -214,7 +214,8 @@ describe('', () => { , ); - expect(element).toContainReactComponent('div', {'data-href': url}); + const div = element.find('div', {'data-href': url} as any); + expect(div).not.toBeNull(); }); }); @@ -798,9 +799,10 @@ describe('', () => { /> , ); - - expect(item).toContainReactComponent('li', {'data-href': 'google.com'}); + const li = item.find('li', {'data-href': 'google.com'} as any); + expect(li).not.toBeNull(); }); + it('renders a data-href tag on the li when the dataHref prop is not specified', () => { const item = mountWithApp( @@ -812,7 +814,8 @@ describe('', () => { , ); - expect(item).toContainReactComponent('li', {'data-href': undefined}); + const li = item.find('li', {'data-href': undefined} as any); + expect(li).not.toBeNull(); }); }); }); From 48d3f2505d5bc7be22258f35d653964c982af942 Mon Sep 17 00:00:00 2001 From: Luca Bezerra Date: Mon, 9 Aug 2021 13:40:52 -0400 Subject: [PATCH 05/16] Modernizing tests for ResourceList. --- UNRELEASED.md | 1 + src/components/ResourceItem/ResourceItem.tsx | 6 +- src/components/ResourceList/ResourceList.tsx | 6 +- .../ResourceList/tests/ResourceList.test.tsx | 567 ++++++++++-------- 4 files changed, 324 insertions(+), 256 deletions(-) diff --git a/UNRELEASED.md b/UNRELEASED.md index c6dc33444cb..993b1e2495b 100644 --- a/UNRELEASED.md +++ b/UNRELEASED.md @@ -59,5 +59,6 @@ Use [the changelog guidelines](https://git.io/polaris-changelog-guidelines) to f - Modernized tests for Message, Menu, Search, SearchDismissOverlay, SearchField, UserMenu and TopBar components. ([#4311](https://github.com/Shopify/polaris-react/pull/4311)) - Modernized tests for ResourceItem ([#4362](https://github.com/Shopify/polaris-react/pull/4362)) +- Modernized tests for ResourceItem, ResourceList ([#4362](https://github.com/Shopify/polaris-react/pull/4362)) ### Deprecations diff --git a/src/components/ResourceItem/ResourceItem.tsx b/src/components/ResourceItem/ResourceItem.tsx index b25df1af93b..74b8ef983c5 100644 --- a/src/components/ResourceItem/ResourceItem.tsx +++ b/src/components/ResourceItem/ResourceItem.tsx @@ -167,11 +167,7 @@ class BaseResourceItem extends Component { name || accessibilityLabel || i18n.translate('Polaris.Common.checkbox'); handleMarkup = ( -
+
({ ) : null; const headerTitleMarkup = ( -
- {headerTitle()} -
+
{headerTitle()}
); const selectButtonMarkup = isSelectable ? ( @@ -639,7 +637,7 @@ export const ResourceList: ResourceListType = function ResourceList({ isSticky && styles['HeaderWrapper-isSticky'], ); return ( -
+
{headerWrapperOverlay}
diff --git a/src/components/ResourceList/tests/ResourceList.test.tsx b/src/components/ResourceList/tests/ResourceList.test.tsx index a11c9548803..8edf82934ce 100644 --- a/src/components/ResourceList/tests/ResourceList.test.tsx +++ b/src/components/ResourceList/tests/ResourceList.test.tsx @@ -10,17 +10,15 @@ import { EmptyState, } from 'components'; import {mountWithApp} from 'test-utilities'; -// eslint-disable-next-line no-restricted-imports -import { - findByTestID, - mountWithAppProvider, - trigger, -} from 'test-utilities/legacy'; import {SELECT_ALL_ITEMS} from 'utilities/resource-list'; import {BulkActions} from '../../BulkActions'; import {CheckableButton} from '../../CheckableButton'; +import {classNames} from '../../../utilities/css'; + +import styles from '../ResourceList.scss'; + const itemsNoID = [{url: 'item 1'}, {url: 'item 2'}]; const singleItemNoID = [{url: 'item 1'}]; const singleItemWithID = [{id: '1', url: 'item 1'}]; @@ -53,10 +51,10 @@ const defaultWindowWidth = window.innerWidth; describe('', () => { describe('renderItem', () => { it('renders list items', () => { - const resourceList = mountWithAppProvider( + const resourceList = mountWithApp( , ); - expect(resourceList.find('li')).toHaveLength(3); + expect(resourceList).toContainReactComponentTimes('li', 3); }); it('renders custom markup and warns user', () => { @@ -64,10 +62,11 @@ describe('', () => { const warningSpy = jest .spyOn(console, 'warn') .mockImplementation(() => {}); - const resourceList = mountWithAppProvider( + const resourceList = mountWithApp( , ); - expect(resourceList.find('li').first().text()).toBe('title 1'); + expect(resourceList).toContainReactText('title 1'); + // expect(resourceList.find('li').first().text()).toBe('title 1'); expect(warningSpy).toHaveBeenCalledWith( ' renderItem function should return a .', ); @@ -78,66 +77,65 @@ describe('', () => { describe('Selectable', () => { it('does not render bulk actions if the promotedBulkActions and the bulkActions props are not provided', () => { - const resourceList = mountWithAppProvider( + const resourceList = mountWithApp( , ); - expect(resourceList.find(BulkActions).exists()).toBe(false); + expect(resourceList).not.toContainReactComponent(BulkActions); }); it('does not render a `CheckableButton` if the `selectable` prop is not provided', () => { - const resourceList = mountWithAppProvider( + const resourceList = mountWithApp( , ); - expect(resourceList.find(CheckableButton).exists()).toBe(false); + expect(resourceList).not.toContainReactComponent(CheckableButton); }); it('does render bulk actions if the promotedBulkActions prop is provided', () => { - const resourceList = mountWithAppProvider( + const resourceList = mountWithApp( , ); - - expect(resourceList.find(BulkActions).exists()).toBe(true); + expect(resourceList).toContainReactComponent(BulkActions); }); it('renders bulk actions if the bulkActions prop is provided', () => { - const resourceList = mountWithAppProvider( + const resourceList = mountWithApp( , ); - expect(resourceList.find(BulkActions).exists()).toBe(true); + expect(resourceList).toContainReactComponent(BulkActions); }); it('renders a `CheckableButton` if the `selectable` prop is true', () => { - const resourceList = mountWithAppProvider( + const resourceList = mountWithApp( , ); - expect(resourceList.find(CheckableButton).exists()).toBe(true); + expect(resourceList).toContainReactComponent(CheckableButton); }); }); describe('hasMoreItems', () => { it('does not add a prop of paginatedSelectAllAction to BulkActions if omitted', () => { - const resourceList = mountWithAppProvider( + const resourceList = mountWithApp( , ); - expect( - resourceList.find(BulkActions).prop('paginatedSelectAllAction'), - ).toBeUndefined(); + expect(resourceList).toContainReactComponent(BulkActions, { + paginatedSelectAllAction: undefined, + }); }); it('adds a prop of paginatedSelectAllAction to BulkActions if included', () => { - const resourceList = mountWithAppProvider( + const resourceList = mountWithApp( ', () => { bulkActions={bulkActions} />, ); + expect(resourceList).toContainReactComponent(BulkActions); expect( - resourceList.find(BulkActions).prop('paginatedSelectAllAction'), - ).toBeDefined(); + resourceList.find(BulkActions)!.props.paginatedSelectAllAction, + ).not.toBe(undefined); }); }); describe('resourceName', () => { describe('resoureName.singular', () => { it('renders default singular resource name when resourceName isn’t provided', () => { - const resourceList = mountWithAppProvider( + const resourceList = mountWithApp( , ); - expect(findByTestID(resourceList, 'headerTitleWrapper').text()).toBe( - 'Showing 1 item', - ); + const headerTitleWrapper = resourceList.find('div', { + className: styles.HeaderTitleWrapper, + }); + expect(headerTitleWrapper).toContainReactText('Showing 1 item'); }); it('renders the given singular resource name when resourceName is provided', () => { - const resourceList = mountWithAppProvider( + const resourceList = mountWithApp( ', () => { showHeader />, ); - expect(findByTestID(resourceList, 'headerTitleWrapper').text()).toBe( - 'Showing 1 product', - ); + const headerTitleWrapper = resourceList.find('div', { + className: styles.HeaderTitleWrapper, + }); + expect(headerTitleWrapper).toContainReactText('Showing 1 product'); }); }); - describe('resoureName.plural', () => { + describe('resourceName.plural', () => { it('renders default plural resource name when resourceName isn’t provided', () => { - const resourceList = mountWithAppProvider( + const resourceList = mountWithApp( , ); - expect(findByTestID(resourceList, 'headerTitleWrapper').text()).toBe( - 'Showing 2 items', - ); + const headerTitleWrapper = resourceList.find('div', { + className: styles.HeaderTitleWrapper, + }); + expect(headerTitleWrapper).toContainReactText('Showing 2 items'); }); it('renders the given plural resource name when resourceName is provided', () => { - const resourceList = mountWithAppProvider( + const resourceList = mountWithApp( ', () => { showHeader />, ); - expect(findByTestID(resourceList, 'headerTitleWrapper').text()).toBe( - 'Showing 2 products', - ); + const headerTitleWrapper = resourceList.find('div', { + className: styles.HeaderTitleWrapper, + }); + expect(headerTitleWrapper).toContainReactText('Showing 2 products'); }); }); }); describe('headerTitle', () => { it('prints loading text when loading is true', () => { - const resourceList = mountWithAppProvider( + const resourceList = mountWithApp( ', () => { />, ); - expect(findByTestID(resourceList, 'headerTitleWrapper').text()).toBe( - 'Loading items', - ); + const headerTitleWrapper = resourceList.find('div', { + className: styles.HeaderTitleWrapper, + }); + expect(headerTitleWrapper).toContainReactText('Loading items'); }); it('prints number of items shown when totalItemsCount is not provided', () => { - const resourceList = mountWithAppProvider( + const resourceList = mountWithApp( ', () => { />, ); - expect(findByTestID(resourceList, 'headerTitleWrapper').text()).toBe( - 'Showing 2 products', - ); + const headerTitleWrapper = resourceList.find('div', { + className: styles.HeaderTitleWrapper, + }); + expect(headerTitleWrapper).toContainReactText('Showing 2 products'); }); it('prints number of items shown of totalItemsCount when totalItemsCount is provided', () => { - const resourceList = mountWithAppProvider( + const resourceList = mountWithApp( ', () => { />, ); - expect(findByTestID(resourceList, 'headerTitleWrapper').text()).toBe( - 'Showing 2 of 5 products', - ); + const headerTitleWrapper = resourceList.find('div', { + className: styles.HeaderTitleWrapper, + }); + expect(headerTitleWrapper).toContainReactText('Showing 2 of 5 products'); }); it('prints number of items shown of totalItemsCount plural when totalItemsCount is provided and items is one resource', () => { - const resourceList = mountWithAppProvider( + const resourceList = mountWithApp( ', () => { />, ); - expect(findByTestID(resourceList, 'headerTitleWrapper').text()).toBe( - 'Showing 1 of 5 products', - ); + const headerTitleWrapper = resourceList.find('div', { + className: styles.HeaderTitleWrapper, + }); + expect(headerTitleWrapper).toContainReactText('Showing 1 of 5 products'); }); }); describe('bulkActionsAccessibilityLabel', () => { it('provides the BulkActions with the right accessibilityLabel if there’s 1 item and it isn’t selected', () => { - const resourceList = mountWithAppProvider( + const resourceList = mountWithApp( , ); - expect(resourceList.find(BulkActions).prop('accessibilityLabel')).toBe( - 'Select item', - ); + expect(resourceList).toContainReactComponent(BulkActions, { + accessibilityLabel: 'Select item', + }); }); it('provides the BulkActions with the right accessibilityLabel if there’s 1 item and it is selected', () => { - const resourceList = mountWithAppProvider( + const resourceList = mountWithApp( ', () => { selectedItems={['1']} />, ); - expect(resourceList.find(BulkActions).prop('accessibilityLabel')).toBe( - 'Deselect item', - ); + expect(resourceList).toContainReactComponent(BulkActions, { + accessibilityLabel: 'Deselect item', + }); }); it('provides the BulkActions with the right accessibilityLabel if there are multiple items and they are selected', () => { - const resourceList = mountWithAppProvider( + const resourceList = mountWithApp( ', () => { selectedItems={['5', '6', '7']} />, ); - expect(resourceList.find(BulkActions).prop('accessibilityLabel')).toBe( - 'Deselect all 3 items', - ); + expect(resourceList).toContainReactComponent(BulkActions, { + accessibilityLabel: 'Deselect all 3 items', + }); }); + it('provides the BulkActions with the right accessibilityLabel if there’s multiple items and some or none are selected', () => { - const resourceList = mountWithAppProvider( + const resourceList = mountWithApp( , ); - expect(resourceList.find(BulkActions).prop('accessibilityLabel')).toBe( - 'Select all 3 items', - ); + expect(resourceList).toContainReactComponent(BulkActions, { + accessibilityLabel: 'Select all 3 items', + }); }); }); describe('onSelectionChange()', () => { it('calls onSelectionChange() when an item is clicked', () => { const onSelectionChange = jest.fn(); - const resourceList = mountWithAppProvider( + const resourceList = mountWithApp( ', () => { onSelectionChange={onSelectionChange} />, ); - const firstItem = resourceList.find(ResourceItem).first(); - findByTestID(firstItem, 'LargerSelectionArea').simulate('click'); + resourceList.find('div', {className: styles.Handle})!.trigger('onClick', { + stopPropagation: () => {}, + nativeEvent: {}, + }); expect(onSelectionChange).toHaveBeenCalled(); }); }); describe('header markup', () => { it('renders header markup if the list isn’t selectable but the showHeader prop is true', () => { - const resourceList = mountWithAppProvider( + const resourceList = mountWithApp( , ); - expect(findByTestID(resourceList, 'ResourceList-Header').exists()).toBe( - true, - ); + expect(resourceList).toContainReactComponent('div', { + className: styles.HeaderWrapper, + }); }); it('doesn’t render header markup if the list is selectable but the showHeader prop is false', () => { - const resourceList = mountWithAppProvider( + const resourceList = mountWithApp( ', () => { renderItem={renderItem} />, ); - expect(findByTestID(resourceList, 'ResourceList-Header').exists()).toBe( - false, - ); + expect(resourceList).not.toContainReactComponent('div', { + className: styles.HeaderWrapper, + }); + expect(resourceList).not.toContainReactComponent('div', { + className: styles.HeaderContentWrapper, + }); }); it('does not render when items is empty', () => { - const resourceList = mountWithAppProvider( + const resourceList = mountWithApp( , ); - - expect(findByTestID(resourceList, 'ResourceList-Header').exists()).toBe( - false, - ); + expect(resourceList).not.toContainReactComponent('div', { + className: styles.HeaderWrapper, + }); + expect(resourceList).not.toContainReactComponent('div', { + className: styles.HeaderContentWrapper, + }); }); it('renders when sort options are given', () => { - const resourceList = mountWithAppProvider( + const resourceList = mountWithApp( ', () => { renderItem={renderItem} />, ); - expect(findByTestID(resourceList, 'ResourceList-Header').exists()).toBe( - true, - ); + expect(resourceList).toContainReactComponent('div', { + className: classNames( + styles.HeaderWrapper, + styles['HeaderWrapper-hasSort'], + ), + }); }); it('renders when an alternateTool is provided', () => { - const resourceList = mountWithAppProvider( + const resourceList = mountWithApp( , ); - expect(findByTestID(resourceList, 'ResourceList-Header').exists()).toBe( - true, - ); + expect(resourceList).toContainReactComponent('div', { + className: classNames( + styles.HeaderWrapper, + styles['HeaderWrapper-hasAlternateTool'], + ), + }); }); it('renders when bulkActions are given', () => { - const resourceList = mountWithAppProvider( + const resourceList = mountWithApp( , ); - expect(findByTestID(resourceList, 'ResourceList-Header').exists()).toBe( - true, - ); + expect(resourceList).toContainReactComponent('div', { + className: classNames( + styles.HeaderWrapper, + styles['HeaderWrapper-hasSelect'], + ), + }); }); it('renders when promotedBulkActions are given', () => { - const resourceList = mountWithAppProvider( + const resourceList = mountWithApp( , ); - expect(findByTestID(resourceList, 'ResourceList-Header').exists()).toBe( - true, - ); + expect(resourceList).toContainReactComponent('div', { + className: classNames( + styles.HeaderWrapper, + styles['HeaderWrapper-hasSelect'], + ), + }); }); it('does not render when sort options, bulkActions and promotedBulkActions are not given', () => { - const resourceList = mountWithAppProvider( + const resourceList = mountWithApp( , ); - expect(findByTestID(resourceList, 'ResourceList-Header').exists()).toBe( - false, - ); + expect(resourceList).not.toContainReactComponent('div', { + className: styles.HeaderWrapper, + }); + expect(resourceList).not.toContainReactComponent('div', { + className: styles.HeaderContentWrapper, + }); }); it('renders on non-initial load when items are provided', () => { - const resourceList = mountWithAppProvider( + const resourceList = mountWithApp( , ); - - expect(findByTestID(resourceList, 'ResourceList-Header')).toHaveLength(0); + // initially not rendered + expect(resourceList).not.toContainReactComponent('div', { + className: styles.HeaderWrapper, + }); + expect(resourceList).not.toContainReactComponent('div', { + className: styles.HeaderContentWrapper, + }); + // update props resourceList.setProps({items: itemsWithID}); - resourceList.update(); - expect(findByTestID(resourceList, 'ResourceList-Header')).toHaveLength(1); + // now it's rendered + expect(resourceList).toContainReactComponent('div', { + className: classNames( + styles.HeaderWrapper, + styles['HeaderWrapper-hasSelect'], + ), + }); }); it('does not render when EmptySearchResult exists', () => { - const resourceList = mountWithAppProvider( + const resourceList = mountWithApp( fake filterControl
} />, ); - - expect(resourceList.find(EmptySearchResult).exists()).toBe(true); - expect(findByTestID(resourceList, 'ResourceList-Header')).toHaveLength(0); + expect(resourceList).toContainReactComponent(EmptySearchResult); + expect(resourceList).not.toContainReactComponent('div', { + className: styles.HeaderWrapper, + }); + expect(resourceList).not.toContainReactComponent('div', { + className: styles.HeaderContentWrapper, + }); }); }); describe('filterControl', () => { it('renders when exists', () => { - const resourceList = mountWithAppProvider( + const resourceList = mountWithApp( Test
} />, ); - expect(resourceList.find('#test123').exists()).toBe(true); + expect(resourceList).toContainReactComponent('div', {id: 'test123'}); }); }); @@ -497,7 +542,7 @@ describe('', () => { ); - const resourceList = mountWithAppProvider( + const resourceList = mountWithApp( ', () => { />, ); - expect(resourceList.find(EmptyState)).toHaveLength(1); + expect(resourceList).toContainReactComponentTimes(EmptyState, 1); }); it('does not render when exists but items are provided', () => { @@ -522,7 +567,7 @@ describe('', () => { ); - const resourceList = mountWithAppProvider( + const resourceList = mountWithApp( ', () => { />, ); - expect(resourceList.find(EmptyState)).toHaveLength(0); + expect(resourceList).not.toContainReactComponent(EmptyState); }); it('does not render when exists, items is empty, but loading is true', () => { @@ -547,7 +592,7 @@ describe('', () => { ); - const resourceList = mountWithAppProvider( + const resourceList = mountWithApp( ', () => { />, ); - expect(resourceList.find(EmptyState)).toHaveLength(0); + expect(resourceList).not.toContainReactComponent(EmptyState); }); }); describe('', () => { it('renders when filterControl exists and items is empty', () => { - const resourceList = mountWithAppProvider( + const resourceList = mountWithApp( fake filterControl
} />, ); - expect(resourceList.find(EmptySearchResult).exists()).toBe(true); + expect(resourceList).toContainReactComponent(EmptySearchResult); }); it('does not render when filterControl does not exist', () => { - const resourceList = mountWithAppProvider( + const resourceList = mountWithApp( , ); - expect(resourceList.find(EmptySearchResult).exists()).toBe(false); + expect(resourceList).not.toContainReactComponent(EmptySearchResult); }); it('does not render when items is not empty', () => { - const resourceList = mountWithAppProvider( + const resourceList = mountWithApp( Test
} />, ); - expect(resourceList.find(EmptySearchResult).exists()).toBe(false); + expect(resourceList).not.toContainReactComponent(EmptySearchResult); }); it('does not render when filterControl exists, items is empty, and loading is true', () => { - const resourceList = mountWithAppProvider( + const resourceList = mountWithApp( ', () => { loading />, ); - expect(resourceList.find(EmptySearchResult).exists()).toBe(false); + expect(resourceList).not.toContainReactComponent(EmptySearchResult); }); it('does not render when filterControl exists, items is empty, and emptyState is set', () => { @@ -616,7 +661,7 @@ describe('', () => { ); - const resourceList = mountWithAppProvider( + const resourceList = mountWithApp( ', () => { />, ); - expect(resourceList.find(EmptySearchResult).exists()).toBe(false); + expect(resourceList).not.toContainReactComponent(EmptySearchResult); }); it('renders the provided markup when emptySearchState is set', () => { - const resourceList = mountWithAppProvider( + const resourceList = mountWithApp( ', () => { />, ); - expect(resourceList.find(EmptySearchResult).exists()).toBe(false); - expect(resourceList.find('div#emptySearchState').exists()).toBe(true); + expect(resourceList).not.toContainReactComponent(EmptySearchResult); + expect(resourceList).toContainReactComponent('div', { + id: 'emptySearchState', + }); }); }); describe('Sorting', () => { it('does not render a sort select if sortOptions aren’t provided', () => { - const resourceList = mountWithAppProvider( + const resourceList = mountWithApp( , ); - expect(resourceList.find(Select).exists()).toBe(false); + expect(resourceList).not.toContainReactComponent(Select); }); it('renders a sort select if sortOptions are provided', () => { - const resourceList = mountWithAppProvider( + const resourceList = mountWithApp( ', () => { renderItem={renderItem} />, ); - expect(resourceList.find(Select).exists()).toBe(true); + expect(resourceList).toContainReactComponent(Select); }); it('does not render a sort select if an alternateTool is provided', () => { - const resourceList = mountWithAppProvider( + const resourceList = mountWithApp( ', () => { alternateTool={alternateTool} />, ); - expect(resourceList.find(Select).exists()).toBe(false); + expect(resourceList).not.toContainReactComponent(Select); }); describe('sortOptions', () => { it('passes a sortOptions to the Select options', () => { - const resourceList = mountWithAppProvider( + const resourceList = mountWithApp( ', () => { renderItem={renderItem} />, ); - expect(resourceList.find(Select).props()).toHaveProperty( - 'options', - sortOptions, - ); + expect(resourceList).toContainReactComponent(Select, { + options: sortOptions, + }); }); }); describe('sortValue', () => { it('passes a sortValue to the Select value', () => { const onSortChange = jest.fn(); - const resourceList = mountWithAppProvider( + const resourceList = mountWithApp( ', () => { renderItem={renderItem} />, ); - expect(resourceList.find(Select).props()).toHaveProperty( - 'value', - 'sortValue', - ); + expect(resourceList).toContainReactComponent(Select, { + value: 'sortValue', + }); }); }); describe('onSortChange', () => { it('calls onSortChange when the Sort Select changes', () => { const onSortChange = jest.fn(); - const resourceList = mountWithAppProvider( + const resourceList = mountWithApp( ', () => { renderItem={renderItem} />, ); - trigger(resourceList.find(Select), 'onChange', 'PRODUCT_TITLE_DESC'); + resourceList.find(Select)!.trigger('onChange', 'PRODUCT_TITLE_DESC'); expect(onSortChange).toHaveBeenCalledWith('PRODUCT_TITLE_DESC'); }); }); @@ -733,25 +778,29 @@ describe('', () => { describe('Alternate Tool', () => { it('does not render if an alternateTool is not provided', () => { - const resourceList = mountWithAppProvider( + const resourceList = mountWithApp( , ); - expect(resourceList.find('#AlternateTool').exists()).toBe(false); + expect(resourceList).not.toContainReactComponent('div', { + id: 'AlternateTool', + }); }); it('renders if an alternateTool is provided', () => { - const resourceList = mountWithAppProvider( + const resourceList = mountWithApp( , ); - expect(resourceList.find('#AlternateTool').exists()).toBe(true); + expect(resourceList).toContainReactComponent('div', { + id: 'AlternateTool', + }); }); it('renders even if sortOptions are provided', () => { - const resourceList = mountWithAppProvider( + const resourceList = mountWithApp( ', () => { alternateTool={alternateTool} />, ); - expect(resourceList.find('#AlternateTool').exists()).toBe(true); + expect(resourceList).toContainReactComponent('div', { + id: 'AlternateTool', + }); }); describe('sortOptions', () => { it('passes a sortOptions to the Select options', () => { - const resourceList = mountWithAppProvider( + const resourceList = mountWithApp( ', () => { onSortChange={noop} />, ); - expect(resourceList.find(Select).props()).toHaveProperty( - 'options', - sortOptions, - ); + expect(resourceList).toContainReactComponent(Select, { + options: sortOptions, + }); }); }); describe('sortValue', () => { it('passes a sortValue to the Select value', () => { const onSortChange = jest.fn(); - const resourceList = mountWithAppProvider( + const resourceList = mountWithApp( ', () => { renderItem={renderItem} />, ); - expect(resourceList.find(Select).props()).toHaveProperty( - 'value', - 'sortValue', - ); + expect(resourceList).toContainReactComponent(Select, { + value: 'sortValue', + }); }); }); describe('onSortChange', () => { it('calls onSortChange when the Sort Select changes', () => { const onSortChange = jest.fn(); - const resourceList = mountWithAppProvider( + const resourceList = mountWithApp( ', () => { renderItem={renderItem} />, ); - trigger(resourceList.find(Select), 'onChange', 'PRODUCT_TITLE_DESC'); + resourceList.find(Select)!.trigger('onChange', 'PRODUCT_TITLE_DESC'); expect(onSortChange).toHaveBeenCalledWith('PRODUCT_TITLE_DESC'); }); }); @@ -817,7 +866,7 @@ describe('', () => { describe('loading', () => { it('renders a spinner', () => { - const resourceList = mountWithAppProvider( + const resourceList = mountWithApp( ', () => { />, ); - expect(resourceList.find(Spinner).exists()).toBe(true); + expect(resourceList).toContainReactComponent(Spinner); }); it('renders a spinner after initial load when loading is true', () => { - const resourceList = mountWithAppProvider( + const resourceList = mountWithApp( ', () => { ); resourceList.setProps({loading: true}); - expect(resourceList.find(Spinner).exists()).toBe(true); + expect(resourceList).toContainReactComponent(Spinner); }); it('does not render an if loading is true and there are no items', () => { - const resourceList = mountWithAppProvider( + const resourceList = mountWithApp( ', () => { />, ); - expect(resourceList.find(ResourceItem)).toHaveLength(0); + expect(resourceList).not.toContainReactComponent(ResourceItem); }); }); describe('BulkActions', () => { it('renders on initial load when items are selected', () => { - const resourceList = mountWithAppProvider( + const resourceList = mountWithApp( ', () => { selectedItems={['1']} />, ); - expect(resourceList.find(BulkActions)).toHaveLength(1); + expect(resourceList).toContainReactComponentTimes(BulkActions, 1); }); it('enables select mode when items are programmatically selected', () => { - const resourceList = mountWithAppProvider( + const resourceList = mountWithApp( ', () => { />, ); - expect(resourceList.find(BulkActions).prop('selectMode')).toBe(false); + expect(resourceList).toContainReactComponent(BulkActions, { + selectMode: false, + }); resourceList.setProps({selectedItems: ['1']}); - resourceList.update(); - expect(resourceList.find(BulkActions).prop('selectMode')).toBe(true); + expect(resourceList).toContainReactComponent(BulkActions, { + selectMode: true, + }); }); it('disables select mode when items are deselected programmatically selected', () => { - const resourceList = mountWithAppProvider( + const resourceList = mountWithApp( ', () => { />, ); - expect(resourceList.find(BulkActions).prop('selectMode')).toBe(true); + expect(resourceList).toContainReactComponent(BulkActions, { + selectMode: true, + }); resourceList.setProps({selectedItems: []}); - resourceList.update(); - expect(resourceList.find(BulkActions).prop('selectMode')).toBe(false); + expect(resourceList).toContainReactComponent(BulkActions, { + selectMode: false, + }); }); describe('focus', () => { @@ -1029,7 +1084,7 @@ describe('', () => { return item.id; } const onSelectionChange = jest.fn(); - const resourceList = mountWithAppProvider( + const resourceList = mountWithApp( ', () => { resolveItemId={resolveItemId} />, ); - const firstItem = resourceList.find(ResourceItem).first(); - findByTestID(firstItem, 'LargerSelectionArea').simulate('click'); - - const lastItem = resourceList.find(ResourceItem).last(); - findByTestID(lastItem, 'LargerSelectionArea').simulate('click', { + const firstItem = resourceList.find(ResourceItem); + firstItem!.find('div', {className: styles.Handle})!.trigger('onClick', { + stopPropagation: () => {}, + nativeEvent: {}, + }); + const allItems = resourceList.findAll(ResourceItem); + const lastItem = allItems[allItems.length - 1]; + lastItem!.find('div', {className: styles.Handle})!.trigger('onClick', { + stopPropagation: () => {}, nativeEvent: {shiftKey: true}, }); - expect(onSelectionChange).toHaveBeenCalledWith(['5', '6', '7']); }); it('does not select shift selected items if resolveItemId was not provided', () => { const onSelectionChange = jest.fn(); - const resourceList = mountWithAppProvider( + const resourceList = mountWithApp( ', () => { onSelectionChange={onSelectionChange} />, ); - const firstItem = resourceList.find(ResourceItem).first(); - findByTestID(firstItem, 'LargerSelectionArea').simulate('click'); - - const lastItem = resourceList.find(ResourceItem).last(); - findByTestID(lastItem, 'LargerSelectionArea').simulate('click', { + const firstItem = resourceList.find(ResourceItem); + firstItem!.find('div', {className: styles.Handle})!.trigger('onClick', { + stopPropagation: () => {}, + nativeEvent: {}, + }); + const allItems = resourceList.findAll(ResourceItem); + const lastItem = allItems[allItems.length - 1]; + lastItem!.find('div', {className: styles.Handle})!.trigger('onClick', { + stopPropagation: () => {}, nativeEvent: {shiftKey: true}, }); @@ -1091,7 +1153,7 @@ describe('', () => { } const onSelectionChange = jest.fn(); - const resourceList = mountWithAppProvider( + const resourceList = mountWithApp( ', () => { resolveItemId={resolveItemId} />, ); - const firstItem = resourceList.find(ResourceItem).first(); - findByTestID(firstItem, 'LargerSelectionArea').simulate('click'); - - const lastItem = resourceList.find(ResourceItem).last(); - findByTestID(lastItem, 'LargerSelectionArea').simulate('click', { + const firstItem = resourceList.find(ResourceItem); + firstItem!.find('div', {className: styles.Handle})!.trigger('onClick', { + stopPropagation: () => {}, + nativeEvent: {}, + }); + const allItems = resourceList.findAll(ResourceItem); + const lastItem = allItems[allItems.length - 1]; + lastItem!.find('div', {className: styles.Handle})!.trigger('onClick', { + stopPropagation: () => {}, nativeEvent: {shiftKey: true}, }); @@ -1118,7 +1184,7 @@ describe('', () => { return item.id; } const onSelectionChange = jest.fn(); - const resourceList = mountWithAppProvider( + const resourceList = mountWithApp( ', () => { resolveItemId={resolveItemId} />, ); - // Sets {lastSeleced: 0} - const firstItem = resourceList.find(ResourceItem).first(); - findByTestID(firstItem, 'LargerSelectionArea').simulate('click'); - - const lastItem = resourceList.find(ResourceItem).last(); - findByTestID(lastItem, 'LargerSelectionArea').simulate('click', { + // Sets {lastSelected: 0} + const firstItem = resourceList.find(ResourceItem); + firstItem!.find('div', {className: styles.Handle})!.trigger('onClick', { + stopPropagation: () => {}, + nativeEvent: {}, + }); + const allItems = resourceList.findAll(ResourceItem); + const lastItem = allItems[allItems.length - 1]; + lastItem!.find('div', {className: styles.Handle})!.trigger('onClick', { + stopPropagation: () => {}, nativeEvent: {shiftKey: true}, }); @@ -1147,7 +1217,7 @@ describe('', () => { }); it('an inline label is hidden on small screen', () => { - const resourceList = mountWithAppProvider( + const resourceList = mountWithApp( ', () => { ); setSmallScreen(); - trigger(resourceList.find(EventListener), 'handler'); - - expect(resourceList.find(Select).first().prop('labelInline')).toBe(false); + resourceList.find(EventListener)!.trigger('handler'); + expect(resourceList).toContainReactComponent(Select, { + labelInline: false, + }); }); it('select mode is turned off on large screen when no items are selected', () => { - const resourceList = mountWithAppProvider( + const resourceList = mountWithApp( ', () => { />, ); - trigger(resourceList.find(BulkActions), 'onSelectModeToggle', true); - trigger(resourceList.find(EventListener).first(), 'handler'); - expect(resourceList.find(BulkActions).prop('selectMode')).toBe(false); + resourceList.find(BulkActions)!.trigger('onSelectModeToggle', true); + resourceList.find(EventListener)!.trigger('handler'); + expect(resourceList).toContainReactComponent(BulkActions, { + selectMode: false, + }); }); }); describe('isFiltered', () => { it('renders `selectAllFilteredItems` label if true', () => { - const resourceList = mountWithAppProvider( + const resourceList = mountWithApp( ', () => { />, ); - expect( - resourceList.find(BulkActions).prop('paginatedSelectAllAction'), - ).toStrictEqual({ - content: 'Select all 2+ customers in this filter', - onAction: expect.any(Function), + expect(resourceList).toContainReactComponent(BulkActions, { + paginatedSelectAllAction: { + content: 'Select all 2+ customers in this filter', + onAction: expect.any(Function), + }, }); }); @@ -1215,13 +1288,13 @@ describe('', () => { resourceList.find(BulkActions)!.find(Button)!.trigger('onClick'); - expect( - resourceList.find(BulkActions)!.prop('paginatedSelectAllText'), - ).toBe('All 2+ customers in this filter are selected.'); + expect(resourceList).toContainReactComponent(BulkActions, { + paginatedSelectAllText: 'All 2+ customers in this filter are selected.', + }); }); it('renders `selectAllItems` label if not passed', () => { - const resourceList = mountWithAppProvider( + const resourceList = mountWithApp( ', () => { />, ); - expect( - resourceList.find(BulkActions).prop('paginatedSelectAllAction'), - ).toStrictEqual({ - content: 'Select all 2+ customers in your store', - onAction: expect.any(Function), + expect(resourceList).toContainReactComponent(BulkActions, { + paginatedSelectAllAction: { + content: 'Select all 2+ customers in your store', + onAction: expect.any(Function), + }, }); }); @@ -1254,9 +1327,9 @@ describe('', () => { resourceList.find(BulkActions)!.find(Button)!.trigger('onClick'); - expect( - resourceList.find(BulkActions)!.prop('paginatedSelectAllText'), - ).toBe('All 2+ customers in your store are selected.'); + expect(resourceList).toContainReactComponent(BulkActions, { + paginatedSelectAllText: 'All 2+ customers in your store are selected.', + }); }); }); }); From 80869c74a686de7167aab1ca89640fab9771778e Mon Sep 17 00:00:00 2001 From: Luca Bezerra Date: Mon, 9 Aug 2021 14:00:51 -0400 Subject: [PATCH 06/16] Fixing lint errors. --- src/components/ResourceList/tests/ResourceList.test.tsx | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/components/ResourceList/tests/ResourceList.test.tsx b/src/components/ResourceList/tests/ResourceList.test.tsx index 8edf82934ce..9d379502bef 100644 --- a/src/components/ResourceList/tests/ResourceList.test.tsx +++ b/src/components/ResourceList/tests/ResourceList.test.tsx @@ -14,9 +14,7 @@ import {SELECT_ALL_ITEMS} from 'utilities/resource-list'; import {BulkActions} from '../../BulkActions'; import {CheckableButton} from '../../CheckableButton'; - import {classNames} from '../../../utilities/css'; - import styles from '../ResourceList.scss'; const itemsNoID = [{url: 'item 1'}, {url: 'item 2'}]; @@ -143,10 +141,9 @@ describe('', () => { bulkActions={bulkActions} />, ); - expect(resourceList).toContainReactComponent(BulkActions); expect( resourceList.find(BulkActions)!.props.paginatedSelectAllAction, - ).not.toBe(undefined); + ).not.toBeUndefined(); }); }); From e9f26bc4615da737f9bf4a49c7b74a17ff058b95 Mon Sep 17 00:00:00 2001 From: Luca Bezerra Date: Tue, 10 Aug 2021 17:36:47 -0400 Subject: [PATCH 07/16] PR suggestions. --- .../ResourceItem/tests/ResourceItem.test.tsx | 110 +++++++----------- .../ResourceList/tests/ResourceList.test.tsx | 51 ++------ 2 files changed, 50 insertions(+), 111 deletions(-) diff --git a/src/components/ResourceItem/tests/ResourceItem.test.tsx b/src/components/ResourceItem/tests/ResourceItem.test.tsx index 5292af4745d..03979d02da3 100644 --- a/src/components/ResourceItem/tests/ResourceItem.test.tsx +++ b/src/components/ResourceItem/tests/ResourceItem.test.tsx @@ -10,7 +10,6 @@ import { } from 'components'; import {ResourceItem} from '../ResourceItem'; -import {classNames} from '../../../utilities/css'; import {ResourceListContext} from '../../../utilities/resource-list'; import styles from '../ResourceItem.scss'; @@ -71,6 +70,10 @@ describe('', () => { const external = false; const ariaLabel = 'View Item'; + const resourceItemSelector = {className: styles.ResourceItem}; + const resourceItemFilter = (node: any) => + node.prop('className').includes(styles.ResourceItem); + describe('accessibilityLabel', () => { it('is used on the for the aria-label attribute', () => { const item = mountWithApp( @@ -214,8 +217,7 @@ describe('', () => { , ); - const div = element.find('div', {'data-href': url} as any); - expect(div).not.toBeNull(); + expect(element).toContainReactComponent('div', {'data-href': url} as any); }); }); @@ -299,12 +301,10 @@ describe('', () => { , ); - wrapper - .find('div', {className: styles.ResourceItem})! - .trigger('onClick', { - stopPropagation: () => {}, - nativeEvent: {}, - }); + wrapper.find('div', resourceItemSelector)!.trigger('onClick', { + stopPropagation: () => {}, + nativeEvent: {}, + }); expect(onClick).toHaveBeenCalledWith(itemId); }); @@ -321,12 +321,10 @@ describe('', () => { , ); - wrapper - .find('div', {className: styles.ResourceItem})! - .trigger('onClick', { - stopPropagation: () => {}, - nativeEvent: {}, - }); + wrapper.find('div', resourceItemSelector)!.trigger('onClick', { + stopPropagation: () => {}, + nativeEvent: {}, + }); expect(onClick).toHaveBeenCalledWith(itemId); }); @@ -337,12 +335,10 @@ describe('', () => { , ); - wrapper - .find('div', {className: styles.ResourceItem})! - .trigger('onClick', { - stopPropagation: () => {}, - nativeEvent: {metaKey: true}, - }); + wrapper.find('div', resourceItemSelector)!.trigger('onClick', { + stopPropagation: () => {}, + nativeEvent: {metaKey: true}, + }); expect(spy).toHaveBeenCalledWith(url, '_blank'); }); @@ -355,7 +351,7 @@ describe('', () => { ); wrapper - .find('div', {className: styles.ResourceItem})! + .find('div', resourceItemSelector)! .trigger('onKeyUp', {key: 'Enter'}); expect(onClick).toHaveBeenCalled(); @@ -370,7 +366,7 @@ describe('', () => { ); wrapper - .find('div', {className: styles.ResourceItem})! + .find('div', resourceItemSelector)! .trigger('onKeyUp', {key: 'Tab'}); expect(onClick).not.toHaveBeenCalled(); @@ -385,13 +381,8 @@ describe('', () => { ); wrapper - .find('div', { - className: classNames( - styles.ResourceItem, - styles.selectable, - styles.selectMode, - ), - })! + .find('div') + .findWhere(resourceItemFilter)! .trigger('onKeyUp', {key: 'Enter'}); expect(onClick).not.toHaveBeenCalled(); @@ -404,12 +395,10 @@ describe('', () => { , ); - wrapper - .find('div', {className: styles.ResourceItem})! - .trigger('onClick', { - stopPropagation: () => {}, - nativeEvent: {ctrlKey: true}, - }); + wrapper.find('div', resourceItemSelector)!.trigger('onClick', { + stopPropagation: () => {}, + nativeEvent: {ctrlKey: true}, + }); expect(spy).toHaveBeenCalledWith(url, '_blank'); }); }); @@ -465,13 +454,8 @@ describe('', () => { ); wrapper - .find('div', { - className: classNames( - styles.ResourceItem, - styles.selectable, - styles.selectMode, - ), - })! + .find('div') + .findWhere(resourceItemFilter)! .trigger('onClick', { stopPropagation: () => {}, nativeEvent: {}, @@ -495,13 +479,8 @@ describe('', () => { ); wrapper - .find('div', { - className: classNames( - styles.ResourceItem, - styles.selectable, - styles.selectMode, - ), - })! + .find('div') + .findWhere(resourceItemFilter)! .trigger('onClick', { stopPropagation: () => {}, nativeEvent: {shiftKey: false}, @@ -531,14 +510,8 @@ describe('', () => { ); wrapper - .find('div', { - className: classNames( - styles.ResourceItem, - styles.selectable, - styles.selected, - styles.selectMode, - ), - })! + .find('div') + .findWhere(resourceItemFilter)! .trigger('onClick', { stopPropagation: () => {}, nativeEvent: {metaKey: true}, @@ -554,14 +527,8 @@ describe('', () => { ); wrapper - .find('div', { - className: classNames( - styles.ResourceItem, - styles.selectable, - styles.selected, - styles.selectMode, - ), - })! + .find('div') + .findWhere(resourceItemFilter)! .trigger('onClick', { stopPropagation: () => {}, nativeEvent: {ctrlKey: true}, @@ -799,8 +766,10 @@ describe('', () => { /> , ); - const li = item.find('li', {'data-href': 'google.com'} as any); - expect(li).not.toBeNull(); + + expect(item).toContainReactComponent('li', { + 'data-href': 'google.com', + } as any); }); it('renders a data-href tag on the li when the dataHref prop is not specified', () => { @@ -814,8 +783,9 @@ describe('', () => { , ); - const li = item.find('li', {'data-href': undefined} as any); - expect(li).not.toBeNull(); + expect(item).toContainReactComponent('li', { + 'data-href': undefined, + } as any); }); }); }); diff --git a/src/components/ResourceList/tests/ResourceList.test.tsx b/src/components/ResourceList/tests/ResourceList.test.tsx index 9d379502bef..a3047b0828c 100644 --- a/src/components/ResourceList/tests/ResourceList.test.tsx +++ b/src/components/ResourceList/tests/ResourceList.test.tsx @@ -14,7 +14,6 @@ import {SELECT_ALL_ITEMS} from 'utilities/resource-list'; import {BulkActions} from '../../BulkActions'; import {CheckableButton} from '../../CheckableButton'; -import {classNames} from '../../../utilities/css'; import styles from '../ResourceList.scss'; const itemsNoID = [{url: 'item 1'}, {url: 'item 2'}]; @@ -371,10 +370,7 @@ describe('', () => { />, ); expect(resourceList).not.toContainReactComponent('div', { - className: styles.HeaderWrapper, - }); - expect(resourceList).not.toContainReactComponent('div', { - className: styles.HeaderContentWrapper, + className: expect.stringContaining(styles.HeaderWrapper), }); }); @@ -383,10 +379,7 @@ describe('', () => { , ); expect(resourceList).not.toContainReactComponent('div', { - className: styles.HeaderWrapper, - }); - expect(resourceList).not.toContainReactComponent('div', { - className: styles.HeaderContentWrapper, + className: expect.stringContaining(styles.HeaderWrapper), }); }); @@ -400,10 +393,7 @@ describe('', () => { />, ); expect(resourceList).toContainReactComponent('div', { - className: classNames( - styles.HeaderWrapper, - styles['HeaderWrapper-hasSort'], - ), + className: expect.stringContaining(styles.HeaderWrapper), }); }); @@ -416,10 +406,7 @@ describe('', () => { />, ); expect(resourceList).toContainReactComponent('div', { - className: classNames( - styles.HeaderWrapper, - styles['HeaderWrapper-hasAlternateTool'], - ), + className: expect.stringContaining(styles.HeaderWrapper), }); }); @@ -432,10 +419,7 @@ describe('', () => { />, ); expect(resourceList).toContainReactComponent('div', { - className: classNames( - styles.HeaderWrapper, - styles['HeaderWrapper-hasSelect'], - ), + className: expect.stringContaining(styles.HeaderWrapper), }); }); @@ -448,10 +432,7 @@ describe('', () => { />, ); expect(resourceList).toContainReactComponent('div', { - className: classNames( - styles.HeaderWrapper, - styles['HeaderWrapper-hasSelect'], - ), + className: expect.stringContaining(styles.HeaderWrapper), }); }); @@ -460,10 +441,7 @@ describe('', () => { , ); expect(resourceList).not.toContainReactComponent('div', { - className: styles.HeaderWrapper, - }); - expect(resourceList).not.toContainReactComponent('div', { - className: styles.HeaderContentWrapper, + className: expect.stringContaining(styles.HeaderWrapper), }); }); @@ -477,19 +455,13 @@ describe('', () => { ); // initially not rendered expect(resourceList).not.toContainReactComponent('div', { - className: styles.HeaderWrapper, - }); - expect(resourceList).not.toContainReactComponent('div', { - className: styles.HeaderContentWrapper, + className: expect.stringContaining(styles.HeaderWrapper), }); // update props resourceList.setProps({items: itemsWithID}); // now it's rendered expect(resourceList).toContainReactComponent('div', { - className: classNames( - styles.HeaderWrapper, - styles['HeaderWrapper-hasSelect'], - ), + className: expect.stringContaining(styles.HeaderWrapper), }); }); @@ -503,10 +475,7 @@ describe('', () => { ); expect(resourceList).toContainReactComponent(EmptySearchResult); expect(resourceList).not.toContainReactComponent('div', { - className: styles.HeaderWrapper, - }); - expect(resourceList).not.toContainReactComponent('div', { - className: styles.HeaderContentWrapper, + className: expect.stringContaining(styles.HeaderWrapper), }); }); }); From ba6d0971cb427c26e76a179a4a39ef04aa724356 Mon Sep 17 00:00:00 2001 From: Luca Bezerra Date: Tue, 10 Aug 2021 13:38:50 -0400 Subject: [PATCH 08/16] Update UNRELEASED.md Co-authored-by: Kyle Durand --- UNRELEASED.md | 1 + 1 file changed, 1 insertion(+) diff --git a/UNRELEASED.md b/UNRELEASED.md index 993b1e2495b..214ccc0e6ce 100644 --- a/UNRELEASED.md +++ b/UNRELEASED.md @@ -60,5 +60,6 @@ Use [the changelog guidelines](https://git.io/polaris-changelog-guidelines) to f - Modernized tests for Message, Menu, Search, SearchDismissOverlay, SearchField, UserMenu and TopBar components. ([#4311](https://github.com/Shopify/polaris-react/pull/4311)) - Modernized tests for ResourceItem ([#4362](https://github.com/Shopify/polaris-react/pull/4362)) - Modernized tests for ResourceItem, ResourceList ([#4362](https://github.com/Shopify/polaris-react/pull/4362)) +- Modernized tests for `ResourceItem`, `ResourceList` ([#4362](https://github.com/Shopify/polaris-react/pull/4362)) ### Deprecations From 4d701f10b50fb8ff0c4e771489ac802064d5f209 Mon Sep 17 00:00:00 2001 From: Luca Bezerra Date: Wed, 11 Aug 2021 10:31:28 -0400 Subject: [PATCH 09/16] Removing constant from tests and exporting Node from react-testing. --- .../ResourceItem/tests/ResourceItem.test.tsx | 56 +++++++++++-------- 1 file changed, 34 insertions(+), 22 deletions(-) diff --git a/src/components/ResourceItem/tests/ResourceItem.test.tsx b/src/components/ResourceItem/tests/ResourceItem.test.tsx index 03979d02da3..5d35f2b410f 100644 --- a/src/components/ResourceItem/tests/ResourceItem.test.tsx +++ b/src/components/ResourceItem/tests/ResourceItem.test.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import {mountWithApp} from 'test-utilities'; +import {mountWithApp, Node} from 'test-utilities'; import { Avatar, ButtonGroup, @@ -70,8 +70,7 @@ describe('', () => { const external = false; const ariaLabel = 'View Item'; - const resourceItemSelector = {className: styles.ResourceItem}; - const resourceItemFilter = (node: any) => + const resourceItemFilter = (node: Node) => node.prop('className').includes(styles.ResourceItem); describe('accessibilityLabel', () => { @@ -301,10 +300,13 @@ describe('', () => { , ); - wrapper.find('div', resourceItemSelector)!.trigger('onClick', { - stopPropagation: () => {}, - nativeEvent: {}, - }); + wrapper + .find('div')! + .findWhere(resourceItemFilter)! + .trigger('onClick', { + stopPropagation: () => {}, + nativeEvent: {}, + }); expect(onClick).toHaveBeenCalledWith(itemId); }); @@ -321,10 +323,13 @@ describe('', () => { , ); - wrapper.find('div', resourceItemSelector)!.trigger('onClick', { - stopPropagation: () => {}, - nativeEvent: {}, - }); + wrapper + .find('div')! + .findWhere(resourceItemFilter)! + .trigger('onClick', { + stopPropagation: () => {}, + nativeEvent: {}, + }); expect(onClick).toHaveBeenCalledWith(itemId); }); @@ -335,10 +340,13 @@ describe('', () => { , ); - wrapper.find('div', resourceItemSelector)!.trigger('onClick', { - stopPropagation: () => {}, - nativeEvent: {metaKey: true}, - }); + wrapper + .find('div')! + .findWhere(resourceItemFilter)! + .trigger('onClick', { + stopPropagation: () => {}, + nativeEvent: {metaKey: true}, + }); expect(spy).toHaveBeenCalledWith(url, '_blank'); }); @@ -351,7 +359,8 @@ describe('', () => { ); wrapper - .find('div', resourceItemSelector)! + .find('div')! + .findWhere(resourceItemFilter)! .trigger('onKeyUp', {key: 'Enter'}); expect(onClick).toHaveBeenCalled(); @@ -366,7 +375,8 @@ describe('', () => { ); wrapper - .find('div', resourceItemSelector)! + .find('div')! + .findWhere(resourceItemFilter)! .trigger('onKeyUp', {key: 'Tab'}); expect(onClick).not.toHaveBeenCalled(); @@ -384,7 +394,6 @@ describe('', () => { .find('div') .findWhere(resourceItemFilter)! .trigger('onKeyUp', {key: 'Enter'}); - expect(onClick).not.toHaveBeenCalled(); }); @@ -395,10 +404,13 @@ describe('', () => { , ); - wrapper.find('div', resourceItemSelector)!.trigger('onClick', { - stopPropagation: () => {}, - nativeEvent: {ctrlKey: true}, - }); + wrapper + .find('div')! + .findWhere(resourceItemFilter)! + .trigger('onClick', { + stopPropagation: () => {}, + nativeEvent: {ctrlKey: true}, + }); expect(spy).toHaveBeenCalledWith(url, '_blank'); }); }); From 439563bbb26d63ba73a4ad48d6be779867c67c52 Mon Sep 17 00:00:00 2001 From: Luca Bezerra Date: Wed, 11 Aug 2021 11:23:54 -0400 Subject: [PATCH 10/16] Better way of classList filtering and Node type exporting. --- .../ResourceItem/tests/ResourceItem.test.tsx | 105 ++++++------------ 1 file changed, 36 insertions(+), 69 deletions(-) diff --git a/src/components/ResourceItem/tests/ResourceItem.test.tsx b/src/components/ResourceItem/tests/ResourceItem.test.tsx index 5d35f2b410f..9fdccf5dca9 100644 --- a/src/components/ResourceItem/tests/ResourceItem.test.tsx +++ b/src/components/ResourceItem/tests/ResourceItem.test.tsx @@ -71,7 +71,7 @@ describe('', () => { const ariaLabel = 'View Item'; const resourceItemFilter = (node: Node) => - node.prop('className').includes(styles.ResourceItem); + node.is('div') && node!.domNode.classList.contains(styles.ResourceItem); describe('accessibilityLabel', () => { it('is used on the for the aria-label attribute', () => { @@ -300,13 +300,10 @@ describe('', () => { , ); - wrapper - .find('div')! - .findWhere(resourceItemFilter)! - .trigger('onClick', { - stopPropagation: () => {}, - nativeEvent: {}, - }); + wrapper.findWhere(resourceItemFilter)!.trigger('onClick', { + stopPropagation: () => {}, + nativeEvent: {}, + }); expect(onClick).toHaveBeenCalledWith(itemId); }); @@ -323,13 +320,10 @@ describe('', () => { , ); - wrapper - .find('div')! - .findWhere(resourceItemFilter)! - .trigger('onClick', { - stopPropagation: () => {}, - nativeEvent: {}, - }); + wrapper.findWhere(resourceItemFilter)!.trigger('onClick', { + stopPropagation: () => {}, + nativeEvent: {}, + }); expect(onClick).toHaveBeenCalledWith(itemId); }); @@ -340,13 +334,10 @@ describe('', () => { , ); - wrapper - .find('div')! - .findWhere(resourceItemFilter)! - .trigger('onClick', { - stopPropagation: () => {}, - nativeEvent: {metaKey: true}, - }); + wrapper.findWhere(resourceItemFilter)!.trigger('onClick', { + stopPropagation: () => {}, + nativeEvent: {metaKey: true}, + }); expect(spy).toHaveBeenCalledWith(url, '_blank'); }); @@ -358,10 +349,7 @@ describe('', () => { , ); - wrapper - .find('div')! - .findWhere(resourceItemFilter)! - .trigger('onKeyUp', {key: 'Enter'}); + wrapper.findWhere(resourceItemFilter)!.trigger('onKeyUp', {key: 'Enter'}); expect(onClick).toHaveBeenCalled(); }); @@ -374,10 +362,7 @@ describe('', () => { , ); - wrapper - .find('div')! - .findWhere(resourceItemFilter)! - .trigger('onKeyUp', {key: 'Tab'}); + wrapper.findWhere(resourceItemFilter)!.trigger('onKeyUp', {key: 'Tab'}); expect(onClick).not.toHaveBeenCalled(); }); @@ -390,10 +375,7 @@ describe('', () => { , ); - wrapper - .find('div') - .findWhere(resourceItemFilter)! - .trigger('onKeyUp', {key: 'Enter'}); + wrapper.findWhere(resourceItemFilter)!.trigger('onKeyUp', {key: 'Enter'}); expect(onClick).not.toHaveBeenCalled(); }); @@ -404,13 +386,10 @@ describe('', () => { , ); - wrapper - .find('div')! - .findWhere(resourceItemFilter)! - .trigger('onClick', { - stopPropagation: () => {}, - nativeEvent: {ctrlKey: true}, - }); + wrapper.findWhere(resourceItemFilter)!.trigger('onClick', { + stopPropagation: () => {}, + nativeEvent: {ctrlKey: true}, + }); expect(spy).toHaveBeenCalledWith(url, '_blank'); }); }); @@ -465,13 +444,10 @@ describe('', () => { , ); - wrapper - .find('div') - .findWhere(resourceItemFilter)! - .trigger('onClick', { - stopPropagation: () => {}, - nativeEvent: {}, - }); + wrapper.findWhere(resourceItemFilter)!.trigger('onClick', { + stopPropagation: () => {}, + nativeEvent: {}, + }); expect(onClick).not.toHaveBeenCalledWith(itemId); }); @@ -490,13 +466,10 @@ describe('', () => { , ); - wrapper - .find('div') - .findWhere(resourceItemFilter)! - .trigger('onClick', { - stopPropagation: () => {}, - nativeEvent: {shiftKey: false}, - }); + wrapper.findWhere(resourceItemFilter)!.trigger('onClick', { + stopPropagation: () => {}, + nativeEvent: {shiftKey: false}, + }); expect(mockSelectModeContext.onSelectionChange).toHaveBeenCalledWith( true, itemId, @@ -521,13 +494,10 @@ describe('', () => { , ); - wrapper - .find('div') - .findWhere(resourceItemFilter)! - .trigger('onClick', { - stopPropagation: () => {}, - nativeEvent: {metaKey: true}, - }); + wrapper.findWhere(resourceItemFilter)!.trigger('onClick', { + stopPropagation: () => {}, + nativeEvent: {metaKey: true}, + }); expect(spy).not.toHaveBeenCalled(); }); @@ -538,13 +508,10 @@ describe('', () => { , ); - wrapper - .find('div') - .findWhere(resourceItemFilter)! - .trigger('onClick', { - stopPropagation: () => {}, - nativeEvent: {ctrlKey: true}, - }); + wrapper.findWhere(resourceItemFilter)!.trigger('onClick', { + stopPropagation: () => {}, + nativeEvent: {ctrlKey: true}, + }); expect(spy).not.toHaveBeenCalled(); }); }); From 92b615b7c8f9eac0f87b6a9c419abe441e046059 Mon Sep 17 00:00:00 2001 From: Luca Bezerra Date: Mon, 16 Aug 2021 14:49:26 -0400 Subject: [PATCH 11/16] Bumping react-testing version to be able to use new type checking features. --- package.json | 2 +- .../ResourceItem/tests/ResourceItem.test.tsx | 32 +++++++++++-------- yarn.lock | 18 +++++------ 3 files changed, 28 insertions(+), 24 deletions(-) diff --git a/package.json b/package.json index 8a8d3c0aeea..8356078bcbc 100644 --- a/package.json +++ b/package.json @@ -101,7 +101,7 @@ "@rollup/pluginutils": "^3.1.0", "@shopify/jest-dom-mocks": "^2.9.1", "@shopify/postcss-plugin": "^3.1.1", - "@shopify/react-testing": "^3.2.0", + "@shopify/react-testing": "^3.2.3", "@shopify/sewing-kit": "^0.140.0", "@shopify/storybook-a11y-test": "^0.0.1", "@size-limit/preset-small-lib": "^4.10.2", diff --git a/src/components/ResourceItem/tests/ResourceItem.test.tsx b/src/components/ResourceItem/tests/ResourceItem.test.tsx index 9fdccf5dca9..f3ca4c46bfc 100644 --- a/src/components/ResourceItem/tests/ResourceItem.test.tsx +++ b/src/components/ResourceItem/tests/ResourceItem.test.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import {mountWithApp, Node} from 'test-utilities'; +import {mountWithApp} from 'test-utilities'; import { Avatar, ButtonGroup, @@ -70,8 +70,12 @@ describe('', () => { const external = false; const ariaLabel = 'View Item'; - const resourceItemFilter = (node: Node) => - node.is('div') && node!.domNode.classList.contains(styles.ResourceItem); + function findResourceItem(wrapper: ReturnType) { + return wrapper!.findWhere<'div'>( + (node) => + node.is('div') && node.domNode!.classList.contains(styles.ResourceItem), + ); + } describe('accessibilityLabel', () => { it('is used on the for the aria-label attribute', () => { @@ -300,7 +304,7 @@ describe('', () => { , ); - wrapper.findWhere(resourceItemFilter)!.trigger('onClick', { + findResourceItem(wrapper)!.trigger('onClick', { stopPropagation: () => {}, nativeEvent: {}, }); @@ -320,7 +324,7 @@ describe('', () => { , ); - wrapper.findWhere(resourceItemFilter)!.trigger('onClick', { + findResourceItem(wrapper)!.trigger('onClick', { stopPropagation: () => {}, nativeEvent: {}, }); @@ -334,7 +338,7 @@ describe('', () => { , ); - wrapper.findWhere(resourceItemFilter)!.trigger('onClick', { + findResourceItem(wrapper)!.trigger('onClick', { stopPropagation: () => {}, nativeEvent: {metaKey: true}, }); @@ -349,7 +353,7 @@ describe('', () => { , ); - wrapper.findWhere(resourceItemFilter)!.trigger('onKeyUp', {key: 'Enter'}); + findResourceItem(wrapper)!.trigger('onKeyUp', {key: 'Enter'}); expect(onClick).toHaveBeenCalled(); }); @@ -362,7 +366,7 @@ describe('', () => { , ); - wrapper.findWhere(resourceItemFilter)!.trigger('onKeyUp', {key: 'Tab'}); + findResourceItem(wrapper)!.trigger('onKeyUp', {key: 'Tab'}); expect(onClick).not.toHaveBeenCalled(); }); @@ -375,7 +379,7 @@ describe('', () => { , ); - wrapper.findWhere(resourceItemFilter)!.trigger('onKeyUp', {key: 'Enter'}); + findResourceItem(wrapper)!.trigger('onKeyUp', {key: 'Enter'}); expect(onClick).not.toHaveBeenCalled(); }); @@ -386,7 +390,7 @@ describe('', () => { , ); - wrapper.findWhere(resourceItemFilter)!.trigger('onClick', { + findResourceItem(wrapper)!.trigger('onClick', { stopPropagation: () => {}, nativeEvent: {ctrlKey: true}, }); @@ -444,7 +448,7 @@ describe('', () => { , ); - wrapper.findWhere(resourceItemFilter)!.trigger('onClick', { + findResourceItem(wrapper)!.trigger('onClick', { stopPropagation: () => {}, nativeEvent: {}, }); @@ -466,7 +470,7 @@ describe('', () => { , ); - wrapper.findWhere(resourceItemFilter)!.trigger('onClick', { + findResourceItem(wrapper)!.trigger('onClick', { stopPropagation: () => {}, nativeEvent: {shiftKey: false}, }); @@ -494,7 +498,7 @@ describe('', () => { , ); - wrapper.findWhere(resourceItemFilter)!.trigger('onClick', { + findResourceItem(wrapper)!.trigger('onClick', { stopPropagation: () => {}, nativeEvent: {metaKey: true}, }); @@ -508,7 +512,7 @@ describe('', () => { , ); - wrapper.findWhere(resourceItemFilter)!.trigger('onClick', { + findResourceItem(wrapper)!.trigger('onClick', { stopPropagation: () => {}, nativeEvent: {ctrlKey: true}, }); diff --git a/yarn.lock b/yarn.lock index 34ba6b6c142..08fe78dc50b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2475,12 +2475,12 @@ "@babel/types" ">=7.0.0" webpack-virtual-modules "^0.2.2" -"@shopify/react-testing@^3.2.0": - version "3.2.0" - resolved "https://registry.yarnpkg.com/@shopify/react-testing/-/react-testing-3.2.0.tgz#496c6282d4d947277f53b27b83db00cb35b82705" - integrity sha512-ynBOJ5NyAhEMfgu2Neir2dWE5YoiVzrl3HR7dzmpqqnEsQn6S4AqtMxjDUChPeVxem0o8ey2C0kxuezphGAd4A== +"@shopify/react-testing@^3.2.3": + version "3.2.3" + resolved "https://registry.yarnpkg.com/@shopify/react-testing/-/react-testing-3.2.3.tgz#674fc87730559af8653fdddf7ea80df6beb42a99" + integrity sha512-AEGYOcMnaM+Qc3qJH5cJL4dEW8/GQNx/vRBk8cvzfX3FhPQ3nOKioEJo95PwSiThUns8R/alsjNVTZtId7mJcw== dependencies: - "@shopify/useful-types" "^3.0.1" + "@shopify/useful-types" "^3.0.3" jest-matcher-utils "^26.6.2" react-reconciler "^0.26.2" @@ -2665,10 +2665,10 @@ dependencies: tslib "^1.14.1" -"@shopify/useful-types@^3.0.1": - version "3.0.1" - resolved "https://registry.yarnpkg.com/@shopify/useful-types/-/useful-types-3.0.1.tgz#1021459d49917ce5bff6b0cb6c34df44a49375b9" - integrity sha512-aWjLNyxGxNKLYKs3evYrars9h8OV2Apc1DcZqkFETnm7EMeoFv16feV21xdwpQxj2W9EwCpw7CSmlvadzXxHyA== +"@shopify/useful-types@^3.0.3": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@shopify/useful-types/-/useful-types-3.0.3.tgz#67abb4c28b35d75f4da0d8887c555df45f8655b6" + integrity sha512-hkndiDi3HTBMZKPggLg99I6zc9P1TBWjPur7AvLYez7De+OR58XVNp8rp9TWIJ5nF73A+WWsaxqw9kmw+Tu+UQ== "@shopify/webpack-asset-metadata-plugin@^2.0.2": version "2.0.2" From f48af193b916d61d633c40102a845da30bdc6df5 Mon Sep 17 00:00:00 2001 From: Luca Bezerra Date: Thu, 19 Aug 2021 12:19:03 -0400 Subject: [PATCH 12/16] Test commit to temporarily increase node's memory heap size. --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 8356078bcbc..613486b046d 100644 --- a/package.json +++ b/package.json @@ -45,7 +45,7 @@ "scripts": { "lint": "sewing-kit lint", "format": "sewing-kit format", - "type-check": "sewing-kit type-check", + "type-check": "sewing-kit --heap 4098 type-check", "test": "sewing-kit test", "test:coverage": "CI=true yarn test --coverage", "posttest:coverage": "yarn open:coverage", From dca67c1533f67777125e2e4198554e1b4f8d4508 Mon Sep 17 00:00:00 2001 From: Luca Bezerra Date: Thu, 19 Aug 2021 12:26:04 -0400 Subject: [PATCH 13/16] Another test commit to temporarily increase node's memory heap size. --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 613486b046d..cab5238e77f 100644 --- a/package.json +++ b/package.json @@ -45,7 +45,7 @@ "scripts": { "lint": "sewing-kit lint", "format": "sewing-kit format", - "type-check": "sewing-kit --heap 4098 type-check", + "type-check": "sewing-kit --heap 8192 type-check", "test": "sewing-kit test", "test:coverage": "CI=true yarn test --coverage", "posttest:coverage": "yarn open:coverage", From 2ef532de9dc9621286f541b541c113bbb111c914 Mon Sep 17 00:00:00 2001 From: Luca Bezerra Date: Thu, 19 Aug 2021 12:26:04 -0400 Subject: [PATCH 14/16] Another test commit to temporarily increase node's memory heap size. --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 613486b046d..80c2f2730e1 100644 --- a/package.json +++ b/package.json @@ -43,9 +43,9 @@ } }, "scripts": { - "lint": "sewing-kit lint", + "lint": "sewing-kit --heap 8192 lint", "format": "sewing-kit format", - "type-check": "sewing-kit --heap 4098 type-check", + "type-check": "sewing-kit type-check", "test": "sewing-kit test", "test:coverage": "CI=true yarn test --coverage", "posttest:coverage": "yarn open:coverage", From 151925bca15a8af04ed4e50facb7c53803606d5b Mon Sep 17 00:00:00 2001 From: Luca Bezerra Date: Mon, 30 Aug 2021 11:24:50 -0400 Subject: [PATCH 15/16] Updating react-testing version. --- package.json | 2 +- yarn.lock | 18 +++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/package.json b/package.json index 6b1edc241ca..3a9356d1c7e 100644 --- a/package.json +++ b/package.json @@ -109,7 +109,7 @@ "@shopify/jest-dom-mocks": "^3.0.5", "@shopify/postcss-plugin": "^3.1.1", "@shopify/prettier-config": "^1.1.2", - "@shopify/react-testing": "^3.2.0", + "@shopify/react-testing": "^3.2.4", "@shopify/storybook-a11y-test": "^0.0.1", "@shopify/stylelint-plugin": "^10.0.1", "@shopify/typescript-configs": "^5.0.0", diff --git a/yarn.lock b/yarn.lock index 197005c6080..4ce74b17d7a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2330,12 +2330,12 @@ resolved "https://registry.yarnpkg.com/@shopify/prettier-config/-/prettier-config-1.1.2.tgz#612f87c0cd1196e8b43c85425e587d0fa7f1172d" integrity sha512-5ugCL9sPGzmOaZjeRGaWUWhHgAbemrS6z+R7v6gwiD+BiqSeoFhIY+imLpfdFCVpuOGalpHeCv6o3gv++EHs0A== -"@shopify/react-testing@^3.2.0": - version "3.2.0" - resolved "https://registry.yarnpkg.com/@shopify/react-testing/-/react-testing-3.2.0.tgz#496c6282d4d947277f53b27b83db00cb35b82705" - integrity sha512-ynBOJ5NyAhEMfgu2Neir2dWE5YoiVzrl3HR7dzmpqqnEsQn6S4AqtMxjDUChPeVxem0o8ey2C0kxuezphGAd4A== +"@shopify/react-testing@^3.2.4": + version "3.2.4" + resolved "https://registry.yarnpkg.com/@shopify/react-testing/-/react-testing-3.2.4.tgz#ecc136533270cbb252147318c3c7e300a02d495d" + integrity sha512-BhQgroiGA6VhPMAwsy2LVdNR1tv7nWkAL4uvW1SDiQEHhJmWJ1AyDq5UXKdWeDhoH3DoZOjALX1SFfLkSdIoKQ== dependencies: - "@shopify/useful-types" "^3.0.3" + "@shopify/useful-types" "^3.0.4" jest-matcher-utils "^26.6.2" react-reconciler "^0.26.2" @@ -2365,10 +2365,10 @@ resolved "https://registry.yarnpkg.com/@shopify/typescript-configs/-/typescript-configs-5.0.0.tgz#4cd1339a6a5ab34e7f7d852d155d2c82b731c152" integrity sha512-1TV9pr3UBr1AlGC//4bdeKiQ2qwDuaqCZGfxO2OtIg/EN3luDdf49UNNm/BL9ZiApHcz7kg9Wklc09vhzD24hw== -"@shopify/useful-types@^3.0.3": - version "3.0.3" - resolved "https://registry.yarnpkg.com/@shopify/useful-types/-/useful-types-3.0.3.tgz#67abb4c28b35d75f4da0d8887c555df45f8655b6" - integrity sha512-hkndiDi3HTBMZKPggLg99I6zc9P1TBWjPur7AvLYez7De+OR58XVNp8rp9TWIJ5nF73A+WWsaxqw9kmw+Tu+UQ== +"@shopify/useful-types@^3.0.4": + version "3.0.4" + resolved "https://registry.yarnpkg.com/@shopify/useful-types/-/useful-types-3.0.4.tgz#6b1f0908f60487550542c75acebea1a4f4eff968" + integrity sha512-uHVbNANIdYgWSF+vgL+H7j3ufyNzAbkHIgL0iYPb/C2OreHC1YaQWeMjjPQobzCb5MxultSPgvAbgWuytm3gCA== "@sinonjs/commons@^1.7.0": version "1.7.1" From ab5903cf84951aa9997a7d3919c117a7c3e60fc3 Mon Sep 17 00:00:00 2001 From: Luca Bezerra Date: Tue, 31 Aug 2021 09:26:16 -0400 Subject: [PATCH 16/16] Addressing PR comments. --- src/components/ResourceItem/tests/ResourceItem.test.tsx | 4 ++-- src/components/ResourceList/tests/ResourceList.test.tsx | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/components/ResourceItem/tests/ResourceItem.test.tsx b/src/components/ResourceItem/tests/ResourceItem.test.tsx index f3ca4c46bfc..d02a270171e 100644 --- a/src/components/ResourceItem/tests/ResourceItem.test.tsx +++ b/src/components/ResourceItem/tests/ResourceItem.test.tsx @@ -1,4 +1,4 @@ -import React from 'react'; +import React, {AllHTMLAttributes} from 'react'; import {mountWithApp} from 'test-utilities'; import { Avatar, @@ -752,7 +752,7 @@ describe('', () => { expect(item).toContainReactComponent('li', { 'data-href': 'google.com', - } as any); + } as AllHTMLAttributes); }); it('renders a data-href tag on the li when the dataHref prop is not specified', () => { diff --git a/src/components/ResourceList/tests/ResourceList.test.tsx b/src/components/ResourceList/tests/ResourceList.test.tsx index a3047b0828c..32079166daa 100644 --- a/src/components/ResourceList/tests/ResourceList.test.tsx +++ b/src/components/ResourceList/tests/ResourceList.test.tsx @@ -63,7 +63,6 @@ describe('', () => { , ); expect(resourceList).toContainReactText('title 1'); - // expect(resourceList.find('li').first().text()).toBe('title 1'); expect(warningSpy).toHaveBeenCalledWith( ' renderItem function should return a .', );