UNPKG

@nuxt/test-utils

Version:
116 lines (115 loc) 3.92 kB
import { i as wrapperSuspended, n as patchWrapperSetProps, t as cleanupAll } from "../suspended-DDMM5DdJ.mjs"; import { config, mount } from "@vue/test-utils"; import { page, server, utils } from "vitest/browser"; //#region src/browser/pure.ts const mountedWrappers = /* @__PURE__ */ new Set(); let idx = 0; function ensureTestIdAttribute(element) { const attributeId = server.config.browser.locators.testIdAttribute; if (!element.hasAttribute(attributeId)) element.setAttribute(attributeId, `__vitest_${idx++}__`); } /** * `render` allows you to mount any vue component within the vitest browser mode. * * ```ts * import { page } from 'vitest/browser' * import { render } from '@nuxt/test-utils/browser' * * it('can render', async () => { * const screen = await render(App, { route: '/' }) * * const title = screen.getByRole('heading') * await expect.element(title).toHaveTextContent('Index') * }) * * it('can render with page', async () => { * const screen = await page.render(App, { route: '/' }) * * const title = screen.getByRole('heading') * await expect.element(title).toHaveTextContent('Index') * }) * ``` * * @param component the component to be tested * @param options optional options to set up your component */ async function render(component, options = {}) { const { container, baseElement, wrapper } = await mountWrapperSuspended(component, options); ensureTestIdAttribute(container); ensureTestIdAttribute(baseElement); const { debug, getElementLocatorSelectors } = utils; const renderResult = { container, baseElement, locator: page.elementLocator(container), get setupState() { return wrapper.setupState; }, debug: (el = container, maxLength, options) => debug(el, maxLength, options), unmount: async () => { wrapper.unmount(); mountedWrappers.delete(wrapper); await mark(renderResult.locator, "nuxt.unmount", renderResult.unmount); }, emitted: ((eventName) => wrapper.emitted(eventName)), rerender: async (props) => { await wrapper.setProps(props); await mark(renderResult.locator, "nuxt.rerender", renderResult.rerender); }, ...getElementLocatorSelectors(container) }; return renderResult; } function cleanup() { mountedWrappers.forEach((wrapper) => { wrapper.unmount(); mountedWrappers.delete(wrapper); }); cleanupAll(); } async function mark(locator, name, fn) { if (!locator.mark) return; const error = new Error(name); if ("captureStackTrace" in Error) Error.captureStackTrace(error, fn); return locator.mark(name, error); } /** * `@vue/test-utils` mounts into a `div` of its own inside `attachTo`. Removing that div keeps the * rendered markup a direct child of the container, so locators and snapshots see the component's * own DOM. */ function unwrapNode(node) { if (node && typeof node.replaceWith === "function") node.replaceWith(...node.childNodes); } async function mountWrapperSuspended(component, options = {}) { const { container: containerOption, baseElement: baseElementOption, ...wrapperOptions } = options; const baseElement = baseElementOption || document.body; const createdContainer = containerOption ? void 0 : baseElement.appendChild(document.createElement("div")); const container = containerOption || createdContainer; const suspendedOptions = { ...wrapperOptions, attachTo: container }; const { wrapper, setProps, cleanup } = await wrapperSuspended(component, suspendedOptions, { wrapperFn: mount, suspendedHelperName: "BrowserSuspendedHelper", clonedComponentName: "BrowserSuspendedComponent", stubRouterLink: false }); patchWrapperSetProps(wrapper, setProps); const _unmount = wrapper.unmount.bind(wrapper); wrapper.unmount = () => { _unmount(); cleanup(); createdContainer?.remove(); }; mountedWrappers.add(wrapper); unwrapNode(wrapper.element.parentElement); return { container, baseElement, wrapper }; } //#endregion export { cleanup, config, render };