forked from nodejs/nodejs.dev
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
chore: add new hook
useCopyToClipboard
(nodejs#3109)
* Chore: add new hook `useCopyToClipboard` * Chore: replace util with hook * Chore: remove util * CHore: update delay * Chore: update format * Chore: update test * Chore: fix nits * Chore: fix nits
- Loading branch information
1 parent
568b952
commit 2e4bc25
Showing
6 changed files
with
114 additions
and
100 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
import React from 'react'; | ||
import { render, fireEvent, screen, waitFor } from '@testing-library/react'; | ||
import { useCopyToClipboard } from '../useCopyToClipboard'; | ||
|
||
describe('useCopyToClipboard', () => { | ||
const HookRenderer = ({ text }: { text: string }): JSX.Element => { | ||
const [copied, copyText] = useCopyToClipboard(); | ||
|
||
return ( | ||
<button onClick={() => copyText(text)} type="button"> | ||
{copied ? 'copied' : 'copy'} | ||
</button> | ||
); | ||
}; | ||
|
||
it('should have `copy` text when failed', async () => { | ||
const navigatorClipboardWriteTextSpy = jest | ||
.fn() | ||
.mockImplementation(() => Promise.reject()); | ||
|
||
Object.defineProperty(window.navigator, 'clipboard', { | ||
writable: true, | ||
value: { | ||
writeText: navigatorClipboardWriteTextSpy, | ||
}, | ||
}); | ||
|
||
render(<HookRenderer text="test copy" />); | ||
const button = screen.getByRole('button'); | ||
fireEvent.click(button); | ||
expect(button).toHaveTextContent('copy'); | ||
}); | ||
|
||
it('should change to `copied` when copy succeeded', async () => { | ||
jest.useFakeTimers(); | ||
const navigatorClipboardWriteTextSpy = jest | ||
.fn() | ||
.mockImplementation(() => Promise.resolve()); | ||
|
||
Object.defineProperty(window.navigator, 'clipboard', { | ||
writable: true, | ||
value: { | ||
writeText: navigatorClipboardWriteTextSpy, | ||
}, | ||
}); | ||
|
||
render(<HookRenderer text="test copy" />); | ||
const button = screen.getByRole('button'); | ||
fireEvent.click(button); | ||
await waitFor(() => { | ||
expect(button).toHaveTextContent('copied'); | ||
}); | ||
jest.advanceTimersByTime(3000); | ||
await waitFor(() => { | ||
expect(button).toHaveTextContent('copy'); | ||
}); | ||
}); | ||
|
||
it('should call clipboard API with `test` once', () => { | ||
const navigatorClipboardWriteTextSpy = jest | ||
.fn() | ||
.mockImplementation(() => Promise.resolve()); | ||
|
||
Object.defineProperty(window.navigator, 'clipboard', { | ||
writable: true, | ||
value: { | ||
writeText: navigatorClipboardWriteTextSpy, | ||
}, | ||
}); | ||
|
||
render(<HookRenderer text="test" />); | ||
const button = screen.getByRole('button'); | ||
fireEvent.click(button); | ||
expect(navigatorClipboardWriteTextSpy).toHaveBeenCalledTimes(1); | ||
expect(navigatorClipboardWriteTextSpy).toHaveBeenCalledWith('test'); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
import { useEffect, useState } from 'react'; | ||
|
||
const copyToClipboard = (value: string) => { | ||
if (typeof window === 'undefined') { | ||
return Promise.resolve(false); | ||
} | ||
|
||
return navigator.clipboard | ||
.writeText(value) | ||
.then(() => true) | ||
.catch(() => false); | ||
}; | ||
|
||
export const useCopyToClipboard = (): [boolean, (text: string) => void] => { | ||
const [copied, setCopied] = useState(false); | ||
|
||
const copyText = (text: string) => copyToClipboard(text).then(setCopied); | ||
|
||
useEffect(() => { | ||
if (!copied) { | ||
return undefined; | ||
} | ||
|
||
const timerId = setTimeout(() => setCopied(false), 3000); | ||
|
||
return () => clearTimeout(timerId); | ||
}, [copied]); | ||
|
||
return [copied, copyText]; | ||
}; |
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.