Skip to content

Commit

Permalink
test(popup): Add tests for Popup (#600)
Browse files Browse the repository at this point in the history
  • Loading branch information
mannycarrera4 committed May 4, 2020
1 parent 9084f91 commit 1339d00
Show file tree
Hide file tree
Showing 6 changed files with 264 additions and 22 deletions.
70 changes: 70 additions & 0 deletions cypress/integration/Popup.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import * as h from '../helpers';

function getPopup() {
return cy.findByRole('dialog');
}

function getPopupTargetButton() {
return cy.contains('Delete Item');
}

function getCloseButton() {
return getPopup().find('[data-close]');
}

describe('Popup', () => {
before(() => {
h.stories.visit();
});
context(`given the open popup`, () => {
beforeEach(() => {
h.stories.load('Components|Popups/Popup/React', 'Open');
});
it('should not have any axe errors', () => {
cy.checkA11y();
});

it('should have a role of dialog', () => {
getPopup().should('have.attr', 'role', 'dialog');
});
});

context(`given the default popup`, () => {
beforeEach(() => {
h.stories.load('Components|Popups/Popup/React', 'Default');
});
context('when the target buttton is clicked', () => {
beforeEach(() => {
getPopupTargetButton().click();
});

it('should open the popup', () => {
getPopup().should('be.visible');
});

it('should not have any axe errors', () => {
cy.checkA11y();
});

context('popup', () => {
it('should have a role of dialog', () => {
getPopup().should('have.attr', 'role', 'dialog');
});

it('should have an aria-labelledby attribute when a heading is provided', () => {
getPopup().should('have.attr', 'aria-labelledby');
});
});

context('when the close button is clicked', () => {
beforeEach(() => {
getCloseButton().click();
});

it('should close the popup', () => {
getPopup().should('not.visible');
});
});
});
});
});
20 changes: 12 additions & 8 deletions modules/popup/react/lib/Popup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export interface PopupProps extends React.HTMLAttributes<HTMLDivElement> {
* The origin from which the Popup will animate.
* @default {horizontal: 'center', vertical: 'top'}
*/
transformOrigin: TransformOrigin;
transformOrigin: TransformOrigin | null;
/**
* The size of the Popup close button. Accepts `Small` or `Medium`.
* @default IconButtonSize.Medium
Expand Down Expand Up @@ -86,12 +86,17 @@ const Container = styled('div', {
maxWidth: `calc(100vw - ${spacing.l})`,
},
({width}) => width && {width},
({transformOrigin}) => ({
animation: popupAnimation(transformOrigin),
animationDuration: '150ms',
animationTimingFunction: 'ease-out',
transformOrigin: `${transformOrigin.vertical} ${transformOrigin.horizontal}`,
})
({transformOrigin}) => {
if (transformOrigin === null) {
return {};
}
return {
animation: popupAnimation(transformOrigin),
animationDuration: '150ms',
animationTimingFunction: 'ease-out',
transformOrigin: `${transformOrigin.vertical} ${transformOrigin.horizontal}`,
};
}
);

const CloseIconContainer = styled('div')<Pick<PopupProps, 'closeIconSize'>>(
Expand Down Expand Up @@ -152,7 +157,6 @@ export default class Popup extends React.Component<PopupProps> {
size={closeIconSize}
onClick={handleClose}
icon={xIcon}
title={closeLabel}
aria-label={closeLabel}
/>
</CloseIconContainer>
Expand Down
3 changes: 3 additions & 0 deletions modules/popup/react/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@
"workday",
"popup"
],
"devDependencies": {
"@workday/canvas-kit-labs-react-core": "^3.6.0"
},
"dependencies": {
"@emotion/core": "^10.0.28",
"@emotion/is-prop-valid": "^0.8.2",
Expand Down
87 changes: 75 additions & 12 deletions modules/popup/react/spec/Popup.spec.tsx
Original file line number Diff line number Diff line change
@@ -1,25 +1,88 @@
import * as React from 'react';
import {render, fireEvent} from '@testing-library/react';
import Popup from '../lib/Popup';
import {mount} from 'enzyme';

describe('Popup', () => {
const cb = jest.fn();
afterEach(() => {
cb.mockReset();
});

test('should call a callback function', () => {
const component = mount(<Popup handleClose={cb}>Hello World</Popup>);
const popup = component.find('button');
popup.simulate('click');
expect(cb.mock.calls.length).toBe(1);
component.unmount();
describe('when rendered with a heading', () => {
it('should render popup with heading text', () => {
const headingText = 'Delete item';
const {getByRole} = render(
<Popup heading={headingText}>
<div>Are you sure you'd like to delete the item titled 'My Item'?</div>

<button onClick={cb}>Delete</button>
</Popup>
);
expect(getByRole('dialog').querySelector('h3')).toContainHTML(headingText);
});
});

describe('when rendered with a handleClose', () => {
it('should render popup with a close button', () => {
const closeButtonAriaLabel = 'close';
const {getByRole} = render(
<Popup closeLabel={closeButtonAriaLabel} handleClose={cb}>
<div>Are you sure you'd like to delete the item titled 'My Item'?</div>

<button onClick={cb}>Delete</button>
</Popup>
);
getByRole('dialog').querySelector('[data-close]');
expect(getByRole('dialog').querySelector('[data-close]')).toHaveAttribute(
'aria-label',
closeButtonAriaLabel
);
});

it('should call the handleClose callback when clicked', () => {
const closeButtonAriaLabel = 'close';
const {getByRole} = render(
<Popup closeLabel={closeButtonAriaLabel} handleClose={cb}>
<div>Are you sure you'd like to delete the item titled 'My Item'?</div>

<button onClick={cb}>Delete</button>
</Popup>
);

fireEvent.click(getByRole('dialog').querySelector('[data-close]'));

expect(cb).toHaveBeenCalledTimes(1);
});
});

test('Popup should spread extra props', () => {
const component = mount(<Popup data-propspread="test" />);
const container = component.at(0).getDOMNode();
expect(container.getAttribute('data-propspread')).toBe('test');
component.unmount();
describe('when rendered with extra props', () => {
it('should render popup with extra props', () => {
const {getByRole} = render(
<Popup data-propspread="test" handleClose={cb}>
<div>Are you sure you'd like to delete the item titled 'My Item'?</div>

<button onClick={cb}>Delete</button>
</Popup>
);

expect(getByRole('dialog')).toHaveAttribute('data-propspread', 'test');
});
});

describe('when rendered with a popup ref', () => {
it('should set the ref to the div element', () => {
const ref = React.createRef<HTMLDivElement>();

render(
<Popup popupRef={ref} data-propspread="test" handleClose={cb}>
<div>Are you sure you'd like to delete the item titled 'My Item'?</div>

<button onClick={cb}>Delete</button>
</Popup>
);

expect(ref.current).not.toBeNull();
expect(ref.current).toHaveAttribute('role', 'dialog');
});
});
});
102 changes: 102 additions & 0 deletions modules/popup/react/stories/stories_VisualTesting.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
/// <reference path="../../../../typings.d.ts" />
/** @jsx jsx */
import {jsx} from '@emotion/core';
import {storiesOf} from '@storybook/react';
import {StaticStates} from '@workday/canvas-kit-labs-react-core';
import {action} from '@storybook/addon-actions';
import {ComponentStatesTable} from '../../../../utils/storybook';
import {Popup} from '../index';
import {PopupPadding} from '../lib/Popup';
import {depth} from '@workday/canvas-kit-react-core';

storiesOf('Components|Popups/Popup/React/Visual Testing', module)
.addParameters({
component: Popup,
chromatic: {
disable: false,
},
})
.add('States', () => (
<StaticStates>
<ComponentStatesTable
rowProps={[
{label: 'Default', props: {}},
{label: 'On Close', props: {handleClose: action('close button clicked')}},
{label: 'With Heading', props: {heading: 'Delete Item'}},
{
label: 'With zero padding',
props: {
heading: 'Delete Item',
handleClose: action('close button clicked'),
padding: PopupPadding.zero,
},
},
{
label: 'With small padding',
props: {
heading: 'Delete Item',
handleClose: action('close button clicked'),
padding: PopupPadding.s,
},
},

{
label: 'With different depth value 1',
props: {
heading: 'Delete Item',
handleClose: action('close button clicked'),
depth: depth[1],
},
},
{
label: 'With different depth value 2',
props: {
heading: 'Delete Item',
handleClose: action('close button clicked'),
depth: depth[2],
},
},
{
label: 'With different depth value 3',
props: {
heading: 'Delete Item',
handleClose: action('close button clicked'),
depth: depth[3],
},
},
{
label: 'With different depth value 4',
props: {
heading: 'Delete Item',
handleClose: action('close button clicked'),
depth: depth[4],
},
},
{
label: 'With custom width',
props: {
heading: 'Delete Item',
handleClose: action('close button clicked'),
width: 300,
},
},
{
label: 'With small close icon',
props: {
heading: 'Delete Item',
handleClose: action('close button clicked'),
width: 300,
closeIconSize: 'small',
},
},
]}
columnProps={[{label: 'Default', props: {}}]}
>
{props => (
<Popup transformOrigin={null} {...props}>
Your workbook was successfully processed.
</Popup>
)}
</ComponentStatesTable>
</StaticStates>
));
4 changes: 2 additions & 2 deletions modules/toast/react/spec/Toast.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@ describe('Toast', () => {
{toastMessage}
</Toast>
);
const closeIcon = container.querySelector('[data-close="close"]'); /*? */
fireEvent.click(closeIcon); /*? */
const closeIcon = container.querySelector('[data-close="close"]');
fireEvent.click(closeIcon);
expect(cb).toHaveBeenCalledTimes(1);
});
});
Expand Down

0 comments on commit 1339d00

Please sign in to comment.