mirror of
https://github.com/zhigang1992/react.git
synced 2026-04-26 23:04:55 +08:00
181
components/textarea/__tests__/__snapshots__/index.test.tsx.snap
Normal file
181
components/textarea/__tests__/__snapshots__/index.test.tsx.snap
Normal file
@@ -0,0 +1,181 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Textarea should render correctly 1`] = `
|
||||
"<div class=\\"wrapper \\"><textarea placeholder=\\"placeholder\\"></textarea><style>
|
||||
.wrapper {
|
||||
display: inline-flex;
|
||||
box-sizing: border-box;
|
||||
user-select: none;
|
||||
width: initial;
|
||||
min-width: 12.5rem;
|
||||
max-width: 95vw;
|
||||
height: auto;
|
||||
border-radius: 5px;
|
||||
border: 1px solid #eaeaea;
|
||||
color: #000;
|
||||
transition: border 0.2s ease 0s, color 0.2s ease 0s;
|
||||
}
|
||||
|
||||
.wrapper.hover {
|
||||
border-color: #666;
|
||||
}
|
||||
|
||||
.wrapper.disabled {
|
||||
background-color: #fafafa;
|
||||
border-color: #eaeaea;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
textarea {
|
||||
background-color: transparent;
|
||||
box-shadow: none;
|
||||
display: block;
|
||||
font-family: -apple-system, BlinkMacSystemFont, \\"Segoe UI\\", \\"Roboto\\", \\"Oxygen\\", \\"Ubuntu\\", \\"Cantarell\\", \\"Fira Sans\\", \\"Droid Sans\\", \\"Helvetica Neue\\", sans-serif;
|
||||
font-size: .875rem;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
min-height: 6.25rem;
|
||||
resize: none;
|
||||
border: none;
|
||||
outline: none;
|
||||
padding: 8pt;
|
||||
}
|
||||
|
||||
.disabled > textarea {
|
||||
cursor: not-allowed;
|
||||
}
|
||||
</style></div>"
|
||||
`;
|
||||
|
||||
exports[`Textarea should work with different styles 1`] = `
|
||||
"<div><div class=\\"wrapper \\"><textarea></textarea><style>
|
||||
.wrapper {
|
||||
display: inline-flex;
|
||||
box-sizing: border-box;
|
||||
user-select: none;
|
||||
width: initial;
|
||||
min-width: 12.5rem;
|
||||
max-width: 95vw;
|
||||
height: auto;
|
||||
border-radius: 5px;
|
||||
border: 1px solid #666;
|
||||
color: #000;
|
||||
transition: border 0.2s ease 0s, color 0.2s ease 0s;
|
||||
}
|
||||
|
||||
.wrapper.hover {
|
||||
border-color: #666;
|
||||
}
|
||||
|
||||
.wrapper.disabled {
|
||||
background-color: #fafafa;
|
||||
border-color: #eaeaea;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
textarea {
|
||||
background-color: transparent;
|
||||
box-shadow: none;
|
||||
display: block;
|
||||
font-family: -apple-system, BlinkMacSystemFont, \\"Segoe UI\\", \\"Roboto\\", \\"Oxygen\\", \\"Ubuntu\\", \\"Cantarell\\", \\"Fira Sans\\", \\"Droid Sans\\", \\"Helvetica Neue\\", sans-serif;
|
||||
font-size: .875rem;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
min-height: 6.25rem;
|
||||
resize: none;
|
||||
border: none;
|
||||
outline: none;
|
||||
padding: 8pt;
|
||||
}
|
||||
|
||||
.disabled > textarea {
|
||||
cursor: not-allowed;
|
||||
}
|
||||
</style></div><div class=\\"wrapper \\"><textarea></textarea><style>
|
||||
.wrapper {
|
||||
display: inline-flex;
|
||||
box-sizing: border-box;
|
||||
user-select: none;
|
||||
width: 20%;
|
||||
min-width: 12.5rem;
|
||||
max-width: 95vw;
|
||||
height: auto;
|
||||
border-radius: 5px;
|
||||
border: 1px solid #eaeaea;
|
||||
color: #000;
|
||||
transition: border 0.2s ease 0s, color 0.2s ease 0s;
|
||||
}
|
||||
|
||||
.wrapper.hover {
|
||||
border-color: #666;
|
||||
}
|
||||
|
||||
.wrapper.disabled {
|
||||
background-color: #fafafa;
|
||||
border-color: #eaeaea;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
textarea {
|
||||
background-color: transparent;
|
||||
box-shadow: none;
|
||||
display: block;
|
||||
font-family: -apple-system, BlinkMacSystemFont, \\"Segoe UI\\", \\"Roboto\\", \\"Oxygen\\", \\"Ubuntu\\", \\"Cantarell\\", \\"Fira Sans\\", \\"Droid Sans\\", \\"Helvetica Neue\\", sans-serif;
|
||||
font-size: .875rem;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
min-height: 6.25rem;
|
||||
resize: none;
|
||||
border: none;
|
||||
outline: none;
|
||||
padding: 8pt;
|
||||
}
|
||||
|
||||
.disabled > textarea {
|
||||
cursor: not-allowed;
|
||||
}
|
||||
</style></div><div class=\\"wrapper \\"><textarea></textarea><style>
|
||||
.wrapper {
|
||||
display: inline-flex;
|
||||
box-sizing: border-box;
|
||||
user-select: none;
|
||||
width: initial;
|
||||
min-width: 12.5rem;
|
||||
max-width: 95vw;
|
||||
height: auto;
|
||||
border-radius: 5px;
|
||||
border: 1px solid #eaeaea;
|
||||
color: #000;
|
||||
transition: border 0.2s ease 0s, color 0.2s ease 0s;
|
||||
}
|
||||
|
||||
.wrapper.hover {
|
||||
border-color: #666;
|
||||
}
|
||||
|
||||
.wrapper.disabled {
|
||||
background-color: #fafafa;
|
||||
border-color: #eaeaea;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
textarea {
|
||||
background-color: transparent;
|
||||
box-shadow: none;
|
||||
display: block;
|
||||
font-family: -apple-system, BlinkMacSystemFont, \\"Segoe UI\\", \\"Roboto\\", \\"Oxygen\\", \\"Ubuntu\\", \\"Cantarell\\", \\"Fira Sans\\", \\"Droid Sans\\", \\"Helvetica Neue\\", sans-serif;
|
||||
font-size: .875rem;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
min-height: 100px;
|
||||
resize: none;
|
||||
border: none;
|
||||
outline: none;
|
||||
padding: 8pt;
|
||||
}
|
||||
|
||||
.disabled > textarea {
|
||||
cursor: not-allowed;
|
||||
}
|
||||
</style></div></div>"
|
||||
`;
|
||||
72
components/textarea/__tests__/index.test.tsx
Normal file
72
components/textarea/__tests__/index.test.tsx
Normal file
@@ -0,0 +1,72 @@
|
||||
import React from 'react'
|
||||
import { mount } from 'enzyme'
|
||||
import { Textarea } from 'components'
|
||||
import { nativeEvent } from 'tests/utils'
|
||||
|
||||
describe('Textarea', () => {
|
||||
it('should render correctly', () => {
|
||||
const wrapper = mount(<Textarea placeholder="placeholder" />)
|
||||
expect(wrapper.html()).toMatchSnapshot()
|
||||
expect(() => wrapper.unmount()).not.toThrow()
|
||||
})
|
||||
|
||||
it('should work with different styles', () => {
|
||||
const wrapper = mount(
|
||||
<div>
|
||||
<Textarea status="secondary" />
|
||||
<Textarea width="20%" />
|
||||
<Textarea minHeight="100px" />
|
||||
</div>
|
||||
)
|
||||
expect(wrapper.html()).toMatchSnapshot()
|
||||
expect(() => wrapper.unmount()).not.toThrow()
|
||||
})
|
||||
|
||||
it('should set textarea from value', () => {
|
||||
const wrapper = mount(<Textarea initialValue="test-value" />)
|
||||
let el = wrapper.find('textarea').getDOMNode() as HTMLTextAreaElement
|
||||
expect(el.value).toEqual('test-value')
|
||||
|
||||
wrapper.setProps({ value: 'test-value2' })
|
||||
el = wrapper.find('textarea').getDOMNode() as HTMLTextAreaElement
|
||||
expect(el.value).toEqual('test-value2')
|
||||
})
|
||||
|
||||
it('should trigger events when textarea changed', () => {
|
||||
let value = ''
|
||||
const handler = jest.fn()
|
||||
.mockImplementation(e => value = e.target.value)
|
||||
const wrapper = mount(<Textarea onChange={handler} />)
|
||||
wrapper.find('textarea')
|
||||
.simulate('change', { target: { value: 'test-value' } })
|
||||
expect(handler).toHaveBeenCalled()
|
||||
expect(value).toEqual('test-value')
|
||||
handler.mockRestore()
|
||||
})
|
||||
|
||||
it('should ignore events when disabled or readonly', () => {
|
||||
const handler = jest.fn()
|
||||
const wrapper = mount(<Textarea onChange={handler} disabled />)
|
||||
wrapper.find('textarea')
|
||||
.simulate('change', { target: { value: 'test-value' } })
|
||||
expect(handler).not.toHaveBeenCalled()
|
||||
|
||||
wrapper.setProps({ disabled: false, readOnly: true })
|
||||
wrapper.find('textarea')
|
||||
.simulate('change', { target: { value: 'test-value2' } })
|
||||
expect(handler).not.toHaveBeenCalled()
|
||||
handler.mockRestore()
|
||||
})
|
||||
|
||||
it('should pass through blur event', () => {
|
||||
const blurHandler = jest.fn()
|
||||
const focusHandler = jest.fn()
|
||||
const wrapper = mount(<Textarea onBlur={blurHandler} onFocus={focusHandler} />)
|
||||
|
||||
wrapper.find('textarea').simulate('focus', nativeEvent)
|
||||
expect(focusHandler).toHaveBeenCalled()
|
||||
|
||||
wrapper.find('textarea').simulate('blur', nativeEvent)
|
||||
expect(blurHandler).toHaveBeenCalled()
|
||||
})
|
||||
})
|
||||
251
components/toast/__tests__/__snapshots__/index.test.tsx.snap
Normal file
251
components/toast/__tests__/__snapshots__/index.test.tsx.snap
Normal file
@@ -0,0 +1,251 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`UseToast should render different actions 1`] = `
|
||||
"<div class=\\"toast-container \\"><div class=\\"toast \\"><div class=\\"message\\">hello</div><div class=\\"action\\"><button class=\\"btn \\"><div class=\\"text\\">remove</div><style>
|
||||
.btn {
|
||||
box-sizing: border-box;
|
||||
display: inline-block;
|
||||
padding: 0 0.625rem;
|
||||
height: 1.5rem;
|
||||
line-height: 1.5rem;
|
||||
min-width: min-content;
|
||||
width: auto;
|
||||
border-radius: 5px;
|
||||
font-weight: 400;
|
||||
font-size: .75rem;
|
||||
user-select: none;
|
||||
outline: none;
|
||||
text-transform: capitalize;
|
||||
justify-content: center;
|
||||
text-align: center;
|
||||
white-space: nowrap;
|
||||
transition: all 0.2s ease;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
color: #fff;
|
||||
background-color: #000;
|
||||
border: 1px solid #000;
|
||||
cursor: pointer;
|
||||
pointer-events: auto;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.btn:hover {
|
||||
color: #000;
|
||||
background-color: #fff;
|
||||
border-color: #000;
|
||||
cursor: pointer;
|
||||
pointer-events: auto;
|
||||
box-shadow: none;
|
||||
transform: translate3d(0px, 0px, 0px);
|
||||
}
|
||||
|
||||
.text {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
display: inline-flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
line-height: inherit;
|
||||
top: -1px;
|
||||
}
|
||||
|
||||
.text :global(p), .text :global(pre), .text :global(div) {
|
||||
margin: 0;
|
||||
}
|
||||
</style></button><button class=\\"btn \\"><div class=\\"text\\">remove</div><style>
|
||||
.btn {
|
||||
box-sizing: border-box;
|
||||
display: inline-block;
|
||||
padding: 0 0.625rem;
|
||||
height: 1.5rem;
|
||||
line-height: 1.5rem;
|
||||
min-width: min-content;
|
||||
width: auto;
|
||||
border-radius: 5px;
|
||||
font-weight: 400;
|
||||
font-size: .75rem;
|
||||
user-select: none;
|
||||
outline: none;
|
||||
text-transform: capitalize;
|
||||
justify-content: center;
|
||||
text-align: center;
|
||||
white-space: nowrap;
|
||||
transition: all 0.2s ease;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
color: #666;
|
||||
background-color: #fff;
|
||||
border: 1px solid #eaeaea;
|
||||
cursor: pointer;
|
||||
pointer-events: auto;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.btn:hover {
|
||||
color: #000;
|
||||
background-color: #fff;
|
||||
border-color: #000;
|
||||
cursor: pointer;
|
||||
pointer-events: auto;
|
||||
box-shadow: none;
|
||||
transform: translate3d(0px, 0px, 0px);
|
||||
}
|
||||
|
||||
.text {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
display: inline-flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
line-height: inherit;
|
||||
top: -1px;
|
||||
}
|
||||
|
||||
.text :global(p), .text :global(pre), .text :global(div) {
|
||||
margin: 0;
|
||||
}
|
||||
</style></button></div><style>
|
||||
.toast {
|
||||
width: 420px;
|
||||
max-width: 90vw;
|
||||
max-height: 75px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
color: #000;
|
||||
background-color: #fff;
|
||||
color: #000;
|
||||
border: 0;
|
||||
border-radius: 5px;
|
||||
padding: 16pt;
|
||||
box-shadow: 0 5px 10px rgba(0, 0, 0, 0.12);
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
opacity: 0;
|
||||
transform: translate3d(0, 100%, 0px) scale(1);
|
||||
transition: all 400ms ease;
|
||||
}
|
||||
|
||||
.toast.visible {
|
||||
opacity: 1;
|
||||
transform: translate3d(0, calc(100% + -75px + -0px), -0px) scale(1);
|
||||
}
|
||||
|
||||
.toast.hide {
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.message {
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
transition: opacity .4s ease;
|
||||
font-size: .875rem;
|
||||
display: -webkit-box;
|
||||
word-break: break-all;
|
||||
padding-right: 8pt;
|
||||
overflow: hidden;
|
||||
max-height: 100%;
|
||||
text-overflow: ellipsis;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-line-clamp: 2;
|
||||
line-height: 1.1rem;
|
||||
}
|
||||
|
||||
.toast :global(button + button) {
|
||||
margin-left: 4pt;
|
||||
}
|
||||
</style></div><style>
|
||||
.toast-container {
|
||||
position: fixed;
|
||||
width: 420px;
|
||||
max-width: 90vw;
|
||||
bottom: 16pt;
|
||||
right: 16pt;
|
||||
z-index: 2000;
|
||||
transition: all 400ms ease;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.toast-container.hover {
|
||||
transform: translate3d(0, -10px, 0);
|
||||
}
|
||||
</style></div>"
|
||||
`;
|
||||
|
||||
exports[`UseToast should work with different types 1`] = `
|
||||
"<div class=\\"toast-container \\"><div class=\\"toast \\"><div class=\\"message\\">hello</div><div class=\\"action\\"></div><style>
|
||||
.toast {
|
||||
width: 420px;
|
||||
max-width: 90vw;
|
||||
max-height: 75px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
color: #000;
|
||||
background-color: #0070f3;
|
||||
color: #fff;
|
||||
border: 0;
|
||||
border-radius: 5px;
|
||||
padding: 16pt;
|
||||
box-shadow: 0 5px 10px rgba(0, 0, 0, 0.12);
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
opacity: 0;
|
||||
transform: translate3d(0, 100%, 0px) scale(1);
|
||||
transition: all 400ms ease;
|
||||
}
|
||||
|
||||
.toast.visible {
|
||||
opacity: 1;
|
||||
transform: translate3d(0, calc(100% + -75px + -0px), -0px) scale(1);
|
||||
}
|
||||
|
||||
.toast.hide {
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.message {
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
transition: opacity .4s ease;
|
||||
font-size: .875rem;
|
||||
display: -webkit-box;
|
||||
word-break: break-all;
|
||||
padding-right: 8pt;
|
||||
overflow: hidden;
|
||||
max-height: 100%;
|
||||
text-overflow: ellipsis;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-line-clamp: 2;
|
||||
line-height: 1.1rem;
|
||||
}
|
||||
|
||||
.toast :global(button + button) {
|
||||
margin-left: 4pt;
|
||||
}
|
||||
</style></div><style>
|
||||
.toast-container {
|
||||
position: fixed;
|
||||
width: 420px;
|
||||
max-width: 90vw;
|
||||
bottom: 16pt;
|
||||
right: 16pt;
|
||||
z-index: 2000;
|
||||
transition: all 400ms ease;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.toast-container.hover {
|
||||
transform: translate3d(0, -10px, 0);
|
||||
}
|
||||
</style></div>"
|
||||
`;
|
||||
151
components/toast/__tests__/index.test.tsx
Normal file
151
components/toast/__tests__/index.test.tsx
Normal file
@@ -0,0 +1,151 @@
|
||||
import React from 'react'
|
||||
import { mount, ReactWrapper } from 'enzyme'
|
||||
import { useToasts, ZEITUIProvider } from 'components'
|
||||
import { nativeEvent, updateWrapper } from 'tests/utils'
|
||||
|
||||
const MockToast: React.FC<{}> = () => {
|
||||
const [, setToast] = useToasts()
|
||||
const clickHandler = (e: any = {}) => {
|
||||
const keys = ['text', 'delay', 'type', 'actions']
|
||||
const params = keys.reduce((pre, key) => {
|
||||
const value = e.target[key]
|
||||
if (!value) return pre
|
||||
return { ...pre, [key]: value }
|
||||
}, {})
|
||||
setToast(params)
|
||||
}
|
||||
return <button id="btn" onClick={clickHandler}>btn</button>
|
||||
}
|
||||
|
||||
const triggerToast = (wrapper: ReactWrapper, params = {}) => {
|
||||
wrapper.find('#btn').simulate('click', {
|
||||
...nativeEvent,
|
||||
target: params,
|
||||
})
|
||||
}
|
||||
|
||||
const expectToastIsShow = (wrapper: ReactWrapper) => {
|
||||
const toast = wrapper.find('.toast-container').find('.toast')
|
||||
expect(toast.length).not.toBe(0)
|
||||
}
|
||||
|
||||
const expectToastIsHidden = (wrapper: ReactWrapper) => {
|
||||
const toast = wrapper.find('.toast-container').find('.toast')
|
||||
expect(toast.length).toBe(0)
|
||||
}
|
||||
|
||||
describe('UseToast', () => {
|
||||
it('should render correctly', async () => {
|
||||
const wrapper = mount(<ZEITUIProvider><MockToast /></ZEITUIProvider>)
|
||||
|
||||
expectToastIsHidden(wrapper)
|
||||
triggerToast(wrapper, { text: 'test-value' })
|
||||
await updateWrapper(wrapper)
|
||||
expectToastIsShow(wrapper)
|
||||
})
|
||||
|
||||
it('should work with different types', async () => {
|
||||
const wrapper = mount(<ZEITUIProvider><MockToast /></ZEITUIProvider>)
|
||||
|
||||
expectToastIsHidden(wrapper)
|
||||
triggerToast(wrapper, { type: 'success', text: 'hello' })
|
||||
await updateWrapper(wrapper)
|
||||
expectToastIsShow(wrapper)
|
||||
expect(wrapper.find('.toast-container').html()).toMatchSnapshot()
|
||||
})
|
||||
|
||||
it('should close toast', async () => {
|
||||
const wrapper = mount(<ZEITUIProvider><MockToast /></ZEITUIProvider>)
|
||||
|
||||
expectToastIsHidden(wrapper)
|
||||
triggerToast(wrapper, { delay: 100, text: 'hello' })
|
||||
await updateWrapper(wrapper, 0)
|
||||
expectToastIsShow(wrapper)
|
||||
// Element already hidden, but Dom was removed after delay
|
||||
await updateWrapper(wrapper, 350)
|
||||
const toast = wrapper.find('.toast-container').find('.hide')
|
||||
expect(toast.length).not.toBe(0)
|
||||
})
|
||||
|
||||
it('the removeal should be delayed when hover is triggerd', async () => {
|
||||
const wrapper = mount(<ZEITUIProvider><MockToast /></ZEITUIProvider>)
|
||||
|
||||
expectToastIsHidden(wrapper)
|
||||
triggerToast(wrapper, { delay: 100, text: 'hello' })
|
||||
await updateWrapper(wrapper, 0)
|
||||
expectToastIsShow(wrapper)
|
||||
|
||||
wrapper.find('.toast-container').simulate('mouseEnter', nativeEvent)
|
||||
await updateWrapper(wrapper, 350)
|
||||
|
||||
// Hover event will postpone hidden event
|
||||
let toast = wrapper.find('.toast-container').find('.hide')
|
||||
expect(toast.length).toBe(0)
|
||||
|
||||
// Restart hidden event after mouse leave
|
||||
wrapper.find('.toast-container').simulate('mouseLeave', nativeEvent)
|
||||
await updateWrapper(wrapper, 350 + 200)
|
||||
toast = wrapper.find('.toast-container').find('.hide')
|
||||
expect(toast.length).not.toBe(0)
|
||||
})
|
||||
|
||||
it('should render different actions', async () => {
|
||||
const wrapper = mount(<ZEITUIProvider><MockToast /></ZEITUIProvider>)
|
||||
const actions = [{
|
||||
name: 'remove',
|
||||
handler: () => {},
|
||||
}, {
|
||||
name: 'remove',
|
||||
handler: () => {},
|
||||
passive: true,
|
||||
}]
|
||||
|
||||
triggerToast(wrapper, { actions, text: 'hello' })
|
||||
await updateWrapper(wrapper)
|
||||
expectToastIsShow(wrapper)
|
||||
expect(wrapper.find('.toast-container').html()).toMatchSnapshot()
|
||||
})
|
||||
|
||||
it('should close toast when action triggered', async () => {
|
||||
const wrapper = mount(<ZEITUIProvider><MockToast /></ZEITUIProvider>)
|
||||
const actions = [{
|
||||
name: 'remove',
|
||||
handler: (_event: any, cancel: Function) => cancel()
|
||||
}]
|
||||
|
||||
expectToastIsHidden(wrapper)
|
||||
triggerToast(wrapper, { actions, text: 'hello' })
|
||||
await updateWrapper(wrapper)
|
||||
expectToastIsShow(wrapper)
|
||||
wrapper.find('.action').find('.btn').at(0)
|
||||
.simulate('click', nativeEvent)
|
||||
|
||||
// Element already hidden, but Dom was removed after delay
|
||||
await updateWrapper(wrapper, 250)
|
||||
const toast = wrapper.find('.toast-container').find('.hide')
|
||||
expect(toast.length).not.toBe(0)
|
||||
})
|
||||
|
||||
it('should work with multiple toasts', async () => {
|
||||
const wrapper = mount(<ZEITUIProvider><MockToast /></ZEITUIProvider>)
|
||||
|
||||
expectToastIsHidden(wrapper)
|
||||
triggerToast(wrapper, { delay: 100, text: 'hello' })
|
||||
triggerToast(wrapper, { delay: 100, text: 'hello' })
|
||||
triggerToast(wrapper, { delay: 100, text: 'hello' })
|
||||
triggerToast(wrapper, { delay: 100, text: 'hello' })
|
||||
triggerToast(wrapper, { delay: 100, text: 'hello' })
|
||||
triggerToast(wrapper, { delay: 200, text: 'hello' })
|
||||
|
||||
/**
|
||||
* If there are multiple Toasts at different deplay in the stack,
|
||||
* the destory Dom event will wait for the maximum delay time.
|
||||
*/
|
||||
await updateWrapper(wrapper, 350)
|
||||
expectToastIsShow(wrapper)
|
||||
|
||||
await updateWrapper(wrapper, 200)
|
||||
const toast = wrapper.find('.toast-container').find('.hide')
|
||||
expect(toast.length).not.toBe(0)
|
||||
})
|
||||
})
|
||||
@@ -76,13 +76,17 @@ const ToastItem: React.FC<ToatItemProps> = React.memo(({
|
||||
}, [])
|
||||
|
||||
useEffect(() => {
|
||||
let unMount = false
|
||||
const shouldBeHide = reverseIndex > 2 || toast.willBeDestroy
|
||||
if (!shouldBeHide) return
|
||||
if (!shouldBeHide || unMount) return
|
||||
const timer = setTimeout(() => {
|
||||
setHide(true)
|
||||
clearTimeout(timer)
|
||||
}, 150)
|
||||
return () => clearTimeout(timer)
|
||||
return () => {
|
||||
unMount = true
|
||||
clearTimeout(timer)
|
||||
}
|
||||
}, [reverseIndex, toast.willBeDestroy])
|
||||
|
||||
return (
|
||||
|
||||
@@ -35,10 +35,13 @@ const useToasts = (): [Array<Toast>, (t: Toast) => void] => {
|
||||
// Wait for all components to display before destroying
|
||||
// The destory means direct remove all element, whether in animation or not.
|
||||
const nextDestoryTime = delay + 500
|
||||
/* istanbul ignore next */
|
||||
if (nextDestoryTime < maxDestoryTime.current) return
|
||||
clearTimeout(destoryTimer.current)
|
||||
maxDestoryTime.current = nextDestoryTime
|
||||
|
||||
destoryTimer.current = window.setTimeout(() => {
|
||||
/* istanbul ignore next */
|
||||
updateToasts((currentToasts: Array<ToastWithID>) => {
|
||||
if (destoryStack.current.length < currentToasts.length) {
|
||||
return currentToasts
|
||||
@@ -49,7 +52,6 @@ const useToasts = (): [Array<Toast>, (t: Toast) => void] => {
|
||||
clearTimeout(destoryTimer.current)
|
||||
}, maxDestoryTime.current)
|
||||
}
|
||||
|
||||
|
||||
const setToast = (toast: Toast): void => {
|
||||
const id = `toast-${getId()}`
|
||||
|
||||
369
components/toggle/__tests__/__snapshots__/index.test.tsx.snap
Normal file
369
components/toggle/__tests__/__snapshots__/index.test.tsx.snap
Normal file
@@ -0,0 +1,369 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Toggle should render correctly 1`] = `
|
||||
"<label class=\\"\\"><input type=\\"checkbox\\"><div class=\\"toggle \\"><span class=\\"inner\\"></span></div><style>
|
||||
label {
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
display: inline-block;
|
||||
vertical-align: center;
|
||||
white-space: nowrap;
|
||||
user-select: none;
|
||||
padding: 3px 0;
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
input {
|
||||
overflow: hidden;
|
||||
visibility: hidden;
|
||||
height: 0;
|
||||
opacity: 0;
|
||||
width: 0;
|
||||
position: absolute;
|
||||
background-color: transparent;
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
.toggle {
|
||||
height: .875rem;
|
||||
width: 1.75rem;
|
||||
border-radius: .875rem;
|
||||
transition-delay: 0.12s;
|
||||
transition-duration: 0.2s;
|
||||
transition-property: background, border;
|
||||
transition-timing-function: cubic-bezier(0, 0, 0.2, 1);
|
||||
position: relative;
|
||||
border: 1px solid transparent;
|
||||
background-color: #eaeaea;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.inner {
|
||||
width: calc(.875rem - 2px);
|
||||
height: calc(.875rem - 2px);
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
left: 1px;
|
||||
box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px 0, rgba(0, 0, 0, 0.1) 0 1px 3px 0;
|
||||
transition: left 280ms cubic-bezier(0, 0, 0.2, 1);
|
||||
border-radius: 50%;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.disabled {
|
||||
border-color: #eaeaea;
|
||||
background-color: #fafafa;
|
||||
}
|
||||
|
||||
.disabled > .inner {
|
||||
background-color: #eaeaea;
|
||||
}
|
||||
|
||||
.disabled.checked {
|
||||
border-color: #888;
|
||||
background-color: #888;
|
||||
}
|
||||
|
||||
.checked {
|
||||
background-color: #0070f3;
|
||||
}
|
||||
|
||||
.checked > .inner {
|
||||
left: calc(100% - (.875rem - 2px));
|
||||
box-shadow: none;
|
||||
}
|
||||
</style></label>"
|
||||
`;
|
||||
|
||||
exports[`Toggle should work with different sizes 1`] = `
|
||||
"<div><label class=\\"\\"><input type=\\"checkbox\\"><div class=\\"toggle \\"><span class=\\"inner\\"></span></div><style>
|
||||
label {
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
display: inline-block;
|
||||
vertical-align: center;
|
||||
white-space: nowrap;
|
||||
user-select: none;
|
||||
padding: 3px 0;
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
input {
|
||||
overflow: hidden;
|
||||
visibility: hidden;
|
||||
height: 0;
|
||||
opacity: 0;
|
||||
width: 0;
|
||||
position: absolute;
|
||||
background-color: transparent;
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
.toggle {
|
||||
height: .835rem;
|
||||
width: 1.67rem;
|
||||
border-radius: .835rem;
|
||||
transition-delay: 0.12s;
|
||||
transition-duration: 0.2s;
|
||||
transition-property: background, border;
|
||||
transition-timing-function: cubic-bezier(0, 0, 0.2, 1);
|
||||
position: relative;
|
||||
border: 1px solid transparent;
|
||||
background-color: #eaeaea;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.inner {
|
||||
width: calc(.835rem - 2px);
|
||||
height: calc(.835rem - 2px);
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
left: 1px;
|
||||
box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px 0, rgba(0, 0, 0, 0.1) 0 1px 3px 0;
|
||||
transition: left 280ms cubic-bezier(0, 0, 0.2, 1);
|
||||
border-radius: 50%;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.disabled {
|
||||
border-color: #eaeaea;
|
||||
background-color: #fafafa;
|
||||
}
|
||||
|
||||
.disabled > .inner {
|
||||
background-color: #eaeaea;
|
||||
}
|
||||
|
||||
.disabled.checked {
|
||||
border-color: #888;
|
||||
background-color: #888;
|
||||
}
|
||||
|
||||
.checked {
|
||||
background-color: #0070f3;
|
||||
}
|
||||
|
||||
.checked > .inner {
|
||||
left: calc(100% - (.835rem - 2px));
|
||||
box-shadow: none;
|
||||
}
|
||||
</style></label><label class=\\"\\"><input type=\\"checkbox\\"><div class=\\"toggle \\"><span class=\\"inner\\"></span></div><style>
|
||||
label {
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
display: inline-block;
|
||||
vertical-align: center;
|
||||
white-space: nowrap;
|
||||
user-select: none;
|
||||
padding: 3px 0;
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
input {
|
||||
overflow: hidden;
|
||||
visibility: hidden;
|
||||
height: 0;
|
||||
opacity: 0;
|
||||
width: 0;
|
||||
position: absolute;
|
||||
background-color: transparent;
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
.toggle {
|
||||
height: .835rem;
|
||||
width: 1.67rem;
|
||||
border-radius: .835rem;
|
||||
transition-delay: 0.12s;
|
||||
transition-duration: 0.2s;
|
||||
transition-property: background, border;
|
||||
transition-timing-function: cubic-bezier(0, 0, 0.2, 1);
|
||||
position: relative;
|
||||
border: 1px solid transparent;
|
||||
background-color: #eaeaea;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.inner {
|
||||
width: calc(.835rem - 2px);
|
||||
height: calc(.835rem - 2px);
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
left: 1px;
|
||||
box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px 0, rgba(0, 0, 0, 0.1) 0 1px 3px 0;
|
||||
transition: left 280ms cubic-bezier(0, 0, 0.2, 1);
|
||||
border-radius: 50%;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.disabled {
|
||||
border-color: #eaeaea;
|
||||
background-color: #fafafa;
|
||||
}
|
||||
|
||||
.disabled > .inner {
|
||||
background-color: #eaeaea;
|
||||
}
|
||||
|
||||
.disabled.checked {
|
||||
border-color: #888;
|
||||
background-color: #888;
|
||||
}
|
||||
|
||||
.checked {
|
||||
background-color: #0070f3;
|
||||
}
|
||||
|
||||
.checked > .inner {
|
||||
left: calc(100% - (.835rem - 2px));
|
||||
box-shadow: none;
|
||||
}
|
||||
</style></label><label class=\\"\\"><input type=\\"checkbox\\"><div class=\\"toggle \\"><span class=\\"inner\\"></span></div><style>
|
||||
label {
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
display: inline-block;
|
||||
vertical-align: center;
|
||||
white-space: nowrap;
|
||||
user-select: none;
|
||||
padding: 3px 0;
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
input {
|
||||
overflow: hidden;
|
||||
visibility: hidden;
|
||||
height: 0;
|
||||
opacity: 0;
|
||||
width: 0;
|
||||
position: absolute;
|
||||
background-color: transparent;
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
.toggle {
|
||||
height: .875rem;
|
||||
width: 1.75rem;
|
||||
border-radius: .875rem;
|
||||
transition-delay: 0.12s;
|
||||
transition-duration: 0.2s;
|
||||
transition-property: background, border;
|
||||
transition-timing-function: cubic-bezier(0, 0, 0.2, 1);
|
||||
position: relative;
|
||||
border: 1px solid transparent;
|
||||
background-color: #eaeaea;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.inner {
|
||||
width: calc(.875rem - 2px);
|
||||
height: calc(.875rem - 2px);
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
left: 1px;
|
||||
box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px 0, rgba(0, 0, 0, 0.1) 0 1px 3px 0;
|
||||
transition: left 280ms cubic-bezier(0, 0, 0.2, 1);
|
||||
border-radius: 50%;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.disabled {
|
||||
border-color: #eaeaea;
|
||||
background-color: #fafafa;
|
||||
}
|
||||
|
||||
.disabled > .inner {
|
||||
background-color: #eaeaea;
|
||||
}
|
||||
|
||||
.disabled.checked {
|
||||
border-color: #888;
|
||||
background-color: #888;
|
||||
}
|
||||
|
||||
.checked {
|
||||
background-color: #0070f3;
|
||||
}
|
||||
|
||||
.checked > .inner {
|
||||
left: calc(100% - (.875rem - 2px));
|
||||
box-shadow: none;
|
||||
}
|
||||
</style></label><label class=\\"\\"><input type=\\"checkbox\\"><div class=\\"toggle \\"><span class=\\"inner\\"></span></div><style>
|
||||
label {
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
display: inline-block;
|
||||
vertical-align: center;
|
||||
white-space: nowrap;
|
||||
user-select: none;
|
||||
padding: 3px 0;
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
input {
|
||||
overflow: hidden;
|
||||
visibility: hidden;
|
||||
height: 0;
|
||||
opacity: 0;
|
||||
width: 0;
|
||||
position: absolute;
|
||||
background-color: transparent;
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
.toggle {
|
||||
height: 1rem;
|
||||
width: 2rem;
|
||||
border-radius: 1rem;
|
||||
transition-delay: 0.12s;
|
||||
transition-duration: 0.2s;
|
||||
transition-property: background, border;
|
||||
transition-timing-function: cubic-bezier(0, 0, 0.2, 1);
|
||||
position: relative;
|
||||
border: 1px solid transparent;
|
||||
background-color: #eaeaea;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.inner {
|
||||
width: calc(1rem - 2px);
|
||||
height: calc(1rem - 2px);
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
left: 1px;
|
||||
box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px 0, rgba(0, 0, 0, 0.1) 0 1px 3px 0;
|
||||
transition: left 280ms cubic-bezier(0, 0, 0.2, 1);
|
||||
border-radius: 50%;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.disabled {
|
||||
border-color: #eaeaea;
|
||||
background-color: #fafafa;
|
||||
}
|
||||
|
||||
.disabled > .inner {
|
||||
background-color: #eaeaea;
|
||||
}
|
||||
|
||||
.disabled.checked {
|
||||
border-color: #888;
|
||||
background-color: #888;
|
||||
}
|
||||
|
||||
.checked {
|
||||
background-color: #0070f3;
|
||||
}
|
||||
|
||||
.checked > .inner {
|
||||
left: calc(100% - (1rem - 2px));
|
||||
box-shadow: none;
|
||||
}
|
||||
</style></label></div>"
|
||||
`;
|
||||
77
components/toggle/__tests__/index.test.tsx
Normal file
77
components/toggle/__tests__/index.test.tsx
Normal file
@@ -0,0 +1,77 @@
|
||||
import React from 'react'
|
||||
import { mount, ReactWrapper } from 'enzyme'
|
||||
import { Toggle } from 'components'
|
||||
import { nativeEvent, updateWrapper } from 'tests/utils'
|
||||
|
||||
const expectToggleIsChecked = (wrapper: ReactWrapper) => {
|
||||
expect(wrapper.find('.checked').length).not.toBe(0)
|
||||
}
|
||||
|
||||
const expectToggleIsUnChecked = (wrapper: ReactWrapper) => {
|
||||
expect(wrapper.find('.checked').length).toBe(0)
|
||||
}
|
||||
|
||||
describe('Toggle', () => {
|
||||
it('should render correctly', () => {
|
||||
const wrapper = mount(<Toggle />)
|
||||
expect(wrapper.html()).toMatchSnapshot()
|
||||
expect(() => wrapper.unmount()).not.toThrow()
|
||||
})
|
||||
|
||||
it('should work with different sizes', () => {
|
||||
const wrapper = mount(
|
||||
<div>
|
||||
<Toggle size="mini" />
|
||||
<Toggle size="small" />
|
||||
<Toggle size="medium" />
|
||||
<Toggle size="large" />
|
||||
</div>
|
||||
)
|
||||
expect(wrapper.html()).toMatchSnapshot()
|
||||
expect(() => wrapper.unmount()).not.toThrow()
|
||||
})
|
||||
|
||||
it('should set toggle follow checked prop', async () => {
|
||||
const wrapper = mount(<Toggle initialChecked={true} />)
|
||||
expectToggleIsChecked(wrapper)
|
||||
|
||||
wrapper.setProps({ checked: false })
|
||||
await updateWrapper(wrapper)
|
||||
expectToggleIsUnChecked(wrapper)
|
||||
|
||||
wrapper.setProps({ checked: true })
|
||||
await updateWrapper(wrapper)
|
||||
expectToggleIsChecked(wrapper)
|
||||
})
|
||||
|
||||
it('should trigger events when toggle changed', async () => {
|
||||
let checked = false
|
||||
const changeHandler = jest.fn()
|
||||
.mockImplementation(e => checked = e.target.checked)
|
||||
const wrapper = mount(<Toggle onChange={changeHandler} />)
|
||||
|
||||
wrapper.find('input').simulate('change', {
|
||||
...nativeEvent,
|
||||
target: { checked: true },
|
||||
})
|
||||
await updateWrapper(wrapper)
|
||||
expectToggleIsChecked(wrapper)
|
||||
|
||||
expect(changeHandler).toHaveBeenCalled()
|
||||
expect(checked).toEqual(true)
|
||||
})
|
||||
|
||||
it('should ignore events when toggle disabled', async () => {
|
||||
const changeHandler = jest.fn()
|
||||
const wrapper = mount(<Toggle onChange={changeHandler} disabled />)
|
||||
|
||||
wrapper.find('input').simulate('change', {
|
||||
...nativeEvent,
|
||||
target: { checked: true },
|
||||
})
|
||||
await updateWrapper(wrapper)
|
||||
expectToggleIsUnChecked(wrapper)
|
||||
|
||||
expect(changeHandler).not.toHaveBeenCalled()
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user