You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
156 lines
4.3 KiB
156 lines
4.3 KiB
"use strict"; |
|
|
|
Object.defineProperty(exports, "__esModule", { |
|
value: true |
|
}); |
|
exports.createEvent = createEvent; |
|
exports.fireEvent = fireEvent; |
|
|
|
var _config = require("./config"); |
|
|
|
var _helpers = require("./helpers"); |
|
|
|
var _eventMap = require("./event-map"); |
|
|
|
function fireEvent(element, event) { |
|
return (0, _config.getConfig)().eventWrapper(() => { |
|
if (!event) { |
|
throw new Error(`Unable to fire an event - please provide an event object.`); |
|
} |
|
|
|
if (!element) { |
|
throw new Error(`Unable to fire a "${event.type}" event - please provide a DOM element.`); |
|
} |
|
|
|
return element.dispatchEvent(event); |
|
}); |
|
} |
|
|
|
function createEvent(eventName, node, init, { |
|
EventType = 'Event', |
|
defaultInit = {} |
|
} = {}) { |
|
if (!node) { |
|
throw new Error(`Unable to fire a "${eventName}" event - please provide a DOM element.`); |
|
} |
|
|
|
const eventInit = { ...defaultInit, |
|
...init |
|
}; |
|
const { |
|
target: { |
|
value, |
|
files, |
|
...targetProperties |
|
} = {} |
|
} = eventInit; |
|
|
|
if (value !== undefined) { |
|
setNativeValue(node, value); |
|
} |
|
|
|
if (files !== undefined) { |
|
// input.files is a read-only property so this is not allowed: |
|
// input.files = [file] |
|
// so we have to use this workaround to set the property |
|
Object.defineProperty(node, 'files', { |
|
configurable: true, |
|
enumerable: true, |
|
writable: true, |
|
value: files |
|
}); |
|
} |
|
|
|
Object.assign(node, targetProperties); |
|
const window = (0, _helpers.getWindowFromNode)(node); |
|
const EventConstructor = window[EventType] || window.Event; |
|
let event; |
|
/* istanbul ignore else */ |
|
|
|
if (typeof EventConstructor === 'function') { |
|
event = new EventConstructor(eventName, eventInit); |
|
} else { |
|
// IE11 polyfill from https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent#Polyfill |
|
event = window.document.createEvent(EventType); |
|
const { |
|
bubbles, |
|
cancelable, |
|
detail, |
|
...otherInit |
|
} = eventInit; |
|
event.initEvent(eventName, bubbles, cancelable, detail); |
|
Object.keys(otherInit).forEach(eventKey => { |
|
event[eventKey] = otherInit[eventKey]; |
|
}); |
|
} // DataTransfer is not supported in jsdom: https://github.com/jsdom/jsdom/issues/1568 |
|
|
|
|
|
const dataTransferProperties = ['dataTransfer', 'clipboardData']; |
|
dataTransferProperties.forEach(dataTransferKey => { |
|
const dataTransferValue = eventInit[dataTransferKey]; |
|
|
|
if (typeof dataTransferValue === 'object') { |
|
/* istanbul ignore if */ |
|
if (typeof window.DataTransfer === 'function') { |
|
Object.defineProperty(event, dataTransferKey, { |
|
value: Object.getOwnPropertyNames(dataTransferValue).reduce((acc, propName) => { |
|
Object.defineProperty(acc, propName, { |
|
value: dataTransferValue[propName] |
|
}); |
|
return acc; |
|
}, new window.DataTransfer()) |
|
}); |
|
} else { |
|
Object.defineProperty(event, dataTransferKey, { |
|
value: dataTransferValue |
|
}); |
|
} |
|
} |
|
}); |
|
return event; |
|
} |
|
|
|
Object.keys(_eventMap.eventMap).forEach(key => { |
|
const { |
|
EventType, |
|
defaultInit |
|
} = _eventMap.eventMap[key]; |
|
const eventName = key.toLowerCase(); |
|
|
|
createEvent[key] = (node, init) => createEvent(eventName, node, init, { |
|
EventType, |
|
defaultInit |
|
}); |
|
|
|
fireEvent[key] = (node, init) => fireEvent(node, createEvent[key](node, init)); |
|
}); // function written after some investigation here: |
|
// https://github.com/facebook/react/issues/10135#issuecomment-401496776 |
|
|
|
function setNativeValue(element, value) { |
|
const { |
|
set: valueSetter |
|
} = Object.getOwnPropertyDescriptor(element, 'value') || {}; |
|
const prototype = Object.getPrototypeOf(element); |
|
const { |
|
set: prototypeValueSetter |
|
} = Object.getOwnPropertyDescriptor(prototype, 'value') || {}; |
|
|
|
if (prototypeValueSetter && valueSetter !== prototypeValueSetter) { |
|
prototypeValueSetter.call(element, value); |
|
} else { |
|
/* istanbul ignore if */ |
|
// eslint-disable-next-line no-lonely-if -- Can't be ignored by istanbul otherwise |
|
if (valueSetter) { |
|
valueSetter.call(element, value); |
|
} else { |
|
throw new Error('The given element does not have a value setter'); |
|
} |
|
} |
|
} |
|
|
|
Object.keys(_eventMap.eventAliasMap).forEach(aliasKey => { |
|
const key = _eventMap.eventAliasMap[aliasKey]; |
|
|
|
fireEvent[aliasKey] = (...args) => fireEvent[key](...args); |
|
}); |
|
/* eslint complexity:["error", 9] */ |