diff --git a/src/modules/Embed/Embed.js b/src/modules/Embed/Embed.js index 55bb2c0d82..a27597700a 100644 --- a/src/modules/Embed/Embed.js +++ b/src/modules/Embed/Embed.js @@ -1,4 +1,5 @@ import cx from 'clsx' +import _ from 'lodash' import PropTypes from 'prop-types' import React from 'react' @@ -57,10 +58,9 @@ export default class Embed extends Component { } handleClick = (e) => { - const { onClick } = this.props const { active } = this.state - if (onClick) onClick(e, { ...this.props, active: true }) + _.invoke(this.props, 'onClick', e, { ...this.props, active: true }) if (!active) this.setState({ active: true }) } diff --git a/src/modules/Transition/Transition.js b/src/modules/Transition/Transition.js index 0cd0fb8e09..0fdea6a222 100644 --- a/src/modules/Transition/Transition.js +++ b/src/modules/Transition/Transition.js @@ -87,7 +87,11 @@ export default class Transition extends Component { const durationType = TRANSITION_CALLBACK_TYPE[nextStatus] const durationValue = normalizeTransitionDuration(duration, durationType) - this.timeoutId = setTimeout(() => this.setState({ status: nextStatus }), durationValue) + if (durationValue === 0) { + this.setState({ status: nextStatus }) + } else { + this.timeoutId = setTimeout(() => this.setState({ status: nextStatus }), durationValue) + } } updateStatus = (prevState) => { @@ -161,7 +165,7 @@ export default class Transition extends Component { debug('render(): state', this.state) const { children } = this.props - const { status } = this.state + const { nextStatus, status } = this.state if (status === TRANSITION_STATUS_UNMOUNTED) { return null @@ -170,6 +174,10 @@ export default class Transition extends Component { return cloneElement(children, { className: this.computeClasses(), style: this.computeStyle(), + ...(process.env.NODE_ENV !== 'production' && { + 'data-test-status': status, + 'data-test-next-status': nextStatus, + }), }) } } diff --git a/test/specs/addons/TransitionablePortal/TransitionablePortal-test.js b/test/specs/addons/TransitionablePortal/TransitionablePortal-test.js index 79d9f23a63..8dd4e6d4de 100644 --- a/test/specs/addons/TransitionablePortal/TransitionablePortal-test.js +++ b/test/specs/addons/TransitionablePortal/TransitionablePortal-test.js @@ -4,68 +4,26 @@ import TransitionablePortal from 'src/addons/TransitionablePortal/Transitionable import * as common from 'test/specs/commonTests' import { domEvent, sandbox, assertWithTimeout } from 'test/utils' -// ---------------------------------------- -// Wrapper -// ---------------------------------------- -let wrapper - -// we need to unmount the modal after every test to remove it from the document -// wrap the render methods to update a global wrapper that is unmounted after each test -const wrapperMount = (...args) => (wrapper = mount(...args)) -const wrapperShallow = (...args) => (wrapper = shallow(...args)) - const quickTransition = { duration: 0 } const requiredProps = { - children:
, + children:
, } describe('TransitionablePortal', () => { - beforeEach(() => { - wrapper = undefined - document.body.innerHTML = '' - }) - - afterEach(() => { - if (wrapper && wrapper.unmount) wrapper.unmount() - }) - common.isConformant(TransitionablePortal, { requiredProps }) describe('children', () => { - it('renders a Portal', () => { - wrapperShallow().should.have.descendants('Portal') - }) - it('renders a Transition', () => { - wrapperShallow().should.have.descendants( - 'Transition', - ) - }) - }) - - describe('getDerivedStateFromProps', () => { - it('passes `open` prop to `portalOpen` when defined', () => { - wrapperMount() + const wrapper = mount() - wrapper.setProps({ open: true }) - wrapper.should.have.state('portalOpen', true) - wrapper.setProps({ open: false }) - wrapper.should.have.state('portalOpen', false) - }) - - it('does not pass `open` prop to `portalOpen` when not defined', () => { - wrapperMount() - - wrapper.setProps({ transition: {} }) - wrapper.should.have.not.state('portalOpen') + wrapper.should.have.descendants('.transition') }) }) describe('onClose', () => { - it('is called with (null, data) when Portal closes', (done) => { + it('is called with (null, data) on a click outside', (done) => { const onClose = sandbox.spy() - - wrapperMount( + const wrapper = mount( { assertWithTimeout(() => { onClose.should.have.been.calledOnce() onClose.should.have.been.calledWithMatch(null, { portalOpen: false }) + + wrapper.unmount() }, done) }) - it('changes `portalOpen` to false', () => { - wrapperMount( - } - />, - ) + it('hides contents on a click outside', () => { + const wrapper = mount(} />) wrapper.find('button').simulate('click') - domEvent.click(document.body) + wrapper.should.have.descendants('.in#children') - wrapper.should.have.state('portalOpen', false) + domEvent.click(document.body) + wrapper.update() + wrapper.should.have.descendants('.out#children') }) }) describe('onHide', () => { it('is called with (null, data) when exiting transition finished', (done) => { const onHide = sandbox.spy() - const trigger =