enzyme-adapter-preact-pure
Version:
Enzyme adapter for Preact
142 lines (141 loc) • 4.44 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.withShallowRendering = exports.shallowRenderVNodeTree = exports.isShallowRendered = exports.getRealType = void 0;
const preact_1 = require("preact");
const compat_js_1 = require("./compat.js");
/**
* Map of component function to replacement stub function used when shallow
* rendering.
*/
const shallowRenderComponents = new Map();
/**
* Global flag indicating whether shallow rendering is active.
*/
let shallowRenderActive = false;
let shallowRenderHookInstalled = false;
function getDisplayName(type) {
return type.displayName || type.name;
}
/**
* Return the real component type of a component instance created by
* shallow rendering.
*/
function getRealType(component) {
const c = component;
const ctor = c.constructor;
if (ctor.originalType) {
return ctor.originalType;
}
else {
return null;
}
}
exports.getRealType = getRealType;
/**
* Return true if a value is something that can be returned from a render
* function.
*/
function isRenderable(value) {
return (value === null ||
Array.isArray(value) ||
typeof value == 'number' ||
typeof value === 'string' ||
(typeof value === 'object' && value.type !== undefined));
}
/**
* Create a dummy component to replace an existing component in rendered output.
*
* The dummy renders nothing but has the same display name as the original.
* This is used to implement shallow rendering by replacing the real component
* during shallow renders.
*/
function makeShallowRenderComponent(type) {
function ShallowRenderStub({ children }) {
// Preact can render fragments, so we can return the children directly.
//
// There is an exception for `children` values which are not directly
// renderable but need to be processed by the component being stubbed.
// For example, a function used as part of the "render prop" pattern
// (https://reactjs.org/docs/render-props.html).
return isRenderable(children) ? children : null;
}
ShallowRenderStub.originalType = type;
ShallowRenderStub.displayName = getDisplayName(type);
return ShallowRenderStub;
}
/**
* Preact `options.vnode` hook that causes a component not to be rendered when
* shallow rendering is enabled.
*/
function shallowRenderVNode(vnode) {
if (typeof vnode.type === 'string' ||
vnode.type == null ||
(typeof preact_1.Fragment !== 'undefined' && vnode.type === preact_1.Fragment)) {
return;
}
let stub = shallowRenderComponents.get(vnode.type);
if (!stub) {
stub = makeShallowRenderComponent(vnode.type);
shallowRenderComponents.set(vnode.type, stub);
}
vnode.type = stub;
}
function installShallowRenderHook() {
if (shallowRenderHookInstalled) {
return;
}
const prevHook = preact_1.options.vnode;
preact_1.options.vnode = vnode => {
if (shallowRenderActive) {
shallowRenderVNode(vnode);
}
if (prevHook) {
prevHook(vnode);
}
};
shallowRenderHookInstalled = true;
}
function isVNode(obj) {
return Object(obj) === obj && typeof obj.type !== 'undefined';
}
/**
* Return true if a VNode has been modified to shallow-render.
*/
function isShallowRendered(vnode) {
if (vnode.type == null || typeof vnode.type === 'string') {
return false;
}
const type = vnode.type;
return typeof type.originalType === 'function';
}
exports.isShallowRendered = isShallowRendered;
/**
* Convert components in a VNode tree to shallow-render.
*/
function shallowRenderVNodeTree(vnode) {
shallowRenderVNode(vnode);
(0, compat_js_1.childElements)(vnode).forEach(c => {
if (isVNode(c)) {
shallowRenderVNodeTree(c);
}
});
}
exports.shallowRenderVNodeTree = shallowRenderVNodeTree;
/**
* Invoke `fn` with shallow rendering enabled in Preact.
*
* During the execution of `fn`, any function or class component elements
* created by Preact's `h` function will be modified to only render a placeholder
* instead of the real component.
*/
function withShallowRendering(fn) {
installShallowRenderHook();
try {
shallowRenderActive = true;
fn();
}
finally {
shallowRenderActive = false;
}
}
exports.withShallowRendering = withShallowRendering;