chore: auto merge branchs (#35399)

chore: feature merge master
This commit is contained in:
github-actions[bot] 2022-05-06 05:52:21 +00:00 committed by GitHub
commit 25de1c4d31
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 556 additions and 306 deletions

View File

@ -1,8 +1,7 @@
import React from 'react'; import React from 'react';
import { mount } from 'enzyme';
import Anchor from '..'; import Anchor from '..';
import type { InternalAnchorClass } from '../Anchor'; import type { InternalAnchorClass } from '../Anchor';
import { sleep, render } from '../../../tests/utils'; import { sleep, render, fireEvent } from '../../../tests/utils';
const { Link } = Anchor; const { Link } = Anchor;
@ -48,42 +47,54 @@ describe('Anchor Render', () => {
it('Anchor render perfectly', () => { it('Anchor render perfectly', () => {
const hash = getHashUrl(); const hash = getHashUrl();
const wrapper = mount( let anchorInstance: InternalAnchorClass;
<Anchor> const { container } = render(
<Anchor
ref={node => {
anchorInstance = node as InternalAnchorClass;
}}
>
<Link href={`#${hash}`} title={hash} /> <Link href={`#${hash}`} title={hash} />
</Anchor>, </Anchor>,
); );
wrapper.find(`a[href="#${hash}"]`).simulate('click'); fireEvent.click(container.querySelector(`a[href="#${hash}"]`)!);
const anchorInstance = wrapper.find('Anchor').last().instance() as any as InternalAnchorClass; anchorInstance!.handleScroll();
anchorInstance.handleScroll(); expect(anchorInstance!.state).not.toBe(null);
expect(anchorInstance.state).not.toBe(null);
}); });
it('Anchor render perfectly for complete href - click', () => { it('Anchor render perfectly for complete href - click', () => {
const hash = getHashUrl(); const hash = getHashUrl();
const wrapper = mount( let anchorInstance: InternalAnchorClass;
<Anchor> const { container } = render(
<Anchor
ref={node => {
anchorInstance = node as InternalAnchorClass;
}}
>
<Link href={`http://www.example.com/#${hash}`} title={hash} /> <Link href={`http://www.example.com/#${hash}`} title={hash} />
</Anchor>, </Anchor>,
); );
wrapper.find(`a[href="http://www.example.com/#${hash}"]`).simulate('click'); fireEvent.click(container.querySelector(`a[href="http://www.example.com/#${hash}"]`)!);
const anchorInstance = wrapper.find('Anchor').last().instance() as any as InternalAnchorClass; expect(anchorInstance!.state!.activeLink).toBe(`http://www.example.com/#${hash}`);
expect(anchorInstance.state.activeLink).toBe(`http://www.example.com/#${hash}`);
}); });
it('Anchor render perfectly for complete href - hash router', async () => { it('Anchor render perfectly for complete href - hash router', async () => {
const root = createDiv(); const root = createDiv();
const scrollToSpy = jest.spyOn(window, 'scrollTo'); const scrollToSpy = jest.spyOn(window, 'scrollTo');
mount(<div id="/faq?locale=en#Q1">Q1</div>, { attachTo: root }); render(<div id="/faq?locale=en#Q1">Q1</div>, { container: root });
const wrapper = mount( let anchorInstance: InternalAnchorClass;
<Anchor> render(
<Anchor
ref={node => {
anchorInstance = node as InternalAnchorClass;
}}
>
<Link href="/#/faq?locale=en#Q1" title="Q1" /> <Link href="/#/faq?locale=en#Q1" title="Q1" />
</Anchor>, </Anchor>,
); );
const anchorInstance = wrapper.find('Anchor').last().instance() as any as InternalAnchorClass; anchorInstance!.handleScrollTo('/#/faq?locale=en#Q1');
anchorInstance.handleScrollTo('/#/faq?locale=en#Q1'); expect(anchorInstance!.state.activeLink).toBe('/#/faq?locale=en#Q1');
expect(anchorInstance.state.activeLink).toBe('/#/faq?locale=en#Q1');
expect(scrollToSpy).not.toHaveBeenCalled(); expect(scrollToSpy).not.toHaveBeenCalled();
await sleep(1000); await sleep(1000);
expect(scrollToSpy).toHaveBeenCalled(); expect(scrollToSpy).toHaveBeenCalled();
@ -92,32 +103,39 @@ describe('Anchor Render', () => {
it('Anchor render perfectly for complete href - scroll', () => { it('Anchor render perfectly for complete href - scroll', () => {
const hash = getHashUrl(); const hash = getHashUrl();
const root = createDiv(); const root = createDiv();
mount(<div id={hash}>Hello</div>, { attachTo: root }); render(<div id={hash}>Hello</div>, { container: root });
const wrapper = mount( let anchorInstance: InternalAnchorClass;
<Anchor> render(
<Anchor
ref={node => {
anchorInstance = node as InternalAnchorClass;
}}
>
<Link href={`http://www.example.com/#${hash}`} title={hash} /> <Link href={`http://www.example.com/#${hash}`} title={hash} />
</Anchor>, </Anchor>,
); );
const anchorInstance = wrapper.find('Anchor').last().instance() as any as InternalAnchorClass; anchorInstance!.handleScroll();
expect(anchorInstance!.state!.activeLink).toBe(`http://www.example.com/#${hash}`);
anchorInstance.handleScroll();
expect(anchorInstance.state.activeLink).toBe(`http://www.example.com/#${hash}`);
}); });
it('Anchor render perfectly for complete href - scrollTo', async () => { it('Anchor render perfectly for complete href - scrollTo', async () => {
const hash = getHashUrl(); const hash = getHashUrl();
const scrollToSpy = jest.spyOn(window, 'scrollTo'); const scrollToSpy = jest.spyOn(window, 'scrollTo');
const root = createDiv(); const root = createDiv();
mount(<div id={`#${hash}`}>Hello</div>, { attachTo: root }); render(<div id={`#${hash}`}>Hello</div>, { container: root });
const wrapper = mount( let anchorInstance: InternalAnchorClass;
<Anchor> render(
<Anchor
ref={node => {
anchorInstance = node as InternalAnchorClass;
}}
>
<Link href={`##${hash}`} title={hash} /> <Link href={`##${hash}`} title={hash} />
</Anchor>, </Anchor>,
); );
const anchorInstance = wrapper.find('Anchor').last().instance() as any as InternalAnchorClass;
anchorInstance.handleScrollTo(`##${hash}`); anchorInstance!.handleScrollTo(`##${hash}`);
expect(anchorInstance.state.activeLink).toBe(`##${hash}`); expect(anchorInstance!.state.activeLink).toBe(`##${hash}`);
const calls = scrollToSpy.mock.calls.length; const calls = scrollToSpy.mock.calls.length;
await sleep(1000); await sleep(1000);
expect(scrollToSpy.mock.calls.length).toBeGreaterThan(calls); expect(scrollToSpy.mock.calls.length).toBeGreaterThan(calls);
@ -125,15 +143,19 @@ describe('Anchor Render', () => {
it('should remove listener when unmount', async () => { it('should remove listener when unmount', async () => {
const hash = getHashUrl(); const hash = getHashUrl();
const wrapper = mount( let anchorInstance: InternalAnchorClass;
<Anchor> const { unmount } = render(
<Anchor
ref={node => {
anchorInstance = node as InternalAnchorClass;
}}
>
<Link href={`#${hash}`} title={hash} /> <Link href={`#${hash}`} title={hash} />
</Anchor>, </Anchor>,
); );
const anchorInstance = wrapper.find('Anchor').last().instance() as any as InternalAnchorClass;
const removeListenerSpy = jest.spyOn((anchorInstance as any).scrollEvent, 'remove'); const removeListenerSpy = jest.spyOn((anchorInstance! as any).scrollEvent, 'remove');
wrapper.unmount(); unmount();
expect(removeListenerSpy).toHaveBeenCalled(); expect(removeListenerSpy).toHaveBeenCalled();
}); });
@ -154,23 +176,27 @@ describe('Anchor Render', () => {
it('should update links when link href update', async () => { it('should update links when link href update', async () => {
const hash = getHashUrl(); const hash = getHashUrl();
let anchorInstance: InternalAnchorClass;
function AnchorUpdate({ href }: { href: string }) { function AnchorUpdate({ href }: { href: string }) {
return ( return (
<Anchor> <Anchor
ref={node => {
anchorInstance = node as InternalAnchorClass;
}}
>
<Link href={href} title={hash} /> <Link href={href} title={hash} />
</Anchor> </Anchor>
); );
} }
const wrapper = mount(<AnchorUpdate href={`#${hash}`} />); const { rerender } = render(<AnchorUpdate href={`#${hash}`} />);
const anchorInstance = wrapper.find('Anchor').last().instance() as any as InternalAnchorClass;
if (anchorInstance == null) { if (anchorInstance! == null) {
throw new Error('anchorInstance should not be null'); throw new Error('anchorInstance should not be null');
} }
expect((anchorInstance as any).links).toEqual([`#${hash}`]); expect((anchorInstance as any)!.links).toEqual([`#${hash}`]);
wrapper.setProps({ href: `#${hash}_1` }); rerender(<AnchorUpdate href={`#${hash}_1`} />);
expect((anchorInstance as any).links).toEqual([`#${hash}_1`]); expect((anchorInstance as any)!.links).toEqual([`#${hash}_1`]);
}); });
it('Anchor onClick event', () => { it('Anchor onClick event', () => {
@ -187,18 +213,20 @@ describe('Anchor Render', () => {
const href = `#${hash}`; const href = `#${hash}`;
const title = hash; const title = hash;
let anchorInstance: InternalAnchorClass;
const wrapper = mount( const { container } = render(
<Anchor onClick={handleClick}> <Anchor
onClick={handleClick}
ref={node => {
anchorInstance = node as InternalAnchorClass;
}}
>
<Link href={href} title={title} /> <Link href={href} title={title} />
</Anchor>, </Anchor>,
); );
wrapper.find(`a[href="${href}"]`).simulate('click'); fireEvent.click(container.querySelector(`a[href="${href}"]`)!);
anchorInstance!.handleScroll();
const anchorInstance = wrapper.find('Anchor').last().instance() as any as InternalAnchorClass;
anchorInstance.handleScroll();
expect(event).not.toBe(undefined); expect(event).not.toBe(undefined);
expect(link).toEqual({ href, title }); expect(link).toEqual({ href, title });
}); });
@ -206,20 +234,28 @@ describe('Anchor Render', () => {
it('Different function returns the same DOM', async () => { it('Different function returns the same DOM', async () => {
const hash = getHashUrl(); const hash = getHashUrl();
const root = createDiv(); const root = createDiv();
mount(<div id={hash}>Hello</div>, { attachTo: root }); render(<div id={hash}>Hello</div>, { container: root });
const getContainerA = createGetContainer(hash); const getContainerA = createGetContainer(hash);
const getContainerB = createGetContainer(hash); const getContainerB = createGetContainer(hash);
let anchorInstance: InternalAnchorClass;
const wrapper = mount( const { rerender } = render(
<Anchor getContainer={getContainerA}> <Anchor
getContainer={getContainerA}
ref={node => {
anchorInstance = node as InternalAnchorClass;
}}
>
<Link href={`#${hash}`} title={hash} /> <Link href={`#${hash}`} title={hash} />
</Anchor>, </Anchor>,
); );
const anchorInstance = wrapper.find('Anchor').last().instance() as any as InternalAnchorClass;
const removeListenerSpy = jest.spyOn((anchorInstance as any).scrollEvent, 'remove'); const removeListenerSpy = jest.spyOn((anchorInstance! as any).scrollEvent, 'remove');
await sleep(1000); await sleep(1000);
wrapper.setProps({ getContainer: getContainerB }); rerender(
<Anchor getContainer={getContainerB}>
<Link href={`#${hash}`} title={hash} />
</Anchor>,
);
expect(removeListenerSpy).not.toHaveBeenCalled(); expect(removeListenerSpy).not.toHaveBeenCalled();
}); });
@ -227,57 +263,73 @@ describe('Anchor Render', () => {
const hash1 = getHashUrl(); const hash1 = getHashUrl();
const hash2 = getHashUrl(); const hash2 = getHashUrl();
const root = createDiv(); const root = createDiv();
mount( render(
<div> <div>
<div id={hash1}>Hello</div> <div id={hash1}>Hello</div>
<div id={hash2}>World</div> <div id={hash2}>World</div>
</div>, </div>,
{ attachTo: root }, { container: root },
); );
const getContainerA = createGetContainer(hash1); const getContainerA = createGetContainer(hash1);
const getContainerB = createGetContainer(hash2); const getContainerB = createGetContainer(hash2);
const wrapper = mount( let anchorInstance: InternalAnchorClass;
<Anchor getContainer={getContainerA}> const { rerender } = render(
<Anchor
getContainer={getContainerA}
ref={node => {
anchorInstance = node as InternalAnchorClass;
}}
>
<Link href={`#${hash1}`} title={hash1} /> <Link href={`#${hash1}`} title={hash1} />
<Link href={`#${hash2}`} title={hash2} /> <Link href={`#${hash2}`} title={hash2} />
</Anchor>, </Anchor>,
); );
const anchorInstance = wrapper.find('Anchor').last().instance() as any as InternalAnchorClass;
const removeListenerSpy = jest.spyOn((anchorInstance as any).scrollEvent, 'remove'); const removeListenerSpy = jest.spyOn((anchorInstance! as any).scrollEvent, 'remove');
expect(removeListenerSpy).not.toHaveBeenCalled(); expect(removeListenerSpy).not.toHaveBeenCalled();
await sleep(1000); await sleep(1000);
wrapper.setProps({ getContainer: getContainerB }); rerender(
<Anchor getContainer={getContainerB}>
<Link href={`#${hash1}`} title={hash1} />
<Link href={`#${hash2}`} title={hash2} />
</Anchor>,
);
expect(removeListenerSpy).toHaveBeenCalled(); expect(removeListenerSpy).toHaveBeenCalled();
}); });
it('Same function returns the same DOM', () => { it('Same function returns the same DOM', () => {
const hash = getHashUrl(); const hash = getHashUrl();
const root = createDiv(); const root = createDiv();
mount(<div id={hash}>Hello</div>, { attachTo: root }); render(<div id={hash}>Hello</div>, { container: root });
const getContainer = createGetContainer(hash); const getContainer = createGetContainer(hash);
const wrapper = mount( let anchorInstance: InternalAnchorClass;
<Anchor getContainer={getContainer}> const { container } = render(
<Anchor
getContainer={getContainer}
ref={node => {
anchorInstance = node as InternalAnchorClass;
}}
>
<Link href={`#${hash}`} title={hash} /> <Link href={`#${hash}`} title={hash} />
</Anchor>, </Anchor>,
); );
wrapper.find(`a[href="#${hash}"]`).simulate('click');
const anchorInstance = wrapper.find('Anchor').last().instance() as any as InternalAnchorClass;
(anchorInstance as any).handleScroll(); fireEvent.click(container.querySelector(`a[href="#${hash}"]`)!);
expect(anchorInstance.state).not.toBe(null);
anchorInstance!.handleScroll();
expect(anchorInstance!.state).not.toBe(null);
}); });
it('Same function returns different DOM', async () => { it('Same function returns different DOM', async () => {
const hash1 = getHashUrl(); const hash1 = getHashUrl();
const hash2 = getHashUrl(); const hash2 = getHashUrl();
const root = createDiv(); const root = createDiv();
mount( render(
<div> <div>
<div id={hash1}>Hello</div> <div id={hash1}>Hello</div>
<div id={hash2}>World</div> <div id={hash2}>World</div>
</div>, </div>,
{ attachTo: root }, { container: root },
); );
const holdContainer = { const holdContainer = {
container: document.getElementById(hash1), container: document.getElementById(hash1),
@ -288,19 +340,28 @@ describe('Anchor Render', () => {
} }
return holdContainer.container; return holdContainer.container;
}; };
const wrapper = mount( let anchorInstance: InternalAnchorClass;
const { rerender } = render(
<Anchor
getContainer={getContainer}
ref={node => {
anchorInstance = node as InternalAnchorClass;
}}
>
<Link href={`#${hash1}`} title={hash1} />
<Link href={`#${hash2}`} title={hash2} />
</Anchor>,
);
const removeListenerSpy = jest.spyOn((anchorInstance! as any).scrollEvent, 'remove');
expect(removeListenerSpy).not.toHaveBeenCalled();
await sleep(1000);
holdContainer.container = document.getElementById(hash2);
rerender(
<Anchor getContainer={getContainer}> <Anchor getContainer={getContainer}>
<Link href={`#${hash1}`} title={hash1} /> <Link href={`#${hash1}`} title={hash1} />
<Link href={`#${hash2}`} title={hash2} /> <Link href={`#${hash2}`} title={hash2} />
</Anchor>, </Anchor>,
); );
const anchorInstance = wrapper.find('Anchor').last().instance() as any as InternalAnchorClass;
const removeListenerSpy = jest.spyOn((anchorInstance as any).scrollEvent, 'remove');
expect(removeListenerSpy).not.toHaveBeenCalled();
await sleep(1000);
holdContainer.container = document.getElementById(hash2);
wrapper.setProps({ 'data-only-trigger-re-render': true });
expect(removeListenerSpy).toHaveBeenCalled(); expect(removeListenerSpy).toHaveBeenCalled();
}); });
@ -323,27 +384,45 @@ describe('Anchor Render', () => {
const scrollToSpy = jest.spyOn(window, 'scrollTo'); const scrollToSpy = jest.spyOn(window, 'scrollTo');
const root = createDiv(); const root = createDiv();
mount(<h1 id={hash}>Hello</h1>, { attachTo: root }); render(<h1 id={hash}>Hello</h1>, { container: root });
const wrapper = mount( let anchorInstance: InternalAnchorClass;
<Anchor> const { rerender } = render(
<Anchor
ref={node => {
anchorInstance = node as InternalAnchorClass;
}}
>
<Link href={`#${hash}`} title={hash} /> <Link href={`#${hash}`} title={hash} />
</Anchor>, </Anchor>,
); );
const anchorInstance = wrapper.find('Anchor').last().instance() as any as InternalAnchorClass;
anchorInstance.handleScrollTo(`#${hash}`); const setProps = (props: Record<string, any>) =>
rerender(
<Anchor
ref={node => {
anchorInstance = node as InternalAnchorClass;
}}
{...props}
>
<Link href={`#${hash}`} title={hash} />
</Anchor>,
);
anchorInstance!.handleScrollTo(`#${hash}`);
await sleep(30); await sleep(30);
expect(scrollToSpy).toHaveBeenLastCalledWith(0, 1000); expect(scrollToSpy).toHaveBeenLastCalledWith(0, 1000);
dateNowMock = dataNowMockFn(); dateNowMock = dataNowMockFn();
wrapper.setProps({ offsetTop: 100 }); setProps({ offsetTop: 100 });
anchorInstance.handleScrollTo(`#${hash}`);
anchorInstance!.handleScrollTo(`#${hash}`);
await sleep(30); await sleep(30);
expect(scrollToSpy).toHaveBeenLastCalledWith(0, 900); expect(scrollToSpy).toHaveBeenLastCalledWith(0, 900);
dateNowMock = dataNowMockFn(); dateNowMock = dataNowMockFn();
wrapper.setProps({ targetOffset: 200 }); setProps({ targetOffset: 200 });
anchorInstance.handleScrollTo(`#${hash}`);
anchorInstance!.handleScrollTo(`#${hash}`);
await sleep(30); await sleep(30);
expect(scrollToSpy).toHaveBeenLastCalledWith(0, 800); expect(scrollToSpy).toHaveBeenLastCalledWith(0, 800);
@ -370,27 +449,43 @@ describe('Anchor Render', () => {
const scrollToSpy = jest.spyOn(window, 'scrollTo'); const scrollToSpy = jest.spyOn(window, 'scrollTo');
const root = createDiv(); const root = createDiv();
mount(<h1 id={hash}>Hello</h1>, { attachTo: root }); render(<h1 id={hash}>Hello</h1>, { container: root });
const wrapper = mount( let anchorInstance: InternalAnchorClass;
<Anchor> const { rerender } = render(
<Anchor
ref={node => {
anchorInstance = node as InternalAnchorClass;
}}
>
<Link href={`#${hash}`} title={hash} /> <Link href={`#${hash}`} title={hash} />
</Anchor>, </Anchor>,
); );
const anchorInstance = wrapper.find('Anchor').last().instance() as any as InternalAnchorClass;
anchorInstance.handleScrollTo(`#${hash}`); const setProps = (props: Record<string, any>) =>
rerender(
<Anchor
ref={node => {
anchorInstance = node as InternalAnchorClass;
}}
{...props}
>
<Link href={`#${hash}`} title={hash} />
</Anchor>,
);
anchorInstance!.handleScrollTo(`#${hash}`);
await sleep(30); await sleep(30);
expect(scrollToSpy).toHaveBeenLastCalledWith(0, 1000); expect(scrollToSpy).toHaveBeenLastCalledWith(0, 1000);
dateNowMock = dataNowMockFn(); dateNowMock = dataNowMockFn();
wrapper.setProps({ offsetTop: 100 }); setProps({ offsetTop: 100 });
anchorInstance.handleScrollTo(`#${hash}`); anchorInstance!.handleScrollTo(`#${hash}`);
await sleep(30); await sleep(30);
expect(scrollToSpy).toHaveBeenLastCalledWith(0, 900); expect(scrollToSpy).toHaveBeenLastCalledWith(0, 900);
dateNowMock = dataNowMockFn(); dateNowMock = dataNowMockFn();
wrapper.setProps({ targetOffset: 200 }); setProps({ targetOffset: 200 });
anchorInstance.handleScrollTo(`#${hash}`); anchorInstance!.handleScrollTo(`#${hash}`);
await sleep(30); await sleep(30);
expect(scrollToSpy).toHaveBeenLastCalledWith(0, 800); expect(scrollToSpy).toHaveBeenLastCalledWith(0, 800);
@ -401,33 +496,44 @@ describe('Anchor Render', () => {
const hash1 = getHashUrl(); const hash1 = getHashUrl();
const hash2 = getHashUrl(); const hash2 = getHashUrl();
const onChange = jest.fn(); const onChange = jest.fn();
const wrapper = mount( let anchorInstance: InternalAnchorClass;
<Anchor onChange={onChange}> render(
<Anchor
onChange={onChange}
ref={node => {
anchorInstance = node as InternalAnchorClass;
}}
>
<Link href={`#${hash1}`} title={hash1} /> <Link href={`#${hash1}`} title={hash1} />
<Link href={`#${hash2}`} title={hash2} /> <Link href={`#${hash2}`} title={hash2} />
</Anchor>, </Anchor>,
// https://github.com/testing-library/react-testing-library/releases/tag/v13.0.0
// @ts-ignore
{ legacyRoot: true },
); );
const anchorInstance = wrapper.find('Anchor').last().instance() as any as InternalAnchorClass;
expect(onChange).toHaveBeenCalledTimes(1); expect(onChange).toHaveBeenCalledTimes(1);
anchorInstance.handleScrollTo(hash2); anchorInstance!.handleScrollTo(hash2);
expect(onChange).toHaveBeenCalledTimes(2); expect(onChange).toHaveBeenCalledTimes(2);
expect(onChange).toHaveBeenCalledWith(hash2); expect(onChange).toHaveBeenCalledWith(hash2);
}); });
it('invalid hash', async () => { it('invalid hash', async () => {
const wrapper = mount( let anchorInstance: InternalAnchorClass;
<Anchor> const { container } = render(
<Anchor
ref={node => {
anchorInstance = node as InternalAnchorClass;
}}
>
<Link href="notexsited" title="title" /> <Link href="notexsited" title="title" />
</Anchor>, </Anchor>,
); );
wrapper.find(`a[href="notexsited"]`).simulate('click'); fireEvent.click(container.querySelector(`a[href="notexsited"]`)!);
const anchorInstance = wrapper.find('Anchor').last().instance() as any as InternalAnchorClass; anchorInstance!.handleScrollTo('notexsited');
expect(anchorInstance!.state).not.toBe(null);
anchorInstance.handleScrollTo('notexsited');
expect(anchorInstance.state).not.toBe(null);
}); });
it('test edge case when getBoundingClientRect return zero size', async () => { it('test edge case when getBoundingClientRect return zero size', async () => {
@ -454,27 +560,42 @@ describe('Anchor Render', () => {
const scrollToSpy = jest.spyOn(window, 'scrollTo'); const scrollToSpy = jest.spyOn(window, 'scrollTo');
const root = createDiv(); const root = createDiv();
mount(<h1 id={hash}>Hello</h1>, { attachTo: root }); render(<h1 id={hash}>Hello</h1>, { container: root });
const wrapper = mount( let anchorInstance: InternalAnchorClass;
<Anchor> const { rerender } = render(
<Anchor
ref={node => {
anchorInstance = node as InternalAnchorClass;
}}
>
<Link href={`#${hash}`} title={hash} /> <Link href={`#${hash}`} title={hash} />
</Anchor>, </Anchor>,
); );
const anchorInstance = wrapper.find('Anchor').last().instance() as any as InternalAnchorClass;
anchorInstance.handleScrollTo(`#${hash}`); const setProps = (props: Record<string, any>) =>
rerender(
<Anchor
ref={node => {
anchorInstance = node as InternalAnchorClass;
}}
{...props}
>
<Link href={`#${hash}`} title={hash} />
</Anchor>,
);
anchorInstance!.handleScrollTo(`#${hash}`);
await sleep(30); await sleep(30);
expect(scrollToSpy).toHaveBeenLastCalledWith(0, 1000); expect(scrollToSpy).toHaveBeenLastCalledWith(0, 1000);
dateNowMock = dataNowMockFn(); dateNowMock = dataNowMockFn();
wrapper.setProps({ offsetTop: 100 }); setProps({ offsetTop: 100 });
anchorInstance.handleScrollTo(`#${hash}`); anchorInstance!.handleScrollTo(`#${hash}`);
await sleep(30); await sleep(30);
expect(scrollToSpy).toHaveBeenLastCalledWith(0, 900); expect(scrollToSpy).toHaveBeenLastCalledWith(0, 900);
dateNowMock = dataNowMockFn(); dateNowMock = dataNowMockFn();
wrapper.setProps({ targetOffset: 200 }); setProps({ targetOffset: 200 });
anchorInstance.handleScrollTo(`#${hash}`); anchorInstance!.handleScrollTo(`#${hash}`);
await sleep(30); await sleep(30);
expect(scrollToSpy).toHaveBeenLastCalledWith(0, 800); expect(scrollToSpy).toHaveBeenLastCalledWith(0, 800);
@ -505,27 +626,44 @@ describe('Anchor Render', () => {
const scrollToSpy = jest.spyOn(window, 'scrollTo'); const scrollToSpy = jest.spyOn(window, 'scrollTo');
const root = createDiv(); const root = createDiv();
mount(<h1 id={hash}>Hello</h1>, { attachTo: root }); render(<h1 id={hash}>Hello</h1>, { container: root });
const wrapper = mount(
<Anchor getContainer={() => document.body}> let anchorInstance: InternalAnchorClass;
const { rerender } = render(
<Anchor
getContainer={() => document.body}
ref={node => {
anchorInstance = node as InternalAnchorClass;
}}
>
<Link href={`#${hash}`} title={hash} /> <Link href={`#${hash}`} title={hash} />
</Anchor>, </Anchor>,
); );
const anchorInstance = wrapper.find('Anchor').last().instance() as any as InternalAnchorClass;
anchorInstance.handleScrollTo(`#${hash}`); const setProps = (props: Record<string, any>) =>
rerender(
<Anchor
getContainer={() => document.body}
ref={node => {
anchorInstance = node as InternalAnchorClass;
}}
{...props}
>
<Link href={`#${hash}`} title={hash} />
</Anchor>,
);
anchorInstance!.handleScrollTo(`#${hash}`);
await sleep(30); await sleep(30);
expect(scrollToSpy).toHaveBeenLastCalledWith(0, 800); expect(scrollToSpy).toHaveBeenLastCalledWith(0, 800);
dateNowMock = dataNowMockFn(); dateNowMock = dataNowMockFn();
wrapper.setProps({ offsetTop: 100 }); setProps({ offsetTop: 100 });
anchorInstance.handleScrollTo(`#${hash}`); anchorInstance!.handleScrollTo(`#${hash}`);
await sleep(30); await sleep(30);
expect(scrollToSpy).toHaveBeenLastCalledWith(0, 800); expect(scrollToSpy).toHaveBeenLastCalledWith(0, 800);
dateNowMock = dataNowMockFn(); dateNowMock = dataNowMockFn();
setProps({ targetOffset: 200 });
wrapper.setProps({ targetOffset: 200 }); anchorInstance!.handleScrollTo(`#${hash}`);
anchorInstance.handleScrollTo(`#${hash}`);
await sleep(30); await sleep(30);
expect(scrollToSpy).toHaveBeenLastCalledWith(0, 800); expect(scrollToSpy).toHaveBeenLastCalledWith(0, 800);
@ -537,15 +675,20 @@ describe('Anchor Render', () => {
const hash1 = getHashUrl(); const hash1 = getHashUrl();
const hash2 = getHashUrl(); const hash2 = getHashUrl();
const getCurrentAnchor = () => `#${hash2}`; const getCurrentAnchor = () => `#${hash2}`;
const wrapper = mount( let anchorInstance: InternalAnchorClass;
<Anchor getCurrentAnchor={getCurrentAnchor}> render(
<Anchor
getCurrentAnchor={getCurrentAnchor}
ref={node => {
anchorInstance = node as InternalAnchorClass;
}}
>
<Link href={`#${hash1}`} title={hash1} /> <Link href={`#${hash1}`} title={hash1} />
<Link href={`#${hash2}`} title={hash2} /> <Link href={`#${hash2}`} title={hash2} />
</Anchor>, </Anchor>,
); );
const anchorInstance = wrapper.find('Anchor').last().instance() as any as InternalAnchorClass;
expect(anchorInstance.state.activeLink).toBe(`#${hash2}`); expect(anchorInstance!.state.activeLink).toBe(`#${hash2}`);
}); });
// https://github.com/ant-design/ant-design/issues/30584 // https://github.com/ant-design/ant-design/issues/30584
@ -553,16 +696,25 @@ describe('Anchor Render', () => {
const hash1 = getHashUrl(); const hash1 = getHashUrl();
const hash2 = getHashUrl(); const hash2 = getHashUrl();
const onChange = jest.fn(); const onChange = jest.fn();
const wrapper = mount( let anchorInstance: InternalAnchorClass;
<Anchor onChange={onChange} getCurrentAnchor={() => hash1}> render(
<Anchor
onChange={onChange}
getCurrentAnchor={() => hash1}
ref={node => {
anchorInstance = node as InternalAnchorClass;
}}
>
<Link href={`#${hash1}`} title={hash1} /> <Link href={`#${hash1}`} title={hash1} />
<Link href={`#${hash2}`} title={hash2} /> <Link href={`#${hash2}`} title={hash2} />
</Anchor>, </Anchor>,
// https://github.com/testing-library/react-testing-library/releases/tag/v13.0.0
// @ts-ignore
{ legacyRoot: true },
); );
const anchorInstance = wrapper.find('Anchor').last().instance() as any as InternalAnchorClass;
expect(onChange).toHaveBeenCalledTimes(1); expect(onChange).toHaveBeenCalledTimes(1);
anchorInstance.handleScrollTo(hash2); anchorInstance!.handleScrollTo(hash2);
expect(onChange).toHaveBeenCalledTimes(2); expect(onChange).toHaveBeenCalledTimes(2);
expect(onChange).toHaveBeenCalledWith(hash2); expect(onChange).toHaveBeenCalledWith(hash2);
}); });
@ -572,16 +724,16 @@ describe('Anchor Render', () => {
const hash1 = getHashUrl(); const hash1 = getHashUrl();
const hash2 = getHashUrl(); const hash2 = getHashUrl();
const getCurrentAnchor = jest.fn(); const getCurrentAnchor = jest.fn();
const wrapper = mount( const { container } = render(
<Anchor getCurrentAnchor={getCurrentAnchor}> <Anchor getCurrentAnchor={getCurrentAnchor}>
<Link href={`#${hash1}`} title={hash1} /> <Link href={`#${hash1}`} title={hash1} />
<Link href={`#${hash2}`} title={hash2} /> <Link href={`#${hash2}`} title={hash2} />
</Anchor>, </Anchor>,
); );
wrapper.find(`a[href="#${hash1}"]`).simulate('click'); fireEvent.click(container.querySelector(`a[href="#${hash1}"]`)!);
expect(getCurrentAnchor).toHaveBeenCalledWith(`#${hash1}`); expect(getCurrentAnchor).toHaveBeenCalledWith(`#${hash1}`);
wrapper.find(`a[href="#${hash2}"]`).simulate('click'); fireEvent.click(container.querySelector(`a[href="#${hash2}"]`)!);
expect(getCurrentAnchor).toHaveBeenCalledWith(`#${hash2}`); expect(getCurrentAnchor).toHaveBeenCalledWith(`#${hash2}`);
}); });
}); });

View File

@ -1,7 +1,7 @@
import React, { memo, useState, useRef, useContext } from 'react'; import React, { memo, useState, useRef, useContext } from 'react';
import { mount } from 'enzyme';
import Anchor from '../Anchor'; import Anchor from '../Anchor';
import AnchorContext from '../context'; import AnchorContext from '../context';
import { getNodeText, render, fireEvent } from '../../../tests/utils';
// we use'memo' here in order to only render inner component while context changed. // we use'memo' here in order to only render inner component while context changed.
const CacheInner = memo(() => { const CacheInner = memo(() => {
@ -38,14 +38,16 @@ const CacheOuter = () => {
}; };
it("Rendering on Anchor without changed AnchorContext won't trigger rendering on child component.", () => { it("Rendering on Anchor without changed AnchorContext won't trigger rendering on child component.", () => {
const wrapper = mount(<CacheOuter />); const { container } = render(<CacheOuter />);
const childCount = wrapper.find('#child_count').text(); const childCount = getNodeText(container.querySelector('#child_count')!);
wrapper.find('#parent_btn').at(0).simulate('click');
expect(wrapper.find('#parent_count').text()).toBe('2'); fireEvent.click(container.querySelector('#parent_btn')!);
expect(getNodeText(container.querySelector('#parent_count')!)).toBe('2');
// child component won't rerender // child component won't rerender
expect(wrapper.find('#child_count').text()).toBe(childCount); expect(getNodeText(container.querySelector('#child_count')!)).toBe(childCount);
wrapper.find('#parent_btn').at(0).simulate('click'); fireEvent.click(container.querySelector('#parent_btn')!);
expect(wrapper.find('#parent_count').text()).toBe('3'); expect(getNodeText(container.querySelector('#parent_count')!)).toBe('3');
// child component won't rerender // child component won't rerender
expect(wrapper.find('#child_count').text()).toBe(childCount); expect(getNodeText(container.querySelector('#child_count')!)).toBe(childCount);
}); });

View File

@ -30,7 +30,17 @@ export interface CarouselRef {
} }
const Carousel = React.forwardRef<CarouselRef, CarouselProps>( const Carousel = React.forwardRef<CarouselRef, CarouselProps>(
({ dots = true, arrows = false, draggable = false, dotPosition = 'bottom', ...props }, ref) => { (
{
dots = true,
arrows = false,
draggable = false,
dotPosition = 'bottom',
vertical = dotPosition === 'left' || dotPosition === 'right',
...props
},
ref,
) => {
const { getPrefixCls, direction } = React.useContext(ConfigContext); const { getPrefixCls, direction } = React.useContext(ConfigContext);
const slickRef = React.useRef<any>(); const slickRef = React.useRef<any>();
@ -60,6 +70,7 @@ const Carousel = React.forwardRef<CarouselRef, CarouselProps>(
}, [props.children]); }, [props.children]);
const newProps = { const newProps = {
vertical,
...props, ...props,
}; };
@ -69,7 +80,6 @@ const Carousel = React.forwardRef<CarouselRef, CarouselProps>(
const prefixCls = getPrefixCls('carousel', newProps.prefixCls); const prefixCls = getPrefixCls('carousel', newProps.prefixCls);
const dotsClass = 'slick-dots'; const dotsClass = 'slick-dots';
newProps.vertical = dotPosition === 'left' || dotPosition === 'right';
const enableDots = !!dots; const enableDots = !!dots;
const dsClass = classNames( const dsClass = classNames(
@ -80,7 +90,7 @@ const Carousel = React.forwardRef<CarouselRef, CarouselProps>(
const className = classNames(prefixCls, { const className = classNames(prefixCls, {
[`${prefixCls}-rtl`]: direction === 'rtl', [`${prefixCls}-rtl`]: direction === 'rtl',
[`${prefixCls}-vertical`]: newProps.vertical, [`${prefixCls}-vertical`]: dotPosition === 'left' || dotPosition === 'right',
}); });
return ( return (

View File

@ -1,5 +1,5 @@
import React from 'react'; import React from 'react';
import { mount } from 'enzyme'; import { render, fireEvent } from '../../../tests/utils';
import Checkbox from '..'; import Checkbox from '..';
import focusTest from '../../../tests/shared/focusTest'; import focusTest from '../../../tests/shared/focusTest';
import { resetWarned } from '../../_util/devWarning'; import { resetWarned } from '../../_util/devWarning';
@ -15,12 +15,14 @@ describe('Checkbox', () => {
const onMouseEnter = jest.fn(); const onMouseEnter = jest.fn();
const onMouseLeave = jest.fn(); const onMouseLeave = jest.fn();
const wrapper = mount(<Checkbox onMouseEnter={onMouseEnter} onMouseLeave={onMouseLeave} />); const { container } = render(
<Checkbox onMouseEnter={onMouseEnter} onMouseLeave={onMouseLeave} />,
);
wrapper.find('label').simulate('mouseenter'); fireEvent.mouseEnter(container.querySelector('label'));
expect(onMouseEnter).toHaveBeenCalled(); expect(onMouseEnter).toHaveBeenCalled();
wrapper.find('label').simulate('mouseleave'); fireEvent.mouseLeave(container.querySelector('label'));
expect(onMouseLeave).toHaveBeenCalled(); expect(onMouseLeave).toHaveBeenCalled();
}); });
@ -28,7 +30,7 @@ describe('Checkbox', () => {
resetWarned(); resetWarned();
const errorSpy = jest.spyOn(console, 'error').mockImplementation(() => {}); const errorSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
mount(<Checkbox value />); render(<Checkbox value />);
expect(errorSpy).toHaveBeenCalledWith( expect(errorSpy).toHaveBeenCalledWith(
'Warning: [antd: Checkbox] `value` is not a valid prop, do you mean `checked`?', 'Warning: [antd: Checkbox] `value` is not a valid prop, do you mean `checked`?',
); );

View File

@ -1,5 +1,4 @@
import React, { useState } from 'react'; import React, { useState } from 'react';
import { mount } from 'enzyme';
import Collapse from '../../collapse'; import Collapse from '../../collapse';
import Table from '../../table'; import Table from '../../table';
import Checkbox from '../index'; import Checkbox from '../index';
@ -14,16 +13,16 @@ describe('CheckboxGroup', () => {
it('should work basically', () => { it('should work basically', () => {
const onChange = jest.fn(); const onChange = jest.fn();
const wrapper = mount( const { container } = render(
<Checkbox.Group options={['Apple', 'Pear', 'Orange']} onChange={onChange} />, <Checkbox.Group options={['Apple', 'Pear', 'Orange']} onChange={onChange} />,
); );
wrapper.find('.ant-checkbox-input').at(0).simulate('change'); fireEvent.click(container.querySelectorAll('.ant-checkbox-input')[0]);
expect(onChange).toHaveBeenCalledWith(['Apple']); expect(onChange).toHaveBeenCalledWith(['Apple']);
wrapper.find('.ant-checkbox-input').at(1).simulate('change'); fireEvent.click(container.querySelectorAll('.ant-checkbox-input')[1]);
expect(onChange).toHaveBeenCalledWith(['Apple', 'Pear']); expect(onChange).toHaveBeenCalledWith(['Apple', 'Pear']);
wrapper.find('.ant-checkbox-input').at(2).simulate('change'); fireEvent.click(container.querySelectorAll('.ant-checkbox-input')[2]);
expect(onChange).toHaveBeenCalledWith(['Apple', 'Pear', 'Orange']); expect(onChange).toHaveBeenCalledWith(['Apple', 'Pear', 'Orange']);
wrapper.find('.ant-checkbox-input').at(1).simulate('change'); fireEvent.click(container.querySelectorAll('.ant-checkbox-input')[1]);
expect(onChange).toHaveBeenCalledWith(['Apple', 'Orange']); expect(onChange).toHaveBeenCalledWith(['Apple', 'Orange']);
}); });
@ -35,12 +34,12 @@ describe('CheckboxGroup', () => {
{ label: 'Pear', value: 'Pear' }, { label: 'Pear', value: 'Pear' },
]; ];
const groupWrapper = mount( const { container } = render(
<Checkbox.Group options={options} onChange={onChangeGroup} disabled />, <Checkbox.Group options={options} onChange={onChangeGroup} disabled />,
); );
groupWrapper.find('.ant-checkbox-input').at(0).simulate('change'); fireEvent.click(container.querySelectorAll('.ant-checkbox-input')[0]);
expect(onChangeGroup).not.toHaveBeenCalled(); expect(onChangeGroup).not.toHaveBeenCalled();
groupWrapper.find('.ant-checkbox-input').at(1).simulate('change'); fireEvent.click(container.querySelectorAll('.ant-checkbox-input')[1]);
expect(onChangeGroup).not.toHaveBeenCalled(); expect(onChangeGroup).not.toHaveBeenCalled();
}); });
@ -52,17 +51,17 @@ describe('CheckboxGroup', () => {
{ label: 'Orange', value: 'Orange', disabled: true }, { label: 'Orange', value: 'Orange', disabled: true },
]; ];
const groupWrapper = mount(<Checkbox.Group options={options} onChange={onChangeGroup} />); const { container } = render(<Checkbox.Group options={options} onChange={onChangeGroup} />);
groupWrapper.find('.ant-checkbox-input').at(0).simulate('change'); fireEvent.click(container.querySelectorAll('.ant-checkbox-input')[0]);
expect(onChangeGroup).toHaveBeenCalledWith(['Apple']); expect(onChangeGroup).toHaveBeenCalledWith(['Apple']);
groupWrapper.find('.ant-checkbox-input').at(1).simulate('change'); fireEvent.click(container.querySelectorAll('.ant-checkbox-input')[1]);
expect(onChangeGroup).toHaveBeenCalledWith(['Apple']); expect(onChangeGroup).toHaveBeenCalledWith(['Apple']);
}); });
it('all children should have a name property', () => { it('all children should have a name property', () => {
const wrapper = mount(<Checkbox.Group name="checkboxgroup" options={['Yes', 'No']} />); const { container } = render(<Checkbox.Group name="checkboxgroup" options={['Yes', 'No']} />);
wrapper.find('input[type="checkbox"]').forEach(el => { [...container.querySelectorAll('input[type="checkbox"]')].forEach(el => {
expect(el.props().name).toEqual('checkboxgroup'); expect(el.getAttribute('name')).toEqual('checkboxgroup');
}); });
}); });
@ -72,9 +71,9 @@ describe('CheckboxGroup', () => {
{ label: 'Orange', value: 'Orange', style: { fontSize: 12 } }, { label: 'Orange', value: 'Orange', style: { fontSize: 12 } },
]; ];
const wrapper = mount(<Checkbox.Group prefixCls="my-checkbox" options={options} />); const { container } = render(<Checkbox.Group prefixCls="my-checkbox" options={options} />);
expect(wrapper.render()).toMatchSnapshot(); expect(container.firstChild).toMatchSnapshot();
}); });
it('should be controlled by value', () => { it('should be controlled by value', () => {
@ -82,23 +81,22 @@ describe('CheckboxGroup', () => {
{ label: 'Apple', value: 'Apple' }, { label: 'Apple', value: 'Apple' },
{ label: 'Orange', value: 'Orange' }, { label: 'Orange', value: 'Orange' },
]; ];
const renderCheckbox = props => <Checkbox.Group {...props} />;
const wrapper = mount(<Checkbox.Group options={options} />); const { container, rerender } = render(renderCheckbox({ options }));
expect(wrapper.find('.ant-checkbox-checked').length).toBe(0); expect(container.querySelectorAll('.ant-checkbox-checked').length).toBe(0);
wrapper.setProps({ value: ['Apple'] }); rerender(renderCheckbox({ options, value: 'Apple' }));
wrapper.update(); expect(container.querySelectorAll('.ant-checkbox-checked').length).toBe(1);
expect(wrapper.find('.ant-checkbox-checked').length).toBe(1);
}); });
// https://github.com/ant-design/ant-design/issues/12642 // https://github.com/ant-design/ant-design/issues/12642
it('should trigger onChange in sub Checkbox', () => { it('should trigger onChange in sub Checkbox', () => {
const onChange = jest.fn(); const onChange = jest.fn();
const wrapper = mount( const { container } = render(
<Checkbox.Group> <Checkbox.Group>
<Checkbox value="my" onChange={onChange} /> <Checkbox value="my" onChange={onChange} />
</Checkbox.Group>, </Checkbox.Group>,
); );
wrapper.find('.ant-checkbox-input').at(0).simulate('change'); fireEvent.click(container.querySelectorAll('.ant-checkbox-input')[0]);
expect(onChange).toHaveBeenCalled(); expect(onChange).toHaveBeenCalled();
expect(onChange.mock.calls[0][0].target.value).toEqual('my'); expect(onChange.mock.calls[0][0].target.value).toEqual('my');
}); });
@ -143,7 +141,7 @@ describe('CheckboxGroup', () => {
// https://github.com/ant-design/ant-design/issues/17297 // https://github.com/ant-design/ant-design/issues/17297
it('onChange should keep the order of the original values', () => { it('onChange should keep the order of the original values', () => {
const onChange = jest.fn(); const onChange = jest.fn();
const wrapper = mount( const { container } = render(
<Checkbox.Group onChange={onChange}> <Checkbox.Group onChange={onChange}>
<Checkbox key={1} value={1} /> <Checkbox key={1} value={1} />
<Checkbox key={2} value={2} /> <Checkbox key={2} value={2} />
@ -151,20 +149,19 @@ describe('CheckboxGroup', () => {
<Checkbox key={4} value={4} /> <Checkbox key={4} value={4} />
</Checkbox.Group>, </Checkbox.Group>,
); );
fireEvent.click(container.querySelectorAll('.ant-checkbox-input')[0]);
wrapper.find('.ant-checkbox-input').at(0).simulate('change');
expect(onChange).toHaveBeenCalledWith([1]); expect(onChange).toHaveBeenCalledWith([1]);
wrapper.find('.ant-checkbox-input').at(1).simulate('change'); fireEvent.click(container.querySelectorAll('.ant-checkbox-input')[1]);
expect(onChange).toHaveBeenCalledWith([1, 2]); expect(onChange).toHaveBeenCalledWith([1, 2]);
wrapper.find('.ant-checkbox-input').at(0).simulate('change'); fireEvent.click(container.querySelectorAll('.ant-checkbox-input')[0]);
expect(onChange).toHaveBeenCalledWith([2]); expect(onChange).toHaveBeenCalledWith([2]);
wrapper.find('.ant-checkbox-input').at(0).simulate('change'); fireEvent.click(container.querySelectorAll('.ant-checkbox-input')[0]);
expect(onChange).toHaveBeenCalledWith([1, 2]); expect(onChange).toHaveBeenCalledWith([1, 2]);
}); });
// https://github.com/ant-design/ant-design/issues/21134 // https://github.com/ant-design/ant-design/issues/21134
it('should work when checkbox is wrapped by other components', () => { it('should work when checkbox is wrapped by other components', () => {
const wrapper = mount( const { container } = render(
<Checkbox.Group> <Checkbox.Group>
<Collapse bordered={false}> <Collapse bordered={false}>
<Collapse.Panel header="test panel"> <Collapse.Panel header="test panel">
@ -175,28 +172,31 @@ describe('CheckboxGroup', () => {
</Collapse> </Collapse>
</Checkbox.Group>, </Checkbox.Group>,
); );
wrapper.find('.ant-collapse-item').at(0).find('.ant-collapse-header').simulate('click');
wrapper.find('.ant-checkbox-input').at(0).simulate('change'); fireEvent.click(
expect(wrapper.find('.ant-checkbox-checked').length).toBe(1); container.querySelector('.ant-collapse-item').querySelector('.ant-collapse-header'),
wrapper.find('.ant-checkbox-input').at(0).simulate('change'); );
expect(wrapper.find('.ant-checkbox-checked').length).toBe(0); fireEvent.click(container.querySelector('.ant-checkbox-input'));
expect(container.querySelectorAll('.ant-checkbox-checked').length).toBe(1);
fireEvent.click(container.querySelector('.ant-checkbox-input'));
expect(container.querySelectorAll('.ant-checkbox-checked').length).toBe(0);
}); });
it('skipGroup', () => { it('skipGroup', () => {
const onChange = jest.fn(); const onChange = jest.fn();
const wrapper = mount( const { container } = render(
<Checkbox.Group onChange={onChange}> <Checkbox.Group onChange={onChange}>
<Checkbox value={1} /> <Checkbox value={1} />
<Checkbox value={2} skipGroup /> <Checkbox value={2} skipGroup />
</Checkbox.Group>, </Checkbox.Group>,
); );
wrapper.find('.ant-checkbox-input').at(1).simulate('change'); fireEvent.click(container.querySelectorAll('.ant-checkbox-input')[1]);
expect(onChange).not.toHaveBeenCalled(); expect(onChange).not.toHaveBeenCalled();
}); });
it('Table rowSelection', () => { it('Table rowSelection', () => {
const onChange = jest.fn(); const onChange = jest.fn();
const wrapper = mount( const { container } = render(
<Checkbox.Group onChange={onChange}> <Checkbox.Group onChange={onChange}>
<Table <Table
dataSource={[{ key: 1, value: '1' }]} dataSource={[{ key: 1, value: '1' }]}
@ -205,27 +205,32 @@ describe('CheckboxGroup', () => {
/> />
</Checkbox.Group>, </Checkbox.Group>,
); );
wrapper.find('.ant-checkbox-input').at(1).simulate('change'); fireEvent.click(container.querySelectorAll('.ant-checkbox-input')[1]);
expect(onChange).not.toHaveBeenCalled(); expect(onChange).not.toHaveBeenCalled();
}); });
it('should get div ref', () => { it('should get div ref', () => {
mount( const refCalls = [];
render(
<Checkbox.Group <Checkbox.Group
options={['Apple', 'Pear', 'Orange']} options={['Apple', 'Pear', 'Orange']}
ref={node => { ref={node => {
expect(node.nodeName).toBe('DIV'); refCalls.push(node);
}} }}
/>, />,
); );
const [mountCall] = refCalls;
expect(mountCall.nodeName).toBe('DIV');
}); });
it('should support number option', () => { it('should support number option', () => {
const onChange = jest.fn(); const onChange = jest.fn();
const wrapper = mount(<Checkbox.Group options={[1, 'Pear', 'Orange']} onChange={onChange} />); const { container } = render(
<Checkbox.Group options={[1, 'Pear', 'Orange']} onChange={onChange} />,
);
wrapper.find('.ant-checkbox-input').at(0).simulate('change'); fireEvent.click(container.querySelector('.ant-checkbox-input'));
expect(onChange).toHaveBeenCalledWith([1]); expect(onChange).toHaveBeenCalledWith([1]);
}); });
@ -251,17 +256,13 @@ describe('CheckboxGroup', () => {
); );
}; };
const wrapper = mount(<Demo />); const { container } = render(<Demo />);
fireEvent.click(container.querySelector('.ant-checkbox-input'));
wrapper.find('.ant-checkbox-input').first().simulate('change');
expect(onChange).toHaveBeenCalledWith([]); expect(onChange).toHaveBeenCalledWith([]);
wrapper.find('.ant-checkbox-input').first().simulate('change'); fireEvent.click(container.querySelector('.ant-checkbox-input'));
expect(onChange).toHaveBeenCalledWith(['length1']); expect(onChange).toHaveBeenCalledWith(['length1']);
wrapper fireEvent.change(container.querySelector('.ant-input'), { target: { value: '' } });
.find('.ant-input') fireEvent.click(container.querySelector('.ant-checkbox-input'));
.first()
.simulate('change', { target: { value: '' } });
wrapper.find('.ant-checkbox-input').first().simulate('change');
expect(onChange).toHaveBeenCalledWith(['A']); expect(onChange).toHaveBeenCalledWith(['A']);
}); });
}); });

View File

@ -1,5 +1,6 @@
import React, { useState } from 'react'; import React, { useState } from 'react';
import { mount } from 'enzyme'; import { mount } from 'enzyme';
import { createPortal } from 'react-dom';
import { render, fireEvent } from '../../../tests/utils'; import { render, fireEvent } from '../../../tests/utils';
// eslint-disable-next-line import/no-unresolved // eslint-disable-next-line import/no-unresolved
import Form from '../../form'; import Form from '../../form';
@ -75,6 +76,40 @@ describe('Input', () => {
}); });
}); });
describe('click focus', () => {
it('click outside should also get focus', () => {
const { container } = render(<Input suffix={<span className="test-suffix" />} />);
const onFocus = jest.spyOn(container.querySelector('input')!, 'focus');
fireEvent.mouseDown(container.querySelector('.test-suffix')!);
fireEvent.mouseUp(container.querySelector('.test-suffix')!);
expect(onFocus).toHaveBeenCalled();
});
it('not get focus if out of component', () => {
const holder = document.createElement('span');
document.body.appendChild(holder);
const Popup = () => createPortal(<span className="popup" />, holder);
const { container } = render(
<Input
suffix={
<span className="test-suffix">
<Popup />
</span>
}
/>,
);
const onFocus = jest.spyOn(container.querySelector('input')!, 'focus');
fireEvent.mouseDown(document.querySelector('.popup')!);
fireEvent.mouseUp(document.querySelector('.popup')!);
expect(onFocus).not.toHaveBeenCalled();
document.body.removeChild(holder);
});
});
it('set mouse cursor position', () => { it('set mouse cursor position', () => {
const defaultValue = '11111'; const defaultValue = '11111';
const valLength = defaultValue.length; const valLength = defaultValue.length;

View File

@ -404,27 +404,6 @@ describe('TextArea allowClear', () => {
expect(wrapper.find('input').props().value).toEqual('Light'); expect(wrapper.find('input').props().value).toEqual('Light');
}); });
describe('click focus', () => {
it('click outside should also get focus', () => {
const wrapper = mount(<Input suffix={<span className="test-suffix" />} />);
const onFocus = jest.spyOn(wrapper.find('input').instance(), 'focus');
wrapper.find('.test-suffix').simulate('mouseUp');
expect(onFocus).toHaveBeenCalled();
});
it('not get focus if out of component', () => {
const wrapper = mount(<Input suffix={<span className="test-suffix" />} />);
const onFocus = jest.spyOn(wrapper.find('input').instance(), 'focus');
const ele = document.createElement('span');
document.body.appendChild(ele);
wrapper.find('.test-suffix').simulate('mouseUp', {
target: ele,
});
expect(onFocus).not.toHaveBeenCalled();
document.body.removeChild(ele);
});
});
it('scroll to bottom when autoSize', async () => { it('scroll to bottom when autoSize', async () => {
const wrapper = mount(<Input.TextArea autoSize />, { attachTo: document.body }); const wrapper = mount(<Input.TextArea autoSize />, { attachTo: document.body });
wrapper.find('textarea').simulate('focus'); wrapper.find('textarea').simulate('focus');

View File

@ -206,6 +206,7 @@ export interface ArgsProps {
duration?: number | null; duration?: number | null;
icon?: React.ReactNode; icon?: React.ReactNode;
placement?: NotificationPlacement; placement?: NotificationPlacement;
maxCount?: number;
style?: React.CSSProperties; style?: React.CSSProperties;
prefixCls?: string; prefixCls?: string;
className?: string; className?: string;

View File

@ -12,7 +12,7 @@
padding: @segmented-container-padding; padding: @segmented-container-padding;
color: @segmented-label-color; color: @segmented-label-color;
background-color: @segmented-bg; background-color: @segmented-bg;
border-radius: 2px; border-radius: @border-radius-base;
transition: all 0.3s @ease-in-out; transition: all 0.3s @ease-in-out;
&-group { &-group {
@ -67,7 +67,7 @@
// syntactic sugar to add `icon` for Segmented Item // syntactic sugar to add `icon` for Segmented Item
&-icon + * { &-icon + * {
margin-left: 6px; margin-left: @margin-sm / 2;
} }
&-input { &-input {

View File

@ -29,7 +29,7 @@ exports[`Space should render correct with children 1`] = `
`; `;
exports[`Space should render width ConfigProvider 1`] = ` exports[`Space should render width ConfigProvider 1`] = `
Array [ HTMLCollection [
<div <div
class="ant-space ant-space-horizontal ant-space-align-center" class="ant-space ant-space-horizontal ant-space-align-center"
> >
@ -91,7 +91,7 @@ Array [
`; `;
exports[`Space should render width rtl 1`] = ` exports[`Space should render width rtl 1`] = `
Array [ HTMLCollection [
<div <div
class="ant-space ant-space-horizontal ant-space-rtl ant-space-align-center" class="ant-space ant-space-horizontal ant-space-rtl ant-space-align-center"
> >

View File

@ -1,5 +1,5 @@
import React from 'react'; import React from 'react';
import { mount } from 'enzyme'; import { render } from '../../../tests/utils';
import Space from '..'; import Space from '..';
// eslint-disable-next-line no-unused-vars // eslint-disable-next-line no-unused-vars
import * as styleChecker from '../../_util/styleChecker'; import * as styleChecker from '../../_util/styleChecker';
@ -12,13 +12,13 @@ jest.mock('../../_util/styleChecker', () => ({
describe('flex gap', () => { describe('flex gap', () => {
it('should render width empty children', () => { it('should render width empty children', () => {
const wrapper = mount( const { container } = render(
<Space> <Space>
<span /> <span />
<span /> <span />
</Space>, </Space>,
); );
expect(wrapper.getDOMNode().style['column-gap']).toBe('8px'); expect(container.querySelector('div.ant-space').style['column-gap']).toBe('8px');
expect(wrapper.getDOMNode().style['row-gap']).toBe('8px'); expect(container.querySelector('div.ant-space').style['row-gap']).toBe('8px');
}); });
}); });

View File

@ -1,6 +1,5 @@
import React, { useState } from 'react'; import React, { useState } from 'react';
import { mount } from 'enzyme'; import { render, fireEvent } from '../../../tests/utils';
import { act } from 'react-dom/test-utils';
import Space from '..'; import Space from '..';
import ConfigProvider from '../../config-provider'; import ConfigProvider from '../../config-provider';
import mountTest from '../../../tests/shared/mountTest'; import mountTest from '../../../tests/shared/mountTest';
@ -11,13 +10,13 @@ describe('Space', () => {
rtlTest(Space); rtlTest(Space);
it('should render width empty children', () => { it('should render width empty children', () => {
const wrapper = mount(<Space />); const { container } = render(<Space />);
expect(wrapper.instance()).toBe(null); expect(container.children.length).toBe(0);
}); });
it('should render width ConfigProvider', () => { it('should render width ConfigProvider', () => {
const wrapper = mount( const { container } = render(
<ConfigProvider space={{ size: 'large' }}> <ConfigProvider space={{ size: 'large' }}>
<Space> <Space>
<span>1</span> <span>1</span>
@ -34,11 +33,11 @@ describe('Space', () => {
</ConfigProvider>, </ConfigProvider>,
); );
expect(wrapper.render()).toMatchSnapshot(); expect(container.children).toMatchSnapshot();
}); });
it('should render width rtl', () => { it('should render width rtl', () => {
const wrapper = mount( const { container } = render(
<ConfigProvider direction="rtl"> <ConfigProvider direction="rtl">
<Space> <Space>
<span>1</span> <span>1</span>
@ -55,46 +54,46 @@ describe('Space', () => {
</ConfigProvider>, </ConfigProvider>,
); );
expect(wrapper.render()).toMatchSnapshot(); expect(container.children).toMatchSnapshot();
}); });
it('should render width customize size', () => { it('should render width customize size', () => {
const wrapper = mount( const { container } = render(
<Space size={10}> <Space size={10}>
<span>1</span> <span>1</span>
<span>2</span> <span>2</span>
</Space>, </Space>,
); );
expect(wrapper.find('div.ant-space-item').at(0).prop('style').marginRight).toBe(10); expect(container.querySelector('div.ant-space-item').style.marginRight).toBe('10px');
expect(wrapper.find('div.ant-space-item').at(1).prop('style').marginRight).toBeUndefined(); expect(container.querySelectorAll('div.ant-space-item')[1].style.marginRight).toBe('');
}); });
it('should render width size 0', () => { it('should render width size 0', () => {
const wrapper = mount( const { container } = render(
<Space size={NaN}> <Space size={NaN}>
<span>1</span> <span>1</span>
<span>2</span> <span>2</span>
</Space>, </Space>,
); );
expect(wrapper.find('div.ant-space-item').at(0).prop('style').marginRight).toBe(0); expect(container.querySelector('div.ant-space-item').style.marginRight).toBe('0px');
}); });
it('should render vertical space width customize size', () => { it('should render vertical space width customize size', () => {
const wrapper = mount( const { container } = render(
<Space size={10} direction="vertical"> <Space size={10} direction="vertical">
<span>1</span> <span>1</span>
<span>2</span> <span>2</span>
</Space>, </Space>,
); );
expect(wrapper.find('div.ant-space-item').at(0).prop('style').marginBottom).toBe(10); expect(container.querySelector('div.ant-space-item').style.marginBottom).toBe('10px');
expect(wrapper.find('div.ant-space-item').at(1).prop('style').marginBottom).toBeUndefined(); expect(container.querySelectorAll('div.ant-space-item')[1].style.marginBottom).toBe('');
}); });
it('should render correct with children', () => { it('should render correct with children', () => {
const wrapper = mount( const { container } = render(
<Space> <Space>
text1<span>text1</span> text1<span>text1</span>
{/* eslint-disable-next-line react/jsx-no-useless-fragment */} {/* eslint-disable-next-line react/jsx-no-useless-fragment */}
@ -102,18 +101,18 @@ describe('Space', () => {
</Space>, </Space>,
); );
expect(wrapper.render()).toMatchSnapshot(); expect(container.children[0]).toMatchSnapshot();
}); });
it('should render with invalidElement', () => { it('should render with invalidElement', () => {
const wrapper = mount( const { container } = render(
<Space> <Space>
text1<span>text1</span> text1<span>text1</span>
text1 text1
</Space>, </Space>,
); );
expect(wrapper.find('div.ant-space-item').length).toBe(3); expect(container.querySelectorAll('div.ant-space-item').length).toBe(3);
}); });
it('should be keep store', () => { it('should be keep store', () => {
@ -144,25 +143,21 @@ describe('Space', () => {
</Space> </Space>
); );
} }
const wrapper = mount(<SpaceDemo />); const { container } = render(<SpaceDemo />);
expect(wrapper.find('#demo').text()).toBe('1'); expect(container.querySelector('#demo')).toHaveTextContent('1');
act(() => { fireEvent.click(container.querySelector('#demo'));
wrapper.find('#demo').simulate('click');
});
expect(wrapper.find('#demo').text()).toBe('2'); expect(container.querySelector('#demo')).toHaveTextContent('2');
act(() => { fireEvent.click(container.querySelector('p'));
wrapper.find('p').simulate('click');
});
expect(wrapper.find('#demo').text()).toBe('2'); expect(container.querySelector('#demo')).toHaveTextContent('2');
}); });
it('split', () => { it('split', () => {
const wrapper = mount( const { container } = render(
<Space split="-"> <Space split="-">
text1<span>text1</span> text1<span>text1</span>
{/* eslint-disable-next-line react/jsx-no-useless-fragment */} {/* eslint-disable-next-line react/jsx-no-useless-fragment */}
@ -170,13 +165,13 @@ describe('Space', () => {
</Space>, </Space>,
); );
expect(wrapper.render()).toMatchSnapshot(); expect(container.children[0]).toMatchSnapshot();
}); });
// https://github.com/ant-design/ant-design/issues/35305 // https://github.com/ant-design/ant-design/issues/35305
it('should not throw duplicated key warning', () => { it('should not throw duplicated key warning', () => {
jest.spyOn(console, 'error').mockImplementation(() => undefined); jest.spyOn(console, 'error').mockImplementation(() => undefined);
mount( render(
<Space> <Space>
<div key="1" /> <div key="1" />
<div /> <div />

View File

@ -88,15 +88,12 @@ const Space: React.FC<SpaceProps> = props => {
latestIndex = i; latestIndex = i;
} }
const keyOfChild = child && child.key; const key = child && child.key || `${itemClassName}-${i}`;
// Add `-space-item` as suffix in case simple key string trigger duplicated key warning
// https://github.com/ant-design/ant-design/issues/35305
const defaultKey = `${i}-space-item`;
return ( return (
<Item <Item
className={itemClassName} className={itemClassName}
key={`${itemClassName}-${keyOfChild || defaultKey}`} key={key}
direction={direction} direction={direction}
index={i} index={i}
marginDirection={marginDirection} marginDirection={marginDirection}

View File

@ -2305,4 +2305,53 @@ describe('Table.filter', () => {
); );
expect(errorSpy).not.toBeCalled(); expect(errorSpy).not.toBeCalled();
}); });
it('can reset if filterResetToDefaultFilteredValue and filter is changing', () => {
const wrapper = mount(
createTable({
columns: [
{
...column,
filters: [
{ text: 'Jack', value: 'Jack' },
{ text: 'Lucy', value: 'Lucy' },
],
defaultFilteredValue: ['Jack'],
filterResetToDefaultFilteredValue: true,
},
],
}),
);
expect(wrapper.find('tbody tr').length).toBe(1);
expect(wrapper.find('tbody tr').text()).toBe('Jack');
// open filter
wrapper.find('span.ant-dropdown-trigger').first().simulate('click');
expect(
wrapper.find('.ant-table-filter-dropdown-btns .ant-btn-link').props().disabled,
).toBeTruthy();
expect(wrapper.find('li.ant-dropdown-menu-item').at(0).text()).toBe('Jack');
expect(wrapper.find('li.ant-dropdown-menu-item').at(1).text()).toBe('Lucy');
// deselect default
wrapper.find('li.ant-dropdown-menu-item').at(0).simulate('click');
expect(
wrapper.find('.ant-table-filter-dropdown-btns .ant-btn-link').props().disabled,
).toBeFalsy();
// select other one
wrapper.find('li.ant-dropdown-menu-item').at(1).simulate('click');
expect(
wrapper.find('.ant-table-filter-dropdown-btns .ant-btn-link').props().disabled,
).toBeFalsy();
// deselect other one
wrapper.find('li.ant-dropdown-menu-item').at(1).simulate('click');
expect(
wrapper.find('.ant-table-filter-dropdown-btns .ant-btn-link').props().disabled,
).toBeFalsy();
// select default
wrapper.find('li.ant-dropdown-menu-item').at(0).simulate('click');
expect(
wrapper.find('.ant-table-filter-dropdown-btns .ant-btn-link').props().disabled,
).toBeTruthy();
});
}); });

View File

@ -407,16 +407,22 @@ function FilterDropdown<RecordType>(props: FilterDropdownProps<RecordType>) {
); );
}; };
const getResetDisabled = () => {
if (filterResetToDefaultFilteredValue) {
return isEqual(
(defaultFilteredValue || []).map(key => String(key)),
selectedKeys,
);
}
return selectedKeys.length === 0;
};
dropdownContent = ( dropdownContent = (
<> <>
{getFilterComponent()} {getFilterComponent()}
<div className={`${prefixCls}-dropdown-btns`}> <div className={`${prefixCls}-dropdown-btns`}>
<Button <Button type="link" size="small" disabled={getResetDisabled()} onClick={() => onReset()}>
type="link"
size="small"
disabled={selectedKeys.length === 0}
onClick={() => onReset()}
>
{locale.filterReset} {locale.filterReset}
</Button> </Button>
<Button type="primary" size="small" onClick={onConfirm}> <Button type="primary" size="small" onClick={onConfirm}>

View File

@ -26,7 +26,7 @@ describe('Tooltip', () => {
const onVisibleChange = jest.fn(); const onVisibleChange = jest.fn();
const ref = React.createRef(); const ref = React.createRef();
const wrapper = mount( const { container, rerender } = render(
<Tooltip <Tooltip
title="" title=""
mouseEnterDelay={0} mouseEnterDelay={0}
@ -39,34 +39,55 @@ describe('Tooltip', () => {
); );
// `title` is empty. // `title` is empty.
const div = wrapper.find('#hello').at(0); const divElement = container.querySelector('#hello');
div.simulate('mouseenter'); fireEvent.mouseEnter(divElement);
expect(onVisibleChange).not.toHaveBeenCalled(); expect(onVisibleChange).not.toHaveBeenCalled();
expect(ref.current.props.visible).toBe(false); expect(ref.current.props.visible).toBe(false);
div.simulate('mouseleave'); fireEvent.mouseLeave(divElement);
expect(onVisibleChange).not.toHaveBeenCalled(); expect(onVisibleChange).not.toHaveBeenCalled();
expect(ref.current.props.visible).toBe(false); expect(ref.current.props.visible).toBe(false);
// update `title` value. // update `title` value.
wrapper.setProps({ title: 'Have a nice day!' }); rerender(
wrapper.find('#hello').simulate('mouseenter'); <Tooltip
title="Have a nice day!"
mouseEnterDelay={0}
mouseLeaveDelay={0}
onVisibleChange={onVisibleChange}
ref={ref}
>
<div id="hello">Hello world!</div>
</Tooltip>,
);
fireEvent.mouseEnter(divElement);
expect(onVisibleChange).toHaveBeenLastCalledWith(true); expect(onVisibleChange).toHaveBeenLastCalledWith(true);
expect(ref.current.props.visible).toBe(true); expect(ref.current.props.visible).toBe(true);
wrapper.find('#hello').simulate('mouseleave'); fireEvent.mouseLeave(divElement);
expect(onVisibleChange).toHaveBeenLastCalledWith(false); expect(onVisibleChange).toHaveBeenLastCalledWith(false);
expect(ref.current.props.visible).toBe(false); expect(ref.current.props.visible).toBe(false);
// add `visible` props. // add `visible` props.
wrapper.setProps({ visible: false }); rerender(
wrapper.find('#hello').simulate('mouseenter'); <Tooltip
title="Have a nice day!"
mouseEnterDelay={0}
mouseLeaveDelay={0}
onVisibleChange={onVisibleChange}
ref={ref}
visible={false}
>
<div id="hello">Hello world!</div>
</Tooltip>,
);
fireEvent.mouseEnter(divElement);
expect(onVisibleChange).toHaveBeenLastCalledWith(true); expect(onVisibleChange).toHaveBeenLastCalledWith(true);
const lastCount = onVisibleChange.mock.calls.length; const lastCount = onVisibleChange.mock.calls.length;
expect(ref.current.props.visible).toBe(false); expect(ref.current.props.visible).toBe(false);
// always trigger onVisibleChange // always trigger onVisibleChange
wrapper.simulate('mouseleave'); fireEvent.mouseLeave(divElement);
expect(onVisibleChange.mock.calls.length).toBe(lastCount); // no change with lastCount expect(onVisibleChange.mock.calls.length).toBe(lastCount); // no change with lastCount
expect(ref.current.props.visible).toBe(false); expect(ref.current.props.visible).toBe(false);
}); });

View File

@ -25,7 +25,7 @@ class ComponentDoc extends React.Component {
expandAll: false, expandAll: false,
visibleAll: process.env.NODE_ENV !== 'production', visibleAll: process.env.NODE_ENV !== 'production',
showRiddleButton: false, showRiddleButton: false,
react18Demo: true, react17Demo: false,
}; };
componentDidMount() { componentDidMount() {
@ -49,12 +49,12 @@ class ComponentDoc extends React.Component {
shouldComponentUpdate(nextProps, nextState) { shouldComponentUpdate(nextProps, nextState) {
const { location, theme } = this.props; const { location, theme } = this.props;
const { location: nextLocation, theme: nextTheme } = nextProps; const { location: nextLocation, theme: nextTheme } = nextProps;
const { expandAll, visibleAll, showRiddleButton, react18Demo } = this.state; const { expandAll, visibleAll, showRiddleButton, react17Demo } = this.state;
const { const {
expandAll: nextExpandAll, expandAll: nextExpandAll,
visibleAll: nextVisibleAll, visibleAll: nextVisibleAll,
showRiddleButton: nextShowRiddleButton, showRiddleButton: nextShowRiddleButton,
react18Demo: nextReact18Demo, react17Demo: nextReact17Demo,
} = nextState; } = nextState;
if ( if (
@ -64,7 +64,7 @@ class ComponentDoc extends React.Component {
theme === nextTheme && theme === nextTheme &&
visibleAll === nextVisibleAll && visibleAll === nextVisibleAll &&
showRiddleButton === nextShowRiddleButton && showRiddleButton === nextShowRiddleButton &&
react18Demo === nextReact18Demo react17Demo === nextReact17Demo
) { ) {
return false; return false;
} }
@ -90,9 +90,9 @@ class ComponentDoc extends React.Component {
}; };
handleDemoVersionToggle = () => { handleDemoVersionToggle = () => {
const { react18Demo } = this.state; const { react17Demo } = this.state;
this.setState({ this.setState({
react18Demo: !react18Demo, react17Demo: !react17Demo,
}); });
}; };
@ -108,7 +108,7 @@ class ComponentDoc extends React.Component {
} = this.props; } = this.props;
const { content, meta } = doc; const { content, meta } = doc;
const demoValues = Object.keys(demos).map(key => demos[key]); const demoValues = Object.keys(demos).map(key => demos[key]);
const { expandAll, visibleAll, showRiddleButton, react18Demo } = this.state; const { expandAll, visibleAll, showRiddleButton, react17Demo } = this.state;
const isSingleCol = meta.cols === 1; const isSingleCol = meta.cols === 1;
const leftChildren = []; const leftChildren = [];
const rightChildren = []; const rightChildren = [];
@ -131,7 +131,7 @@ class ComponentDoc extends React.Component {
location={location} location={location}
theme={theme} theme={theme}
setIframeTheme={setIframeTheme} setIframeTheme={setIframeTheme}
react18={react18Demo} react18={react17Demo}
/> />
); );
if (index % 2 === 0 || isSingleCol) { if (index % 2 === 0 || isSingleCol) {
@ -224,12 +224,12 @@ class ComponentDoc extends React.Component {
title={ title={
<FormattedMessage <FormattedMessage
id={`app.component.examples.${ id={`app.component.examples.${
react18Demo ? 'openDemoNotReact18' : 'openDemoWithReact18' react17Demo ? 'openDemoWithReact18' : 'openDemoNotReact18'
}`} }`}
/> />
} }
> >
{react18Demo ? ( {react17Demo ? (
<ExperimentFilled <ExperimentFilled
className={expandTriggerClass} className={expandTriggerClass}
onClick={this.handleDemoVersionToggle} onClick={this.handleDemoVersionToggle}