Skip to content

Commit

Permalink
test: Remove enzyme (#1418)
Browse files Browse the repository at this point in the history
Enzyme is not being supported long term. The React 17 adapter is unofficial and there may not be an adapter for future versions of React.

[category:Test]
  • Loading branch information
NicholasBoll authored Jan 14, 2022
1 parent 5f58fc1 commit b72dd97
Show file tree
Hide file tree
Showing 27 changed files with 510 additions and 1,172 deletions.
12 changes: 7 additions & 5 deletions .github/workflows/pull-request.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ on: pull_request
jobs:
install:
runs-on: ubuntu-latest
outputs:
cypress-version: ${{ steps.cypress-version.outputs.version }}

steps:
- uses: actions/checkout@v2
Expand Down Expand Up @@ -51,7 +53,7 @@ jobs:
- uses: actions/cache/@v2
with:
path: .cache/cypress
key: ${{ runner.os }}-cypress-cache-version-${{ steps.cypress-version.outputs.version }}
key: ${{ runner.os }}-cypress-cache-version-${{ needs.install.outputs.cypress-version }}

- uses: actions/cache@v2
with:
Expand Down Expand Up @@ -84,7 +86,7 @@ jobs:
- uses: actions/cache/@v2
with:
path: .cache/cypress
key: ${{ runner.os }}-cypress-cache-version-${{ steps.cypress-version.outputs.version }}
key: ${{ runner.os }}-cypress-cache-version-${{ needs.install.outputs.cypress-version }}

- uses: actions/cache@v2
with:
Expand Down Expand Up @@ -116,7 +118,7 @@ jobs:
- uses: actions/cache/@v2
with:
path: .cache/cypress
key: ${{ runner.os }}-cypress-cache-version-${{ steps.cypress-version.outputs.version }}
key: ${{ runner.os }}-cypress-cache-version-${{ needs.install.outputs.cypress-version }}

- uses: actions/cache@v2
with:
Expand All @@ -139,7 +141,7 @@ jobs:

integration-test:
runs-on: ubuntu-latest
needs: 'build'
needs: ['install', 'build']
strategy:
fail-fast: false
matrix:
Expand All @@ -156,7 +158,7 @@ jobs:
- uses: actions/cache/@v2
with:
path: .cache/cypress
key: ${{ runner.os }}-cypress-cache-version-${{ steps.cypress-version.outputs.version }}
key: ${{ runner.os }}-cypress-cache-version-${{ needs.install.outputs.cypress-version }}

- uses: actions/cache@v2
with:
Expand Down
3 changes: 0 additions & 3 deletions jest/setupTests.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import Adapter from 'enzyme-adapter-react-16';
import {configure} from 'enzyme';
import {toHaveNoViolations} from 'jest-axe';
import {matchers} from 'jest-emotion';
import '@testing-library/jest-dom/extend-expect';
Expand All @@ -10,7 +8,6 @@ import {setUniqueSeed, resetUniqueIdCount} from '@workday/canvas-kit-react/commo

expect.extend(toHaveNoViolations);
expect.extend(matchers);
configure({adapter: new Adapter()});

// add convenience variables to the global context
(global as any).verifyComponent = verifyComponent;
Expand Down
103 changes: 9 additions & 94 deletions modules/labs-react/header/spec/GlobalHeader.spec.tsx
Original file line number Diff line number Diff line change
@@ -1,111 +1,26 @@
import * as React from 'react';
import DeprecatedGlobalHeader from '../lib/GlobalHeader';
import {shallow} from 'enzyme';
import DeprecatedHeader from '../lib/Header';
import {SearchForm} from '@workday/canvas-kit-labs-react/search-form';
import {DeprecatedDubLogoTitle} from '../lib/parts';
import {DeprecatedHeaderTheme, DeprecatedHeaderVariant} from '../lib/shared/types';

declare global {
interface Window {
resizeBy: (x: number, y: number) => void;
}
}
const map: {[key: string]: any} = {};
window.addEventListener = jest.fn((event, callback) => {
map[event] = callback;
});
window.removeEventListener = jest.fn((event, callback) => {
if (map[event] && map[event] === callback) {
delete map[event];
}
});
window.dispatchEvent = (event: Event) => {
if (map[event.type]) {
map[event.type]();
}

// TODO: not totally accurate
return false;
};

window.resizeBy = (x: number, y: number) => {
// @ts-ignore
window.innerWidth = x;
// @ts-ignore
window.innerHeight = y;
window.dispatchEvent(new Event('resize'));
};

// @ts-ignore
window.requestAnimationFrame = cbFn => cbFn();
import {render} from '@testing-library/react';

describe('DeprecatedGlobalHeader', () => {
const cb = jest.fn();
beforeEach(() => {
window.resizeBy(1280, 1024);
});

afterEach(() => {
cb.mockReset();
});

describe('How DeprecatedGlobalHeader children render', () => {
beforeEach(() => {
window.resizeBy(1280, 1024);
});

test('Renders non-React child elements as is', () => {
const text = 'not a react element';
const wrapper = shallow<DeprecatedGlobalHeader>(
<DeprecatedGlobalHeader>{text}</DeprecatedGlobalHeader>
);
it('should render non-element children as is', () => {
const text = 'not an element';
const {container} = render(<DeprecatedGlobalHeader>{text}</DeprecatedGlobalHeader>);

expect(wrapper.contains(text));
expect(container).toContainHTML(text);
});

test('Renders a div element as is', () => {
const wrapper = shallow<DeprecatedGlobalHeader>(
<DeprecatedGlobalHeader>
<div>Test</div>
</DeprecatedGlobalHeader>
);
expect(
wrapper
.find('div')
.first()
.contains('Test')
).toBeTruthy();
});

test('Passes props to Header correctly', () => {
const propsHeader1 = {
brand: <div>Brand</div>,
menuToggle: <div>MenuToggle</div>,
onMenuClick: jest.fn(),
leftSlot: <SearchForm onSubmit={jest.fn()} />,
isCollapsed: true,
};
const propsHeader2 = {
menuToggle: 'abcde',
isCollapsed: false,
themeColor: DeprecatedHeaderTheme.White,
};
const defaultProps = {
brand: <DeprecatedDubLogoTitle />,
variant: DeprecatedHeaderVariant.Global,
children: undefined,
};

const childPropsHeader1 = shallow(<DeprecatedGlobalHeader {...propsHeader1} />)
.find(DeprecatedHeader)
.props();
const childPropsHeader2 = shallow(<DeprecatedGlobalHeader {...propsHeader2} />)
.find(DeprecatedHeader)
.props();
it('should render a div element as is', () => {
const html = <div>Test</div>;
const {container} = render(<DeprecatedGlobalHeader>{html}</DeprecatedGlobalHeader>);

expect(childPropsHeader1).toEqual({...defaultProps, ...propsHeader1});
expect(childPropsHeader2).toEqual({...defaultProps, ...propsHeader2});
expect(container).toContainHTML('<div>Test</div>');
});
});
});
132 changes: 28 additions & 104 deletions modules/labs-react/header/spec/Header.spec.tsx
Original file line number Diff line number Diff line change
@@ -1,136 +1,60 @@
import * as React from 'react';
import Header from '../lib/Header';
import {shallow, mount} from 'enzyme';
import {IconButton} from '@workday/canvas-kit-react/button';
import {SystemIcon} from '@workday/canvas-kit-react/icon';
import {activityStreamIcon, justifyIcon} from '@workday/canvas-system-icons-web';

declare global {
interface Window {
resizeBy: (x: number, y: number) => void;
}
}
const map: {[key: string]: any} = {};
window.addEventListener = jest.fn((event, callback) => {
map[event] = callback;
});
window.removeEventListener = jest.fn((event, callback) => {
if (map[event] && map[event] === callback) {
delete map[event];
}
});
window.dispatchEvent = (event: Event) => {
if (map[event.type]) {
map[event.type]();
}

// TODO: not totally accurate
return false;
};

window.resizeBy = (x: number, y: number) => {
// @ts-ignore
window.innerWidth = x;
// @ts-ignore
window.innerHeight = y;
window.dispatchEvent(new Event('resize'));
};

// @ts-ignore
window.requestAnimationFrame = cbFn => cbFn();
import {activityStreamIcon} from '@workday/canvas-system-icons-web';

describe('Header', () => {
const cb = jest.fn();
beforeEach(() => {
window.resizeBy(1280, 1024);
});
import {screen, render, fireEvent} from '@testing-library/react';

afterEach(() => {
cb.mockReset();
});
describe('Header', () => {
it('should spread extra props to containing element', () => {
render(<Header data-testid="test" data-propspread="test" />);

test('Header should spread extra props', () => {
const component = mount(<Header data-propspread="test" />);
const container = component.at(0).getDOMNode();
expect(container.getAttribute('data-propspread')).toBe('test');
component.unmount();
expect(screen.getByTestId('test')).toHaveAttribute('data-propspread', 'test');
});

describe('How Header children render', () => {
beforeEach(() => {
window.resizeBy(1280, 1024);
});
it('should render non-element children as is', () => {
const text = 'not an element';

test('Renders non-React child elements as is', () => {
const text = 'not a react element';
const wrapper = shallow<Header>(<Header>{text}</Header>);
const {container} = render(<Header>{text}</Header>);

expect(wrapper.contains(text));
expect(container).toContainHTML(text);
});

test('Renders a div element as is', () => {
const wrapper = shallow<Header>(
<Header>
<div>Test</div>
</Header>
);
expect(
wrapper
.find('div')
.first()
.contains('Test')
).toBeTruthy();
});
it('should render children as is', () => {
const children = <div>Test</div>;

const {container} = render(<Header>{children}</Header>);

test('Converts SystemIcons into IconButtons matching theme', () => {
const theme = Header.Theme.Blue;

const wrapper = mount<Header>(
<Header themeColor={theme}>
<a href="#">
<SystemIcon icon={activityStreamIcon} />
</a>
</Header>
);
const renderedIcon = wrapper.find(IconButton).first();

expect(wrapper.find(IconButton)).toHaveLength(1);
expect(renderedIcon.props().icon).toBe(activityStreamIcon);
expect(renderedIcon.props().variant).toBe('inverse');
expect(renderedIcon.props().onClick).toBeTruthy();
expect(container).toContainHTML('<div>Test</div>');
});

test('Renders a child hamburger menu (IconButton) when isCollapsed is true', () => {
const wrapper = mount<Header>(
<Header isCollapsed={true}>
<IconButton icon={activityStreamIcon} aria-label="Activity Stream" />
</Header>
);
const renderedIcon = wrapper.find(IconButton).first();
it('should render a hamburger menu with a justify icon when "isCollapsed" is true', () => {
render(<Header isCollapsed={true} />);

expect(renderedIcon.props().icon).toBe(justifyIcon);
expect(screen.getByRole('button', {name: 'Open Menu'})).toContainHTML('wd-icon-justify');
});

describe('When rendered in collapsed mode', () => {
test('Calls onMenuClick when the menuToggle does not have an onClick prop', () => {
describe('when rendered in collapsed mode', () => {
it('should call "onMenuClick" when the "menuToggle" component does not have an "onClick" prop', () => {
const onMenuClick = jest.fn();
const wrapper = mount<Header>(
render(
<Header
isCollapsed={true}
onMenuClick={onMenuClick}
menuToggle={<IconButton aria-label="Activity Stream" icon={activityStreamIcon} />}
/>
);

wrapper.find('button').simulate('click');
fireEvent.click(screen.getByRole('button', {name: 'Activity Stream'}));

expect(onMenuClick).toHaveBeenCalled();
});

test('Does not overwrite the menuToggle onClick prop when onMenuClick is defined', () => {
it('should not call "onMenuClick" when the "menuToggle" component has an "onClick" prop', () => {
const onMenuClick = jest.fn();
const onIconClick = jest.fn();
const wrapper = mount<Header>(
render(
<Header
isCollapsed={true}
onMenuClick={onMenuClick}
Expand All @@ -144,15 +68,15 @@ describe('Header', () => {
/>
);

wrapper.find('button').simulate('click');
fireEvent.click(screen.getByRole('button', {name: 'Activity Stream'}));

expect(onMenuClick).not.toHaveBeenCalled();
expect(onIconClick).toHaveBeenCalled();
});

test('Does not overwrite the menuToggle onClick prop when onMenuClick is undefined', () => {
it('should not overwrite the "menuToggle" onClick when "onMenuClick" is not provided', () => {
const onIconClick = jest.fn();
const wrapper = mount<Header>(
render(
<Header
isCollapsed={true}
menuToggle={
Expand All @@ -165,7 +89,7 @@ describe('Header', () => {
/>
);

wrapper.find('button').simulate('click');
fireEvent.click(screen.getByRole('button', {name: 'Activity Stream'}));

expect(onIconClick).toHaveBeenCalled();
});
Expand Down
2 changes: 1 addition & 1 deletion modules/preview-react/menu/lib/MenuItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,7 @@ class MenuItem extends React.Component<MenuItemProps> {
id={id}
role={role}
onClick={this.handleClick}
aria-disabled={!!isDisabled}
aria-disabled={isDisabled ? true : undefined}
isDisabled={!!isDisabled}
isFocused={!!isFocused}
{...elemProps}
Expand Down
Loading

0 comments on commit b72dd97

Please sign in to comment.