refactor: export all hooks functions directly from main module

refactor: rename the modules to make sure tree-shaking works
This commit is contained in:
unix
2020-05-15 23:10:02 +08:00
parent b93acc8d75
commit 4e7b4cc57d
46 changed files with 82 additions and 57 deletions

View File

@@ -0,0 +1,57 @@
import { useClipboard } from 'components'
import { renderHook } from '@testing-library/react-hooks'
describe('UseClipboard', () => {
beforeAll(() => {
window.getSelection = jest.fn().mockImplementation(() => ({
removeAllRanges: jest.fn(),
addRange: jest.fn(),
}))
document.createRange = jest.fn().mockImplementation(() => ({
selectNode: jest.fn(),
}))
})
it('should work correctly', () => {
document.execCommand = jest.fn()
const { result } = renderHook(() => useClipboard())
result.current.copy('test')
expect(document.execCommand).toHaveBeenCalled()
;(document.execCommand as jest.Mock).mockClear()
})
it('should capture copy erros', () => {
const errorSpy = jest.spyOn(console, 'error').mockImplementation(() => {})
document.execCommand = jest.fn().mockImplementation(() => {
throw new Error('test')
})
const { result } = renderHook(() => useClipboard())
result.current.copy('space speace breaks $@#')
expect(errorSpy).toHaveBeenCalled()
;(document.execCommand as jest.Mock).mockClear()
errorSpy.mockRestore()
})
it('should work correctly without text', () => {
const errorSpy = jest.spyOn(console, 'error').mockImplementation(() => {})
document.execCommand = jest.fn()
const { result } = renderHook(() => useClipboard())
result.current.copy('')
expect(errorSpy).not.toHaveBeenCalled()
;(document.execCommand as jest.Mock).mockClear()
errorSpy.mockRestore()
})
it('should not throw errors when the browser does not support', () => {
window.getSelection = jest.fn().mockImplementation(() => undefined)
const errorSpy = jest.spyOn(console, 'error').mockImplementation(() => {})
document.execCommand = jest.fn()
const { result } = renderHook(() => useClipboard())
result.current.copy('test')
expect(errorSpy).not.toHaveBeenCalled()
;(document.execCommand as jest.Mock).mockClear()
;(window.getSelection as jest.Mock).mockClear()
errorSpy.mockRestore()
})
})

View File

@@ -0,0 +1,3 @@
import useClipboard from './use-clipboard'
export default useClipboard

View File

@@ -0,0 +1,54 @@
import usePortal from '../utils/use-portal'
import useWarning from '../utils/use-warning'
import { useCallback } from 'react'
export type UseClipboardOptions = {
onError: Function
}
export type UseClipboardResult = {
copy: (text: string) => void
}
const defaultOptions: UseClipboardOptions = {
onError: () => useWarning('Failed to copy.', 'use-clipboard'),
}
const useClipboard = (options: UseClipboardOptions = defaultOptions): UseClipboardResult => {
const el = usePortal('clipboard')
const copyText = (el: HTMLElement | null, text: string) => {
if (!el || !text) return
const selection = window.getSelection()
if (!selection) return
el.style.whiteSpace = 'pre'
el.textContent = text
const range = window.document.createRange()
selection.removeAllRanges()
range.selectNode(el)
selection.addRange(range)
try {
window.document.execCommand('copy')
} catch (e) {
options.onError && options.onError()
}
selection.removeAllRanges()
if (el) {
el.textContent = ''
}
}
const copy = useCallback(
(text: string) => {
copyText(el, text)
},
[el],
)
return { copy }
}
export default useClipboard