mirror of
https://github.com/zhigang1992/react.git
synced 2026-01-31 17:18:40 +08:00
Merge pull request #160 from unix/test
test(shared): add testcases for shared components
This commit is contained in:
148
components/shared/__tests__/__snapshots__/backdrop.test.tsx.snap
Normal file
148
components/shared/__tests__/__snapshots__/backdrop.test.tsx.snap
Normal file
@@ -0,0 +1,148 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Backdrop content should be offset 1`] = `
|
||||
"<div class=\\"backdrop transition-enter\\"><div class=\\"layer\\"></div><div class=\\"content\\"><span>test-value</span></div><div class=\\"offset\\"></div><style>
|
||||
.backdrop {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
display: flex;
|
||||
align-content: center;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
height: 100vh;
|
||||
width: 100vw;
|
||||
overflow: auto;
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
.content {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
position: relative;
|
||||
z-index: 1001;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.offset {
|
||||
height: 0vh;
|
||||
opacity: 0;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.layer {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
opacity: 0.25;
|
||||
background-color: black;
|
||||
transition: opacity .35s cubic-bezier(.4, 0, .2, 1);
|
||||
pointer-events: none;
|
||||
z-index: 1000;
|
||||
}
|
||||
</style></div>"
|
||||
`;
|
||||
|
||||
exports[`Backdrop content should be offset 2`] = `
|
||||
"<div class=\\"backdrop transition-enter\\"><div class=\\"layer\\"></div><div class=\\"content\\"><span>test-value</span></div><div class=\\"offset\\"></div><style>
|
||||
.backdrop {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
display: flex;
|
||||
align-content: center;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
height: 100vh;
|
||||
width: 100vw;
|
||||
overflow: auto;
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
.content {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
position: relative;
|
||||
z-index: 1001;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.offset {
|
||||
height: 100vh;
|
||||
opacity: 0;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.layer {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
opacity: 0.25;
|
||||
background-color: black;
|
||||
transition: opacity .35s cubic-bezier(.4, 0, .2, 1);
|
||||
pointer-events: none;
|
||||
z-index: 1000;
|
||||
}
|
||||
</style></div>"
|
||||
`;
|
||||
|
||||
exports[`Backdrop should render correctly 1`] = `
|
||||
"<div class=\\"backdrop transition-enter\\"><div class=\\"layer\\"></div><div class=\\"content\\"><span>test-value</span></div><div class=\\"offset\\"></div><style>
|
||||
.backdrop {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
display: flex;
|
||||
align-content: center;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
height: 100vh;
|
||||
width: 100vw;
|
||||
overflow: auto;
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
.content {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
position: relative;
|
||||
z-index: 1001;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.offset {
|
||||
height: 0vh;
|
||||
opacity: 0;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.layer {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
opacity: 0.25;
|
||||
background-color: black;
|
||||
transition: opacity .35s cubic-bezier(.4, 0, .2, 1);
|
||||
pointer-events: none;
|
||||
z-index: 1000;
|
||||
}
|
||||
</style></div>"
|
||||
`;
|
||||
@@ -0,0 +1,3 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Dropdown should render correctly 1`] = `"<div></div>"`;
|
||||
@@ -0,0 +1,3 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`CSSTransition should render correctly 1`] = `"<span class=\\"undefined transition-enter\\">test</span>"`;
|
||||
65
components/shared/__tests__/backdrop.test.tsx
Normal file
65
components/shared/__tests__/backdrop.test.tsx
Normal file
@@ -0,0 +1,65 @@
|
||||
import React from 'react'
|
||||
import { mount } from 'enzyme'
|
||||
import Backdrop from '../backdrop'
|
||||
import { nativeEvent, updateWrapper } from 'tests/utils'
|
||||
|
||||
describe('Backdrop', () => {
|
||||
it('should render correctly', () => {
|
||||
const wrapper = mount(
|
||||
<Backdrop visible><span>test-value</span></Backdrop>
|
||||
)
|
||||
expect(wrapper.html()).toMatchSnapshot()
|
||||
expect(() => wrapper.unmount()).not.toThrow()
|
||||
})
|
||||
|
||||
it('should be shown or hidden by prop', async () => {
|
||||
const wrapper = mount(
|
||||
<Backdrop><span>test-value</span></Backdrop>
|
||||
)
|
||||
expect(wrapper.find('.backdrop').length).toBe(0)
|
||||
wrapper.setProps({ visible: true })
|
||||
await updateWrapper(wrapper, 350)
|
||||
expect(wrapper.find('.backdrop').length).not.toBe(0)
|
||||
})
|
||||
|
||||
it('background click events should be captured', () => {
|
||||
const handler = jest.fn()
|
||||
const wrapper = mount(
|
||||
<Backdrop onClick={handler} visible><span>test-value</span></Backdrop>
|
||||
)
|
||||
wrapper.find('.backdrop').simulate('click', nativeEvent)
|
||||
expect(handler).toHaveBeenCalled()
|
||||
handler.mockRestore()
|
||||
})
|
||||
|
||||
it('should be no error when handler missing', () => {
|
||||
const wrapper = mount(
|
||||
<Backdrop visible><span>test-value</span></Backdrop>
|
||||
)
|
||||
wrapper.find('.backdrop').simulate('click', nativeEvent)
|
||||
expect(() => wrapper.unmount()).not.toThrow()
|
||||
})
|
||||
|
||||
it('should be prevent event from the container', () => {
|
||||
const handler = jest.fn()
|
||||
const wrapper = mount(
|
||||
<Backdrop onClick={handler} visible><span>test-value</span></Backdrop>
|
||||
)
|
||||
wrapper.find('.content').simulate('click', nativeEvent)
|
||||
wrapper.find('.offset').simulate('click', nativeEvent)
|
||||
expect(handler).not.toHaveBeenCalled()
|
||||
handler.mockRestore()
|
||||
})
|
||||
|
||||
it('content should be offset', () => {
|
||||
const wrapper = mount(
|
||||
<Backdrop visible><span>test-value</span></Backdrop>
|
||||
)
|
||||
const notOffset = wrapper.html()
|
||||
expect(wrapper.html()).toMatchSnapshot()
|
||||
|
||||
wrapper.setProps({ offsetY: '100' })
|
||||
expect(wrapper.html()).toMatchSnapshot()
|
||||
expect(notOffset).not.toEqual(wrapper.html())
|
||||
})
|
||||
})
|
||||
165
components/shared/__tests__/dropdown.test.tsx
Normal file
165
components/shared/__tests__/dropdown.test.tsx
Normal file
@@ -0,0 +1,165 @@
|
||||
import React, { useRef } from 'react'
|
||||
import { mount } from 'enzyme'
|
||||
import Dropdown from '../dropdown'
|
||||
import { nativeEvent, updateWrapper } from 'tests/utils'
|
||||
import { act } from 'react-dom/test-utils'
|
||||
|
||||
const simulateGlobalClick = () => {
|
||||
document.body.dispatchEvent(
|
||||
new MouseEvent('click', {
|
||||
view: window,
|
||||
bubbles: true,
|
||||
cancelable: true,
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
||||
describe('Dropdown', () => {
|
||||
beforeAll(() => {
|
||||
window.Element.prototype.getBoundingClientRect = () => ({
|
||||
width: 100,
|
||||
left: 0,
|
||||
right: 100,
|
||||
top: 0,
|
||||
bottom: 100,
|
||||
height: 100,
|
||||
x: 0,
|
||||
} as DOMRect)
|
||||
})
|
||||
|
||||
it('should render correctly', async () => {
|
||||
const Mock: React.FC<{ visible?: boolean }> = ({ visible = false }) => {
|
||||
const ref = useRef<HTMLDivElement>(null)
|
||||
return (
|
||||
<div ref={ref}>
|
||||
<Dropdown parent={ref} visible={visible}>
|
||||
<span>test-value</span>
|
||||
</Dropdown>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
const wrapper = mount(<Mock />)
|
||||
wrapper.setProps({ visible: true })
|
||||
await updateWrapper(wrapper, 300)
|
||||
|
||||
expect(wrapper.find('.dropdown').html()).toContain('test-value')
|
||||
expect(wrapper.html()).toMatchSnapshot()
|
||||
expect(() => wrapper.unmount()).not.toThrow()
|
||||
})
|
||||
|
||||
it('should be work without parent', () => {
|
||||
const wrapper = mount(
|
||||
<Dropdown visible>
|
||||
<span>test-value</span>
|
||||
</Dropdown>
|
||||
)
|
||||
|
||||
expect(() => wrapper.unmount()).not.toThrow()
|
||||
})
|
||||
|
||||
it('events should be prevented', () => {
|
||||
const handler = jest.fn()
|
||||
const Mock: React.FC<{}> = () => {
|
||||
const ref = useRef<HTMLDivElement>(null)
|
||||
return (
|
||||
<div ref={ref} onClick={handler}>
|
||||
<Dropdown parent={ref} visible>
|
||||
<span>test-value</span>
|
||||
</Dropdown>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
const wrapper = mount(<Mock />)
|
||||
wrapper.find('.dropdown').simulate('click', nativeEvent)
|
||||
|
||||
expect(handler).not.toHaveBeenCalled()
|
||||
expect(() => wrapper.unmount()).not.toThrow()
|
||||
handler.mockRestore()
|
||||
})
|
||||
|
||||
it('should trigger rect update', async () => {
|
||||
let dynamicTopMock = 100, calledTimes = 0
|
||||
window.Element.prototype.getBoundingClientRect = () => {
|
||||
calledTimes ++
|
||||
return {
|
||||
width: 100,
|
||||
left: 0,
|
||||
right: 100,
|
||||
top: 0,
|
||||
bottom: dynamicTopMock,
|
||||
height: 100,
|
||||
x: 0,
|
||||
} as DOMRect
|
||||
}
|
||||
const Mock: React.FC<{}> = () => {
|
||||
const ref = useRef<HTMLDivElement>(null)
|
||||
return (
|
||||
<div ref={ref}>
|
||||
<Dropdown parent={ref} visible>
|
||||
<span>test-value</span>
|
||||
</Dropdown>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
const wrapper = mount(<Mock />)
|
||||
expect(calledTimes).toBe(1)
|
||||
|
||||
// Do not render if position is not updated
|
||||
act(() => simulateGlobalClick())
|
||||
expect(calledTimes).toBe(2)
|
||||
await updateWrapper(wrapper, 50)
|
||||
|
||||
// Trigger position diff first, then trigger the update
|
||||
// Get Rect twice total
|
||||
act(() => {
|
||||
dynamicTopMock++
|
||||
simulateGlobalClick()
|
||||
})
|
||||
expect(calledTimes).toBeGreaterThanOrEqual(4)
|
||||
|
||||
act(() => {
|
||||
dynamicTopMock++
|
||||
window.dispatchEvent(new Event('resize'))
|
||||
})
|
||||
expect(calledTimes).toBeGreaterThanOrEqual(5)
|
||||
|
||||
expect(() => wrapper.unmount()).not.toThrow()
|
||||
})
|
||||
|
||||
it('should tigger rect update when mouseenter', () => {
|
||||
let calledTimes = 0
|
||||
window.Element.prototype.getBoundingClientRect = () => {
|
||||
calledTimes ++
|
||||
return {
|
||||
width: 100,
|
||||
left: 0,
|
||||
right: 100,
|
||||
top: 0,
|
||||
bottom: 100,
|
||||
height: 100,
|
||||
x: 0,
|
||||
} as DOMRect
|
||||
}
|
||||
const Mock: React.FC<{}> = () => {
|
||||
const ref = useRef<HTMLDivElement>(null)
|
||||
return (
|
||||
<div ref={ref} id="parent">
|
||||
<Dropdown parent={ref} visible>
|
||||
<span>test-value</span>
|
||||
</Dropdown>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
const wrapper = mount(<Mock />)
|
||||
expect(calledTimes).toBe(1)
|
||||
|
||||
// MouseEnter event is monitored by native API, the simulate can not trigger it.
|
||||
const parent = wrapper.find('#parent').getDOMNode() as HTMLDivElement
|
||||
act(() => {
|
||||
parent.dispatchEvent(new Event('mouseenter'))
|
||||
})
|
||||
expect(calledTimes).toBe(2)
|
||||
|
||||
expect(() => wrapper.unmount()).not.toThrow()
|
||||
})
|
||||
})
|
||||
67
components/shared/__tests__/transition.test.tsx
Normal file
67
components/shared/__tests__/transition.test.tsx
Normal file
@@ -0,0 +1,67 @@
|
||||
import React from 'react'
|
||||
import { mount } from 'enzyme'
|
||||
import CSSTransition from '../css-transition'
|
||||
import { updateWrapper } from 'tests/utils'
|
||||
|
||||
describe('CSSTransition', () => {
|
||||
it('should render correctly', () => {
|
||||
const wrapper = mount(<CSSTransition visible><span>test</span></CSSTransition>)
|
||||
expect(wrapper.text()).toContain('test')
|
||||
expect(wrapper.html()).toMatchSnapshot()
|
||||
expect(() => wrapper.unmount()).not.toThrow()
|
||||
})
|
||||
|
||||
it('should work correctly with time props', async () => {
|
||||
const wrapper = mount(
|
||||
<CSSTransition enterTime={300} leaveTime={300}>
|
||||
<span id="test">test</span>
|
||||
</CSSTransition>
|
||||
)
|
||||
expect(wrapper.find('.transition-enter-active').length).toBe(0)
|
||||
|
||||
wrapper.setProps({ visible: true })
|
||||
await updateWrapper(wrapper, 310)
|
||||
expect(wrapper.find('.transition-enter-active').length).not.toBe(0)
|
||||
|
||||
wrapper.setProps({ visible: false })
|
||||
await updateWrapper(wrapper, 310)
|
||||
expect(wrapper.find('.transition-leave-active').length).not.toBe(0)
|
||||
})
|
||||
|
||||
it('should clear css-transition classes after hidden', async () => {
|
||||
const wrapper = mount(<CSSTransition visible><span>test</span></CSSTransition>)
|
||||
// don't remove classes after shown
|
||||
await updateWrapper(wrapper, 60)
|
||||
expect(wrapper.find('.transition-enter-active').length).not.toBe(0)
|
||||
|
||||
await updateWrapper(wrapper, 150)
|
||||
expect(wrapper.find('.transition-enter-active').length).not.toBe(0)
|
||||
|
||||
// remove classes after hidden
|
||||
wrapper.setProps({ visible: false })
|
||||
await updateWrapper(wrapper, 60)
|
||||
expect(wrapper.find('.transition-leave-active').length).not.toBe(0)
|
||||
|
||||
await updateWrapper(wrapper, 150)
|
||||
expect(wrapper.find('.transition-leave-active').length).toBe(0)
|
||||
expect(wrapper.find('.transition-enter-active').length).toBe(0)
|
||||
})
|
||||
|
||||
it('custom class names should be rendered', async () => {
|
||||
const wrapper = mount(
|
||||
<CSSTransition name="test">
|
||||
<span id="test">test</span>
|
||||
</CSSTransition>
|
||||
)
|
||||
|
||||
expect(wrapper.find('.test-enter-active').length).toBe(0)
|
||||
|
||||
wrapper.setProps({ visible: true })
|
||||
await updateWrapper(wrapper, 60)
|
||||
expect(wrapper.find('.test-enter-active').length).not.toBe(0)
|
||||
|
||||
wrapper.setProps({ visible: false })
|
||||
await updateWrapper(wrapper, 60)
|
||||
expect(wrapper.find('.test-leave-active').length).not.toBe(0)
|
||||
})
|
||||
})
|
||||
@@ -57,6 +57,7 @@ const Dropdown: React.FC<React.PropsWithChildren<Props>> = React.memo(({
|
||||
useEffect(() => {
|
||||
if (!parent || !parent.current) return
|
||||
parent.current.addEventListener('mouseenter', updateRect)
|
||||
/* istanbul ignore next */
|
||||
return () => {
|
||||
if (!parent || !parent.current) return
|
||||
parent.current.removeEventListener('mouseenter', updateRect)
|
||||
|
||||
Reference in New Issue
Block a user