import * as React from 'react';
import { expect } from 'chai';
import { spy } from 'sinon';
import { createRenderer, reactMajor, isJsdom } from '@mui/internal-test-utils';
import Portal, { PortalProps } from '@mui/material/Portal';
describe('', () => {
const { render, renderToString } = createRenderer();
describe.skipIf(!isJsdom())('server-side', () => {
it('render nothing on the server', () => {
const { container } = renderToString(
Bar
,
);
expect(container.firstChild).to.equal(null);
});
});
describe('ref', () => {
it('should have access to the mountNode when disabledPortal={false}', () => {
const refSpy = spy();
const { unmount } = render(
Foo
,
);
expect(refSpy.args).to.deep.equal([[document.body]]);
unmount();
expect(refSpy.args).to.deep.equal([[document.body], [null]]);
});
it('should have access to the mountNode when disabledPortal={true}', () => {
const refSpy = spy();
const { unmount } = render(
Foo
,
{ strict: reactMajor <= 18 },
);
const mountNode = document.querySelector('.woofPortal');
expect(refSpy.args).to.deep.equal([[mountNode]]);
unmount();
expect(refSpy.args).to.deep.equal([[mountNode], [null]]);
});
it('should have access to the mountNode when switching disabledPortal', () => {
const refSpy = spy();
const { setProps, unmount } = render(
Foo
,
{ strict: reactMajor <= 18 },
);
const mountNode = document.querySelector('.woofPortal');
expect(refSpy.args).to.deep.equal([[mountNode]]);
setProps({
disablePortal: false,
ref: refSpy,
});
expect(refSpy.args).to.deep.equal([[mountNode], [null], [document.body]]);
unmount();
expect(refSpy.args).to.deep.equal([[mountNode], [null], [document.body], [null]]);
});
});
it('should render in a different node', () => {
render(
,
);
const rootElement = document.querySelector('#test1')!;
expect(rootElement.contains(document.querySelector('.woofPortal1'))).to.equal(true);
expect(rootElement.contains(document.querySelector('.woofPortal2'))).to.equal(false);
});
it('should unmount when parent unmounts', () => {
function Child() {
const containerRef = React.useRef(null);
return (
);
}
function Parent(props: { show?: boolean }) {
const { show = true } = props;
return {show ? : null}
;
}
const { setProps } = render();
expect(document.querySelectorAll('#test1').length).to.equal(1);
setProps({ show: false });
expect(document.querySelectorAll('#test1').length).to.equal(0);
});
it('should render overlay into container (document)', () => {
render(
,
);
expect(document.querySelectorAll('.test2').length).to.equal(2);
});
it('should render overlay into container (DOMNode)', () => {
const container = document.createElement('div');
render(
,
);
expect(container.querySelectorAll('#test2').length).to.equal(1);
});
it('should change container on prop change', () => {
type ContainerProps = {
disablePortal?: boolean;
containerElement?: boolean;
};
function ContainerTest(props: ContainerProps) {
const { containerElement = false, disablePortal = true } = props;
const containerRef = React.useRef(null);
const container = React.useCallback(
() => (containerElement ? containerRef.current : null),
[containerElement],
);
return (
);
}
const { setProps } = render();
expect(document.querySelector('#test3')?.parentElement?.nodeName).to.equal('SPAN');
setProps({
containerElement: true,
disablePortal: true,
});
expect(document.querySelector('#test3')?.parentElement?.nodeName).to.equal('SPAN');
setProps({
containerElement: true,
disablePortal: false,
});
expect(document.querySelector('#test3')?.parentElement?.nodeName).to.equal('STRONG');
setProps({
containerElement: false,
disablePortal: false,
});
expect(document.querySelector('#test3')?.parentElement?.nodeName).to.equal('BODY');
});
it('should call ref after child effect', () => {
const callOrder: Array = [];
const handleRef = (node: Element | null) => {
if (node) {
callOrder.push('ref');
}
};
const updateFunction = () => {
callOrder.push('effect');
};
function Test(props: PortalProps) {
const { container } = props;
const containerRef = React.useRef(null);
React.useEffect(() => {
if (containerRef.current !== container) {
updateFunction();
}
containerRef.current = container;
}, [container]);
return (
);
}
const { setProps } = render();
setProps({ container: null });
setProps({ container: document.createElement('div') });
setProps({ container: null });
expect(callOrder).to.deep.equal([
'effect',
'ref',
'effect',
'ref',
'effect',
'ref',
'effect',
'ref',
]);
});
});