Skip to content

Commit

Permalink
Update activeElement tests to use modern testing utils
Browse files Browse the repository at this point in the history
An imminent bump to SK and thus Jest exposes a case enzyme doesn't
handle component mounting to jsdom in a way that is spec compliant,
which then results in test that assert on document.activeElement failing.
Fortunatly react-testing doesn't have this problem, so we can just use
that instead
  • Loading branch information
BPScott committed Jun 23, 2020
1 parent a0acc07 commit c3e998e
Show file tree
Hide file tree
Showing 10 changed files with 142 additions and 213 deletions.
8 changes: 4 additions & 4 deletions src/components/Banner/tests/Banner.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -145,11 +145,11 @@ describe('<Banner />', () => {
return <Banner ref={banner} status="critical" />;
}

const div = mountWithAppProvider(<Test />)
.find('div')
.filterWhere((element) => element.prop('tabIndex') === 0);
const testComponent = mountWithApp(<Test />);

expect(div.getDOMNode()).toBe(document.activeElement);
expect(document.activeElement).toBe(
testComponent.find('div', {tabIndex: 0})!.domNode,
);
});

describe('Focus className', () => {
Expand Down
9 changes: 5 additions & 4 deletions src/components/Checkbox/tests/Checkbox.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {mountWithAppProvider} from 'test-utilities/legacy';
import {mountWithApp} from 'test-utilities';

import {Key} from '../../../types';
import {Choice} from '../../Choice';
import {Checkbox} from '../Checkbox';

describe('<Checkbox />', () => {
Expand Down Expand Up @@ -73,12 +74,12 @@ describe('<Checkbox />', () => {
});

it('sets focus on the input when checkbox is toggled off', () => {
const checkbox = mountWithAppProvider(
const checkbox = mountWithApp(
<Checkbox checked id="checkboxId" label="Checkbox" onChange={noop} />,
);
(checkbox.find('input') as any).instance().checked = false;
checkbox.simulate('click');
expect(checkbox.find('input').instance()).toBe(document.activeElement);
checkbox.find(Choice)!.trigger('onClick');

expect(document.activeElement).toBe(checkbox.find('input')!.domNode);
});

it('is not called from keyboard events when disabled', () => {
Expand Down
33 changes: 11 additions & 22 deletions src/components/Focus/tests/Focus.test.tsx
Original file line number Diff line number Diff line change
@@ -1,68 +1,57 @@
import React, {useRef, useState, useEffect} from 'react';
// eslint-disable-next-line no-restricted-imports
import {mountWithAppProvider} from 'test-utilities/legacy';
import {mountWithApp} from 'test-utilities';

import {Focus, FocusProps} from '../Focus';

describe('<Focus />', () => {
it('mounts', () => {
const focus = mountWithAppProvider(<FocusTestWrapper />);

expect(focus.exists()).toBe(true);
});

it('will not focus any element if none are natively focusable', () => {
mountWithAppProvider(
mountWithApp(
<FocusTestWrapper>
<span />
</FocusTestWrapper>,
);

expect(document.body).toBe(document.activeElement);
expect(document.activeElement).toBe(document.body);
});

it('will focus first focusable node when passing current node', () => {
const focus = mountWithAppProvider(
const focus = mountWithApp(
<FocusTestWrapper>
<input />
</FocusTestWrapper>,
);

const input = focus.find('input').getDOMNode();
expect(input).toBe(document.activeElement);
expect(document.activeElement).toBe(focus.find('input')!.domNode);
});

it('will focus first focusable node when passing ref', () => {
const focus = mountWithAppProvider(
const focus = mountWithApp(
<FocusTestWrapperRootReference>
<input />
</FocusTestWrapperRootReference>,
);

const input = focus.find('input').getDOMNode();
expect(input).toBe(document.activeElement);
expect(document.activeElement).toBe(focus.find('input')!.domNode);
});

it('will not focus the first focusable node if `disabled` is true', () => {
const focus = mountWithAppProvider(
const focus = mountWithApp(
<FocusTestWrapper disabled>
<input />
</FocusTestWrapper>,
);

const input = focus.find('input').getDOMNode();
expect(input).not.toBe(document.activeElement);
expect(document.activeElement).not.toBe(focus.find('input')!.domNode);
});

it('will not focus if there is no node', () => {
const focus = mountWithAppProvider(
const focus = mountWithApp(
<FocusTestWrapperNoNode>
<input />
</FocusTestWrapperNoNode>,
);

const input = focus.find('input').getDOMNode();
expect(input).not.toBe(document.activeElement);
expect(document.activeElement).not.toBe(focus.find('input')!.domNode);
});
});

Expand Down
29 changes: 15 additions & 14 deletions src/components/Frame/tests/Frame.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import {CSSTransition} from '@material-ui/react-transition-group';
import {animationFrame} from '@shopify/jest-dom-mocks';
import {documentHasStyle, mountWithApp} from 'test-utilities';
// eslint-disable-next-line no-restricted-imports
import {mountWithAppProvider, trigger} from 'test-utilities/legacy';
import {mountWithAppProvider} from 'test-utilities/legacy';
import {
ContextualSaveBar as PolarisContextualSavebar,
Loading as PolarisLoading,
Expand Down Expand Up @@ -53,13 +53,15 @@ describe('<Frame />', () => {
});

it('sets focus to the main content target anchor element when the skip to content link is clicked', () => {
const frame = mountWithAppProvider(<Frame />);
const mainAnchor = frame.find('main').find('a');
trigger(frame.find('a').at(0), 'onClick');
expect(mainAnchor.getDOMNode()).toBe(document.activeElement);
const frame = mountWithApp(<Frame />);

frame.find('a', {children: 'Skip to content'})!.trigger('onClick');
expect(document.activeElement).toBe(
frame.find('a', {id: 'AppFrameMainContent'})!.domNode,
);
});

it('sets focus to target element when the skip to content link is clicked', () => {
it.only('sets focus to target element when the skip to content link is clicked', () => {
const targetId = 'SkipToContentTarget';
const targetRef = React.createRef<HTMLAnchorElement>();

Expand All @@ -68,19 +70,18 @@ describe('<Frame />', () => {
<a id={targetId} ref={targetRef} tabIndex={-1} href="" />
);

const frame = mountWithAppProvider(
const frame = mountWithApp(
<Frame skipToContentTarget={targetRef}>{skipToContentTarget}</Frame>,
);

const triggerAnchor = frame.find('a').at(0);
const targetAnchor = frame.find(`#${targetId}`);
trigger(triggerAnchor, 'onFocus');
trigger(triggerAnchor, 'onClick');
const triggerAnchor = frame.findAll('a')[0]!;

triggerAnchor.trigger('onFocus');
triggerAnchor.trigger('onClick');

expect(triggerAnchor.getDOMNode().getAttribute('href')).toBe(
`#${targetId}`,
expect(document.activeElement).toBe(
frame.find('a', {id: targetId})!.domNode,
);
expect(targetAnchor.getDOMNode()).toBe(document.activeElement);
});
});

Expand Down
2 changes: 1 addition & 1 deletion src/components/Modal/tests/Modal.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ describe('<Modal>', () => {
const modal = mountWithAppProvider(<Modal onClose={jest.fn()} open />);
const focusedNode = findFirstFocusableNode(modal.find(Dialog).getDOMNode());

expect(focusedNode).toBe(document.activeElement);
expect(document.activeElement).toBe(focusedNode);
});

describe('src', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ describe('<FilterCreator />', () => {
'onClick',
);

expect(activator.getDOMNode()).toBe(document.activeElement);
expect(document.activeElement).toBe(activator.getDOMNode());
});

it('does not focus the activator after adding a filter if focus was never originally received by the by activator', () => {
Expand All @@ -110,7 +110,7 @@ describe('<FilterCreator />', () => {
'onClick',
);

expect(activator.getDOMNode()).not.toBe(document.activeElement);
expect(document.activeElement).not.toBe(activator.getDOMNode());
});

it('renders just a button by default', () => {
Expand Down
89 changes: 39 additions & 50 deletions src/components/ResourceList/tests/ResourceList.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
Button,
EmptyState,
} from 'components';
import {mountWithApp, Element} from 'test-utilities';
// eslint-disable-next-line no-restricted-imports
import {
findByTestID,
Expand Down Expand Up @@ -925,27 +926,28 @@ describe('<ResourceList />', () => {

describe('large screen', () => {
it('focuses the checkbox in the bulk action when the plain CheckableButton is clicked', () => {
const resourceList = mountWithAppProvider(
const resourceList = mountWithApp(
<ResourceList
items={itemsWithID}
renderItem={renderItem}
promotedBulkActions={promotedBulkActions}
/>,
);

const selectAllCheckableButton = plainCheckableButton(resourceList);
resourceList
.find(CheckableButton, {plain: true})!
.trigger('onToggleAll');

trigger(selectAllCheckableButton, 'onToggleAll');
const deselectAllCheckbox = resourceList
.findAll(CheckableButton)
.find((ele) => !ele.prop('plain'))!
.find('input', {type: 'checkbox'})!;

const deselectAllCheckbox = bulkActionsCheckableButton(
resourceList,
).find('input[type="checkbox"]');

expect(deselectAllCheckbox.getDOMNode()).toBe(document.activeElement);
expect(document.activeElement).toBe(deselectAllCheckbox.domNode);
});

it('focuses the plain CheckableButton checkbox when items are selected and the deselect Checkable button is clicked', () => {
const resourceList = mountWithAppProvider(
const resourceList = mountWithApp(
<ResourceList
items={itemsWithID}
renderItem={renderItem}
Expand All @@ -954,18 +956,17 @@ describe('<ResourceList />', () => {
/>,
);

const deselectAllCheckableButton = bulkActionsCheckableButton(
resourceList,
);

trigger(deselectAllCheckableButton, 'onToggleAll');
resourceList
.findAll(CheckableButton)
.find((ele) => !ele.prop('plain'))!
.trigger('onToggleAll');

const selectAllCheckableCheckbox = plainCheckableButton(
resourceList,
).find('input[type="checkbox"]');
const selectAllCheckableCheckbox = resourceList
.find(CheckableButton, {plain: true})!
.find('input', {type: 'checkbox'})!;

expect(selectAllCheckableCheckbox.getDOMNode()).toBe(
document.activeElement,
expect(document.activeElement).toBe(
selectAllCheckableCheckbox.domNode,
);
});
});
Expand All @@ -978,33 +979,33 @@ describe('<ResourceList />', () => {
it('keeps focus on the CheckableButton checkbox when selecting', () => {
setSmallScreen();

const resourceList = mountWithAppProvider(
const resourceList = mountWithApp(
<ResourceList
items={itemsWithID}
renderItem={renderItem}
promotedBulkActions={promotedBulkActions}
/>,
);

trigger(resourceList.find(Button).first(), 'onClick');
resourceList.find(Button)!.trigger('onClick');

const selectAllCheckableButton = bulkActionsCheckableButton(
resourceList,
);
const selectAllCheckableButton = resourceList
.findAll(CheckableButton)
.find((ele) => !ele.prop('plain'))!;

trigger(selectAllCheckableButton, 'onToggleAll');
selectAllCheckableButton.trigger('onToggleAll');

const checkBox = selectAllCheckableButton.find(
'input[type="checkbox"]',
);
const checkBox = selectAllCheckableButton.find('input', {
type: 'checkbox',
})!;

expect(checkBox.getDOMNode()).toBe(document.activeElement);
expect(document.activeElement).toBe(checkBox.domNode);
});

it('keeps focus on the CheckableButton checkbox when deselecting', () => {
setSmallScreen();

const resourceList = mountWithAppProvider(
const resourceList = mountWithApp(
<ResourceList
items={itemsWithID}
selectedItems={allSelectedIDs}
Expand All @@ -1013,17 +1014,17 @@ describe('<ResourceList />', () => {
/>,
);

const deselectAllCheckableButton = bulkActionsCheckableButton(
resourceList,
);
const deselectAllCheckableButton = resourceList
.findAll(CheckableButton)
.find((ele) => !ele.prop('plain'))!;

trigger(deselectAllCheckableButton, 'onToggleAll');
deselectAllCheckableButton.trigger('onToggleAll');

const checkBox = deselectAllCheckableButton.find(
'input[type="checkbox"]',
);
const checkBox = deselectAllCheckableButton.find('input', {
type: 'checkbox',
})!;

expect(checkBox.getDOMNode()).toBe(document.activeElement);
expect(document.activeElement).toBe(checkBox.domNode);
});
});
});
Expand Down Expand Up @@ -1224,15 +1225,3 @@ function setDefaultScreen() {
value: defaultWindowWidth,
});
}

function bulkActionsCheckableButton(wrapper: ReactWrapper) {
return wrapper.findWhere(
(wrap) => wrap.is(CheckableButton) && !wrap.prop('plain'),
);
}

function plainCheckableButton(wrapper: ReactWrapper) {
return wrapper.findWhere(
(wrap) => wrap.is(CheckableButton) && wrap.prop('plain'),
);
}
Loading

0 comments on commit c3e998e

Please sign in to comment.