-
Notifications
You must be signed in to change notification settings - Fork 251
/
Copy pathcopy.ts
112 lines (87 loc) Β· 3.19 KB
/
copy.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
import userEvent from '#src'
import {render, setup} from '#testHelpers'
test('copy selected value', async () => {
const {getEvents, user} = setup<HTMLInputElement>(
`<input value="foo bar baz"/>`,
{
selection: {anchorOffset: 4, focusOffset: 7},
},
)
const dt = await user.copy()
expect(dt?.getData('text')).toBe('bar')
expect(getEvents('copy')).toHaveLength(1)
await expect(window.navigator.clipboard.readText()).resolves.toBe('bar')
})
test('copy selected text outside of editable', async () => {
const {getEvents, user} = setup(`<div tabindex="-1">foo bar baz</div>`, {
selection: {focusNode: '//text()', anchorOffset: 1, focusOffset: 5},
})
const dt = await user.copy()
expect(dt?.getData('text')).toBe('oo b')
expect(getEvents('copy')).toHaveLength(1)
await expect(window.navigator.clipboard.readText()).resolves.toBe('oo b')
})
test('copy selected text in contenteditable', async () => {
const {getEvents, user} = setup(`<div contenteditable>foo bar baz</div>`, {
selection: {focusNode: '//text()', anchorOffset: 1, focusOffset: 5},
})
const dt = await user.copy()
expect(dt?.getData('text')).toBe('oo b')
expect(getEvents('copy')).toHaveLength(1)
await expect(window.navigator.clipboard.readText()).resolves.toBe('oo b')
})
test('copy on empty selection does nothing', async () => {
const {getEvents, user} = setup(`<input/>`)
await window.navigator.clipboard.writeText('foo')
await user.copy()
await expect(window.navigator.clipboard.readText()).resolves.toBe('foo')
expect(getEvents()).toHaveLength(0)
})
test('prevent default behavior per event handler', async () => {
const {element, eventWasFired, getEvents, user} = setup(
`<input value="bar"/>`,
{
selection: {anchorOffset: 0, focusOffset: 3},
},
)
element.addEventListener('copy', e => e.preventDefault())
await window.navigator.clipboard.writeText('foo')
await user.copy()
expect(eventWasFired('copy')).toBe(true)
expect(getEvents('copy')[0].clipboardData?.getData('text')).toBe('bar')
await expect(window.navigator.clipboard.readText()).resolves.toBe('foo')
})
describe('without Clipboard API', () => {
beforeEach(() => {
Object.defineProperty(window.navigator, 'clipboard', {
value: undefined,
configurable: true,
})
})
test('reject if trying to use missing API', async () => {
render<HTMLInputElement>(`<input value="foo bar baz"/>`, {
selection: {anchorOffset: 4, focusOffset: 7},
})
await expect(
userEvent.copy({writeToClipboard: true}),
).rejects.toThrowErrorMatchingInlineSnapshot(
`The Clipboard API is unavailable.`,
)
})
test('skip using missing API', async () => {
render<HTMLInputElement>(`<input value="foo bar baz"/>`, {
selection: {anchorOffset: 4, focusOffset: 7},
})
const dt = await userEvent.copy()
expect(dt?.getData('text/plain')).toBe('bar')
})
})
describe('on shadow DOM', () => {
test('copy in an input element', async () => {
const {user} = setup('<shadow-input value="test"></shadow-input>', {
selection: {anchorOffset: 0, focusOffset: 4},
})
const data = await user.copy()
expect(data?.getData('text')).toEqual('test')
})
})