@igor.dvlpr/astro-render-component
Version:
š¤ Plug-and-play Astro component renderer for fast, zero-config testing in any DOM-like JS/TS environment. š¬
47 lines (46 loc) ⢠2 kB
JavaScript
// Author: Igor DimitrijeviÄ (@igorskyflyer)
import { experimental_AstroContainer as AstroContainer } from 'astro/container';
/**
* Renders an Astro component to a `DocumentFragment` in a DOM-like environment.
*
* This utility is primarily intended for testing or server-side rendering scenarios
* where a simulated DOM (e.g., `happy-dom`) is available. It instantiates
* an `AstroContainer`, renders the component to an HTML string, and parses it into
* a `DocumentFragment` for further inspection or manipulation.
*
* @param component - The Astro component to render.
* @param options - Optional rendering configuration passed to the container (e.g., props, slots).
* @returns A Promise that resolves to a `DocumentFragment` containing the rendered output.
*
* @throws Will throw if executed in a non-DOM environment (e.g., Node.js without happy-dom`).
* @throws Will throw if the component fails to render.
*
* @example
* ``` ts
* // @āvitest-environment happy-dom
* import { renderAstroComponent } from '@igor.dvlpr/astro-render-component'
* import MyComponent from '../components/MyComponent.astro'
* import { expect } from 'vitest'
*
* const fragment = await renderAstroComponent(MyComponent, { props: { title: 'Hello' } })
* expect(fragment.querySelector('h1')?.textContent).toBe('Hello')
* ```
*/
export async function renderAstroComponent(component, options = {}) {
if (typeof document === 'undefined') {
throw new Error('renderAstroComponent requires a DOM-like environment (e.g., happy-dom)');
}
try {
const container = await AstroContainer.create();
const result = await container.renderToString(component, options);
const template = document.createElement('template');
template.innerHTML = result;
return template.content;
}
catch (err) {
if (err instanceof Error) {
throw new Error(`Failed to render Astro component: ${err.message}`);
}
throw err;
}
}