enzyme-adapter-preact-pure
Version:
Enzyme adapter for Preact
131 lines (130 loc) • 5.28 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
const preact_1 = require("preact");
const test_utils_1 = require("preact/test-utils");
const compat_js_1 = require("./compat.js");
const debounce_render_hook_js_1 = require("./debounce-render-hook.js");
const event_map_js_1 = require("./event-map.js");
const preact10_internals_js_1 = require("./preact10-internals.js");
const preact10_rst_js_1 = require("./preact10-rst.js");
const util_js_1 = require("./util.js");
function constructEvent(type, init) {
const meta = event_map_js_1.eventMap[type];
const defaultInit = meta?.defaultInit ?? {};
return new Event(type, {
...defaultInit,
...init,
});
}
class MountRenderer {
constructor(options = {}) {
(0, debounce_render_hook_js_1.installHook)();
this._container = options.container || document.createElement('div');
this._getNode = preact10_rst_js_1.getNode;
this._options = options;
}
render(el, context, callback) {
(0, test_utils_1.act)(() => {
if (!this._options.wrappingComponent) {
(0, compat_js_1.render)(el, this._container);
return;
}
// `this._options.wrappingComponent` is only available during mount-rendering,
// even though ShallowRenderer uses an instance of MountRenderer under the hood.
// For shallow-rendered components, we need to utilize `wrapWithWrappingComponent`.
const wrappedComponent = (0, preact_1.createElement)(this._options.wrappingComponent, this._options.wrappingComponentProps || null, el);
(0, compat_js_1.render)(wrappedComponent, this._container);
});
if (callback) {
callback();
}
}
unmount() {
// A custom tag name is used here to work around
// https://github.com/developit/preact/issues/1288.
(0, compat_js_1.render)((0, preact_1.h)('unmount-me', {}), this._container);
this._container.innerHTML = '';
}
getNode() {
(0, debounce_render_hook_js_1.flushRenders)();
const container = this._container;
if (
// If the root component rendered null then the only indicator that content
// has been rendered will be metadata attached to the container.
typeof (0, preact10_internals_js_1.getLastVNodeRenderedIntoContainer)(container) === 'undefined') {
return null;
}
return this._getNode(this._container);
}
simulateError(nodeHierarchy, rootNode, error) {
const errNode = nodeHierarchy[0];
const render = () => {
// Modify the stack to match where the error is thrown. This makes
// debugging easier.
error.stack = new Error().stack;
throw error;
};
(0, util_js_1.withReplacedMethod)(errNode.instance, 'render', render, () => {
(0, test_utils_1.act)(() => {
errNode.instance.forceUpdate();
});
});
}
simulateEvent(node, eventName, args = {}) {
let hostNode;
if (node.nodeType == 'host') {
hostNode = node.instance;
}
else if (this._options.simulateEventsOnComponents) {
const possibleHostNode = (0, util_js_1.nodeToHostNode)(node);
if (possibleHostNode == null) {
const name = (0, util_js_1.getDisplayName)(node);
throw new Error(`Cannot simulate event on "${name}" which is not a DOM element or contains no DOM element children. ` +
'Find a DOM element or Component that contains a DOM element in the output and simulate an event on that.');
}
hostNode = possibleHostNode;
}
else {
const name = (0, util_js_1.getDisplayName)(node);
throw new Error(`Cannot simulate event on "${name}" which is not a DOM element. ` +
'Find a DOM element in the output and simulate an event on that. ' +
'Or, enable the simulateEventsOnComponents option to enable this feature.');
}
// To be more faithful to a real browser, this should use the appropriate
// constructor for the event type. This implementation is good enough for
// many components though.
const { bubbles, composed, cancelable, ...extra } = args;
const init = {};
if (typeof bubbles === 'boolean') {
init.bubbles = bubbles;
}
if (typeof composed === 'boolean') {
init.composed = composed;
}
if (typeof cancelable === 'boolean') {
init.cancelable = cancelable;
}
const event = constructEvent(eventName, init);
Object.assign(event, extra);
(0, test_utils_1.act)(() => {
hostNode.dispatchEvent(event);
});
}
batchedUpdates(fn) {
fn();
}
container() {
return this._container;
}
wrapInvoke(callback) {
let result;
(0, test_utils_1.act)(() => {
result = callback();
});
return result;
}
getWrappingComponentRenderer() {
return this;
}
}
exports.default = MountRenderer;