Skip to content

Instantly share code, notes, and snippets.

@robertknight
Created April 1, 2017 09:15
Show Gist options
  • Star 8 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save robertknight/88e9d10cff9269c55d453e5fb8364f47 to your computer and use it in GitHub Desktop.
Save robertknight/88e9d10cff9269c55d453e5fb8364f47 to your computer and use it in GitHub Desktop.
Shallow rendering implementation for Preact
import { options, render } from 'preact';
import { ATTR_KEY } from 'preact/src/constants';
/**
* Returns the input properties that were passed to an element when it was
* rendered.
*
* See `shallowRender` documentation for usage example.
*/
export function propsForElement(el) {
if (!el) {
throw new Error('Supplied element is null. Is the element in the render output?');
}
return el[ATTR_KEY] || {};
}
/**
* Perform a "shallow render" of a Preact component.
*
* This renders the output of a component's render() method without recursively
* rendering any other components referenced by that output. Instead any
* components referenced in the output are rendered as if they were DOM elements
* with the custom tag name `component-${name}`.
*
* This allows you to test the render of a component without executing the
* render code for any child components. Instead tests that use shallow
* rendering test that the child components were rendered in the expected places
* and were passed the expected inputs.
*
* Unlike React's Shallow Rendering, this does require a DOM.
*
* Example usage:
*
* function Button({ label }) {
* return <button><Label label={label}/></button>;
* }
*
* const el = shallowRender(<Button label="some-label"/>, container);
* const labelEl = el.querySelector('component-label');
* assert.deepEqual(propsForElement(labelEl), { label: 'some-label' });
*/
export default function shallowRender(preactEl, domEl) {
// Override the `vnode` hook to transform composite components in the render
// output into DOM elements.
const oldVnodeHook = options.vnode;
const vnodeHook = (node) => {
if (oldVnodeHook) {
oldVnodeHook(node);
}
if (typeof node.nodeName === 'string') {
return;
}
// Prepend `component-` prefix so that the element name will not clash with
// ordinary HTML elements.
node.nodeName = 'component-' + node.nodeName.name; // eslint-disable-line no-param-reassign
};
try {
options.vnode = vnodeHook;
const el = render(preactEl, domEl);
options.vnode = oldVnodeHook;
return el;
} catch (err) {
options.vnode = oldVnodeHook;
throw err;
}
}
@asolove
Copy link

asolove commented Apr 1, 2017

Nice. 👍

@developit
Copy link

how did I not see this before

@athulmurali
Copy link

import { ATTR_KEY } from 'preact/src/constants';
Can you please share what the constants are ? @robertknight

@robertknight
Copy link
Author

That constant doesn't exist in Preact any more. https://github.com/preactjs/enzyme-adapter-preact-pure has a working implementation of shallow rendering for Preact (see ShallowRenderer.ts), though I recommend using the "full" rendering mode instead.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment