Skip to content

Commit

Permalink
fix(clipboard): prevent default behavior on copy/cut (#866)
Browse files Browse the repository at this point in the history
  • Loading branch information
ph-fritsche committed Mar 1, 2022
1 parent d3d71ac commit 5423094
Show file tree
Hide file tree
Showing 8 changed files with 61 additions and 23 deletions.
11 changes: 6 additions & 5 deletions src/clipboard/copy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,12 @@ export async function copy(this: Instance) {
return
}

this.dispatchUIEvent(target, 'copy', {
clipboardData,
})

if (this[Config].writeToClipboard) {
if (
this.dispatchUIEvent(target, 'copy', {
clipboardData,
}) &&
this[Config].writeToClipboard
) {
await writeDataTransferToClipboard(doc, clipboardData)
}

Expand Down
24 changes: 8 additions & 16 deletions src/clipboard/cut.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,5 @@
import {Config, Instance} from '../setup'
import {
copySelection,
input,
isEditable,
writeDataTransferToClipboard,
} from '../utils'
import {copySelection, writeDataTransferToClipboard} from '../utils'

export async function cut(this: Instance) {
const doc = this[Config].document
Expand All @@ -16,16 +11,13 @@ export async function cut(this: Instance) {
return
}

this.dispatchUIEvent(target, 'cut', {
clipboardData,
})

if (isEditable(target)) {
input(this[Config], target, '', 'deleteByCut')
}

if (this[Config].writeToClipboard) {
await writeDataTransferToClipboard(doc, clipboardData)
if (
this.dispatchUIEvent(target, 'cut', {
clipboardData,
}) &&
this[Config].writeToClipboard
) {
await writeDataTransferToClipboard(target.ownerDocument, clipboardData)
}

return clipboardData
Expand Down
10 changes: 10 additions & 0 deletions src/event/behavior/cut.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import {input, isEditable} from '../../utils'
import {behavior} from './registry'

behavior.cut = (event, target, config) => {
return () => {
if (isEditable(target)) {
input(config, target, '', 'deleteByCut')
}
}
}
1 change: 1 addition & 0 deletions src/event/behavior/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import './click'
import './cut'
import './keydown'
import './keypress'
import './keyup'
Expand Down
2 changes: 1 addition & 1 deletion tests/_helpers/listeners.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ export function addListeners(
eventHandlerCalls = []
}

function eventWasFired(eventType: keyof GlobalEventHandlersEventMap) {
function eventWasFired(eventType: keyof DocumentEventMap) {
return getEvents(eventType).length > 0
}

Expand Down
16 changes: 16 additions & 0 deletions tests/clipboard/copy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,22 @@ test('copy on empty selection does nothing', async () => {
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', {
Expand Down
17 changes: 17 additions & 0 deletions tests/clipboard/cut.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,23 @@ test('cut on empty selection does nothing', async () => {
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('cut', e => e.preventDefault())
await window.navigator.clipboard.writeText('foo')

await user.cut()
expect(eventWasFired('cut')).toBe(true)
expect(getEvents('cut')[0].clipboardData?.getData('text')).toBe('bar')
expect(eventWasFired('input')).toBe(false)
await expect(window.navigator.clipboard.readText()).resolves.toBe('foo')
})

describe('without Clipboard API', () => {
beforeEach(() => {
Object.defineProperty(window.navigator, 'clipboard', {
Expand Down
3 changes: 2 additions & 1 deletion tests/event/behavior/keypress.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@ cases(
expect(getEvents('input')[0]).toHaveProperty('inputType', inputType)
if (expectedValue !== undefined) {
expect(element).toHaveValue(expectedValue)
} else if (expectedHtml !== undefined) {
}
if (expectedHtml !== undefined) {
expect(element).toHaveProperty('innerHTML', expectedHtml)
}
},
Expand Down

0 comments on commit 5423094

Please sign in to comment.