Skip to content

Instantly share code, notes, and snippets.

@sand4rt
Created December 2, 2021 20:50
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sand4rt/5da4dda9b1aec636c92b83b83cc95aee to your computer and use it in GitHub Desktop.
Save sand4rt/5da4dda9b1aec636c92b83b83cc95aee to your computer and use it in GitHub Desktop.
Vue Testing Library renderAsyc suspense workaround
/**
* WARNING 01-12-2021: Vue testing library doesn't support <Suspense> see:
* https://github.com/testing-library/vue-testing-library/issues/230
*
* The code below is copied from vue testing library
* and modified to support <Suspense>:
* https://github.com/testing-library/vue-testing-library/blob/main/src/render.js
*/
import { mount, flushPromises } from '@vue/test-utils';
import { h, defineComponent, Suspense } from 'vue';
import {
getQueriesForElement,
prettyDOM,
RenderOptions,
RenderResult,
} from '@/utils-tests/testing-library';
const mountedWrappers = new Set();
async function renderAsync(
Component: any,
{
store = null,
routes = null,
container: customContainer,
baseElement: customBaseElement,
...mountOptions
}: RenderOptions = {}
): Promise<RenderResult> {
const div = document.createElement('div');
const baseElement = customBaseElement || customContainer || document.body;
const container = customContainer || baseElement.appendChild(div);
if (store || routes) {
console.warn(`Providing 'store' or 'routes' options is no longer available.
You need to create a router/vuex instance and provide it through 'global.plugins'.
Check out the test examples on GitHub for further details.`);
}
const { props, slots, ...restMountingOptions } = mountOptions;
const wrapper = mount(
defineComponent({
render() {
return h(Suspense, null, {
default: h(Component, props, slots),
});
},
}),
{
attachTo: container,
...restMountingOptions,
} as RenderOptions
);
await flushPromises();
// this removes the additional "data-v-app" div node from VTU:
// https://github.com/vuejs/vue-test-utils-next/blob/master/src/mount.ts#L196-L213
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
unwrapNode(wrapper.parentElement);
mountedWrappers.add(wrapper);
return {
container,
baseElement,
debug: (el = baseElement, maxLength, options) =>
Array.isArray(el)
? el.forEach((e) =>
console.log(
prettyDOM(e as any, maxLength, options as any)
)
)
: console.log(prettyDOM(el as any, maxLength, options as any)),
unmount: () => wrapper.unmount(),
html: () => wrapper.html(),
emitted: () => wrapper.emitted(),
rerender: (props) => wrapper.setProps(props as any),
...getQueriesForElement(baseElement as HTMLElement),
} as RenderResult;
}
function unwrapNode(node: HTMLElement) {
node.replaceWith(...node.childNodes);
}
function cleanup() {
mountedWrappers.forEach(cleanupAtWrapper);
}
function cleanupAtWrapper(wrapper: any) {
if (
wrapper.element.parentNode &&
wrapper.element.parentNode.parentNode === document.body
) {
document.body.removeChild(wrapper.element.parentNode);
}
wrapper.unmount();
mountedWrappers.delete(wrapper);
}
afterEach(() => {
cleanup();
});
export { renderAsync };
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment