Skip to content

Commit

Permalink
Fix unit tests
Browse files Browse the repository at this point in the history
  • Loading branch information
youknowriad committed May 14, 2019
1 parent 67350c1 commit a5446a1
Show file tree
Hide file tree
Showing 6 changed files with 86 additions and 106 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ exports[`URLPopover matches the snapshot in its default state 1`] = `
<Popover
className="editor-url-popover block-editor-url-popover"
focusOnMount="firstElement"
noArrow={false}
position="bottom center"
>
<div
Expand All @@ -28,7 +27,6 @@ exports[`URLPopover matches the snapshot when the settings are toggled open 1`]
<Popover
className="editor-url-popover block-editor-url-popover"
focusOnMount="firstElement"
noArrow={false}
position="bottom center"
>
<div
Expand Down Expand Up @@ -59,7 +57,6 @@ exports[`URLPopover matches the snapshot when there are no settings 1`] = `
<Popover
className="editor-url-popover block-editor-url-popover"
focusOnMount="firstElement"
noArrow={false}
position="bottom center"
>
<div
Expand Down
3 changes: 1 addition & 2 deletions packages/components/src/dropdown-menu/test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import { Component } from '@wordpress/element';
* Internal dependencies
*/
import DropdownMenu from '../';
import Popover from '../../popover';

describe( 'DropdownMenu', () => {
let controls;
Expand Down Expand Up @@ -79,7 +78,7 @@ describe( 'DropdownMenu', () => {
}
);

expect( TestUtils.scryRenderedComponentsWithType( wrapper, Popover ) ).toHaveLength( 1 );
expect( TestUtils.scryRenderedDOMComponentsWithClass( wrapper, 'components-popover' ) ).toHaveLength( 1 );
} );
} );
} );
6 changes: 3 additions & 3 deletions packages/components/src/dropdown/test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,11 @@ import TestUtils from 'react-dom/test-utils';
* Internal dependencies
*/
import Dropdown from '../';
import Popover from '../../popover';

describe( 'Dropdown', () => {
const expectPopoverVisible = ( wrapper, visible ) => {
expect(
TestUtils.scryRenderedComponentsWithType( wrapper, Popover ) )
TestUtils.scryRenderedDOMComponentsWithClass( wrapper, 'components-popover' ) )
.toHaveLength( visible ? 1 : 0 );
};
const buttonElement = ( wrapper ) => TestUtils.findRenderedDOMComponentWithTag(
Expand All @@ -31,13 +30,14 @@ describe( 'Dropdown', () => {
buttonElement( wrapper ).getAttribute( 'aria-expanded' )
).toBe( expanded.toString() );
};

const wrapper = TestUtils.renderIntoDocument( <Dropdown
className="container"
contentClassName="content"
renderToggle={ ( { isOpen, onToggle } ) => (
<button aria-expanded={ isOpen } onClick={ onToggle }>Toggleee</button>
) }
renderContent={ () => null }
renderContent={ () => <span>test</span> }
/> );

expectButtonExpanded( wrapper, false );
Expand Down
41 changes: 25 additions & 16 deletions packages/components/src/popover/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -182,30 +182,39 @@ const Popover = ( {
}, [] );

// Focus handling
useRef( () => {
if ( ! focusOnMount || ! contentRef.current ) {
return;
}
useEffect( () => {
/*
* Without the setTimeout, the dom node is not being focused. Related:
* https://stackoverflow.com/questions/35522220/react-ref-with-focus-doesnt-work-without-settimeout-my-example
*
* TODO: Treat the cause, not the symptom.
*/
const focusTimeout = setTimeout( () => {
if ( ! focusOnMount || ! contentRef.current ) {
return;
}

if ( focusOnMount === 'firstElement' ) {
if ( focusOnMount === 'firstElement' ) {
// Find first tabbable node within content and shift focus, falling
// back to the popover panel itself.
const firstTabbable = focus.tabbable.find( contentRef.current )[ 0 ];
const firstTabbable = focus.tabbable.find( contentRef.current )[ 0 ];
if ( firstTabbable ) {
firstTabbable.focus();
} else {
contentRef.current.focus();
}

if ( firstTabbable ) {
firstTabbable.focus();
} else {
contentRef.current.focus();
return;
}

return;
}

if ( focusOnMount === 'container' ) {
if ( focusOnMount === 'container' ) {
// Focus the popover panel itself so items in the popover are easily
// accessed via keyboard navigation.
contentRef.current.focus();
}
contentRef.current.focus();
}
}, 0 );

return () => clearTimeout( focusTimeout );
}, [] );

// Event handlers
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`Popover #render() should pass additional props to portaled element 1`] = `
exports[`Popover should pass additional props to portaled element 1`] = `
<span>
<div
tabindex="-1"
Expand All @@ -23,7 +23,7 @@ exports[`Popover #render() should pass additional props to portaled element 1`]
</span>
`;

exports[`Popover #render() should render content 1`] = `
exports[`Popover should render content 1`] = `
<span>
<div
tabindex="-1"
Expand Down
135 changes: 55 additions & 80 deletions packages/components/src/popover/test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,108 +2,83 @@
* External dependencies
*/
import TestUtils from 'react-dom/test-utils';
import ReactDOM from 'react-dom';
import { noop } from 'lodash';

/**
* WordPress dependencies
*/
import { Component } from '@wordpress/element';

/**
* Internal dependencies
*/
import Popover from '../';

describe( 'Popover', () => {
describe( '#componentDidUpdate()', () => {
let wrapper;
beforeEach( () => {
jest.spyOn( Popover.prototype, 'computePopoverPosition' ).mockImplementation( noop );
jest.spyOn( Popover.prototype, 'toggleAutoRefresh' ).mockImplementation( noop );
} );

afterEach( () => {
jest.restoreAllMocks();

// Resetting keyboard state is deferred, so ensure that timers are
// consumed to avoid leaking into other tests.
jest.runAllTimers();

if ( document.activeElement ) {
document.activeElement.blur();
}
} );
jest.useFakeTimers();

it( 'should turn on auto refresh', () => {
wrapper = TestUtils.renderIntoDocument( <Popover /> );
expect( Popover.prototype.toggleAutoRefresh ).toHaveBeenCalledWith( true );
expect( Popover.prototype.computePopoverPosition ).toHaveBeenCalled();
} );
class PopoverWrapper extends Component {
render() {
return <Popover { ...this.props } />;
}
}

it( 'should turn off auto refresh', () => {
wrapper = TestUtils.renderIntoDocument( <Popover /> );
// eslint-disable-next-line react/no-find-dom-node
ReactDOM.unmountComponentAtNode( ReactDOM.findDOMNode( wrapper ).parentNode );
expect( Popover.prototype.toggleAutoRefresh ).toHaveBeenCalledWith( false );
} );
describe( 'Popover', () => {
afterEach( () => {
if ( document.activeElement ) {
document.activeElement.blur();
}
} );

it( 'should set offset and forced positions on changed position', () => {
const node = document.createElement( 'div' );
wrapper = ReactDOM.render( <Popover />, node );
jest.clearAllMocks();
it( 'should focus when opening in response to keyboard event', () => {
// As in the real world, these occur in sequence before the popover
// has been mounted. Keyup's resetting is deferred.
document.dispatchEvent( new window.KeyboardEvent( 'keydown' ) );
document.dispatchEvent( new window.KeyboardEvent( 'keyup' ) );

ReactDOM.render( <Popover position={ 'bottom right' } />, node );
// An ideal test here would mount with an input child and focus the
// child, but in context of JSDOM the inputs are not visible and
// are therefore skipped as tabbable, defaulting to popover.
let wrapper;
TestUtils.act( () => {
wrapper = TestUtils.renderIntoDocument( <PopoverWrapper /> );

expect( Popover.prototype.toggleAutoRefresh ).not.toHaveBeenCalled();
expect( Popover.prototype.computePopoverPosition ).toHaveBeenCalled();
} );
jest.advanceTimersByTime( 1 );

it( 'should focus when opening in response to keyboard event', ( done ) => {
// As in the real world, these occur in sequence before the popover
// has been mounted. Keyup's resetting is deferred.
document.dispatchEvent( new window.KeyboardEvent( 'keydown' ) );
document.dispatchEvent( new window.KeyboardEvent( 'keyup' ) );

// An ideal test here would mount with an input child and focus the
// child, but in context of JSDOM the inputs are not visible and
// are therefore skipped as tabbable, defaulting to popover.
wrapper = TestUtils.renderIntoDocument( <Popover /> );

setTimeout( () => {
const content = TestUtils.findRenderedDOMComponentWithClass(
wrapper,
'components-popover__content'
);
expect( document.activeElement ).toBe( content );
done();
}, 1 );

jest.runAllTimers();
const content = TestUtils.findRenderedDOMComponentWithClass(
wrapper,
'components-popover__content'
);
expect( document.activeElement ).toBe( content );
} );
} );

it( 'should allow focus-on-open behavior to be disabled', ( done ) => {
const activeElement = document.activeElement;

wrapper = TestUtils.renderIntoDocument( <Popover focusOnMount={ false } /> );
it( 'should allow focus-on-open behavior to be disabled', () => {
const activeElement = document.activeElement;
TestUtils.act( () => {
TestUtils.renderIntoDocument( <Popover focusOnMount={ false } /> );

setTimeout( () => {
expect( document.activeElement ).toBe( activeElement );
done();
} );
jest.advanceTimersByTime( 1 );

jest.runAllTimers();
expect( document.activeElement ).toBe( activeElement );
} );
} );

describe( '#render()', () => {
it( 'should render content', () => {
const wrapper = TestUtils.renderIntoDocument( <Popover>Hello</Popover> );
const content = TestUtils.findRenderedDOMComponentWithTag( wrapper, 'span' );

expect( content ).toMatchSnapshot();
it( 'should render content', () => {
let wrapper;
TestUtils.act( () => {
wrapper = TestUtils.renderIntoDocument( <PopoverWrapper>Hello</PopoverWrapper> );
} );
const content = TestUtils.findRenderedDOMComponentWithTag( wrapper, 'span' );

it( 'should pass additional props to portaled element', () => {
const wrapper = TestUtils.renderIntoDocument( <Popover role="tooltip">Hello</Popover> );
const content = TestUtils.findRenderedDOMComponentWithTag( wrapper, 'span' );
expect( content ).toMatchSnapshot();
} );

expect( content ).toMatchSnapshot();
it( 'should pass additional props to portaled element', () => {
let wrapper;
TestUtils.act( () => {
wrapper = TestUtils.renderIntoDocument( <PopoverWrapper role="tooltip">Hello</PopoverWrapper> );
} );
const content = TestUtils.findRenderedDOMComponentWithTag( wrapper, 'span' );

expect( content ).toMatchSnapshot();
} );
} );

0 comments on commit a5446a1

Please sign in to comment.