This repository has been archived on 2025-12-24. You can view files and clone it, but cannot push or open issues or pull requests.
site-template/ref/astro-embed/tests/utils/render.mjs
2025-03-07 14:59:06 +01:00

98 lines
3.1 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* eslint-disable no-console */
import { prettyDOM, queries } from '@testing-library/dom';
import { getComponentOutput } from 'astro-component-tester';
import { parseHTML } from 'linkedom';
import lzString from 'lz-string';
const { compressToEncodedURIComponent } = lzString;
/**
* Get a `JSDOM` instance for an Astro component
* @param path {string} Path to an Astro component to render (relative to monorepo root)
* @param [props] {Record<string, unknown>} Any props to pass to the component
* @returns A Promise for a `JSDOM` instance
*/
export const renderDOM = async (path, props) => {
const { raw } = await getComponentOutput(path, props);
return parseHTML(raw);
};
/**
* Render an Astro component to an interface matching
* `@testing-library/dom`s `screen` API.
* @param path {string} Path to an Astro component to render (relative to monorepo root)
* @param [props] {Record<string, unknown>} Any props to pass to the component
* @returns A `@testing-library/dom` “screen” containing the rendered component
*/
export const renderScreen = async (path, props) =>
getScreen(await renderDOM(path, props));
/**
* Create an interface matching `@testing-library/dom`s `screen`, but without
* needing a global DOM environment.
* @param container {Window}
* @returns {typeof import('@testing-library/dom').screen}
*/
function getScreen(container) {
const { document } = container.window;
/** @type {typeof import('@testing-library/dom').screen.debug} */
const debug = (element = document, maxLength, options) =>
Array.isArray(element)
? element.forEach((el) => logDOM(el, maxLength, options))
: logDOM(element, maxLength, options);
/** @type {typeof import('@testing-library/dom').screen.logTestingPlaygroundURL} */
const logTestingPlaygroundURL = (element = document.body) => {
if (!element || !('innerHTML' in element)) {
console.log(`The element you're providing isn't a valid DOM element.`);
return;
}
if (!element.innerHTML) {
console.log(`The provided element doesn't have any children.`);
return;
}
console.log(
`Open this URL in your browser\n\n${getPlaygroundUrl(element.innerHTML)}`
);
};
const fakeScreen =
/** @type {typeof import('@testing-library/dom').screen} */ ({
debug,
logTestingPlaygroundURL,
});
for (const [key, query] of Object.entries(queries)) {
fakeScreen[key] = (...args) =>
query(
/** @type {HTMLElement} */ (
/** @type {unknown} */ (container.window.document)
),
...args
);
}
return fakeScreen;
}
// Below are utilities borrowed from Testing Librarys screen implementation.
// See: https://github.com/testing-library/dom-testing-library/blob/main/src/screen.ts
/** @param {string} string */
function unindent(string) {
return string.replace(/[ \t]*[\n][ \t]*/g, '\n');
}
/** @param {string} value */
function encode(value) {
return compressToEncodedURIComponent(unindent(value));
}
/** @param {string} markup */
function getPlaygroundUrl(markup) {
return `https://testing-playground.com/#markup=${encode(markup)}`;
}
/** @param {Parameters<typeof prettyDOM>} args */
function logDOM(...args) {
console.log(prettyDOM(...args));
}