API
Esta página fue traducida por PageTurner AI (beta). No está respaldada oficialmente por el proyecto. ¿Encontraste un error? Reportar problema →
Dado que esta biblioteca está inspirada en preact-testing-library, puedes consultar su página para obtener más información.
Existen varias diferencias clave que debes conocer.
render
La función render recibe una función que retorna un componente de Solid, en lugar de recibir simplemente el componente en sí.
const results = render(() => <YourComponent />, options)
Solid.js no vuelve a renderizar, solo ejecuta efectos secundarios activados por estados reactivos que modifican el DOM. Por lo tanto, no existe un método rerender. Puedes utilizar señales globales para manipular tu componente de prueba de manera que provoque su actualización.
Además de la API original, la función render de esta biblioteca de pruebas soporta una práctica opción location que configura un enrutador en memoria apuntando a la ubicación especificada. Dado que esta configuración no es síncrona, necesitas usar primero consultas asíncronas (findBy) después de implementarla:
it('uses params', async () => {
const App = () => (
<>
<Route path="/ids/:id" component={() => <p>Id: {useParams()?.id}</p>} />
<Route path="/" component={() => <p>Start</p>} />
</>
)
const {findByText} = render(() => <App />, {location: 'ids/1234'})
expect(await findByText('Id: 1234')).not.toBeFalsy()
})
Utiliza @solidjs/router, así que si prefieres un enrutador diferente, deberías considerar la opción wrapper en su lugar. Si intentas usar esta funcionalidad sin tener el paquete instalado, recibirás un mensaje de error.
renderHook
El estado reactivo externo de Solid.js no requiere elementos DOM para funcionar, por lo que nuestra llamada renderHook para probar hooks en el contexto de un componente (si tu hook no requiere el contexto de un componente, createRoot debería bastar para probar el comportamiento reactivo; por conveniencia, también tenemos createEffect, descrito en la sección Async methods) no incluye container, baseElement ni queries en sus opciones o valor de retorno. En cambio, incluye un owner para usar con runWithOwner si es necesario. También expone una función cleanup, aunque esta se llama automáticamente después de finalizar la prueba.
function renderHook<Args extends any[], Result>(
hook: (...args: Args) => Result,
options: {
initialProps?: Args,
wrapper?: Component<{ children: JSX.Element }>
}
) => {
result: Result;
owner: Owner | null;
cleanup: () => void;
}
Esto puede usarse para probar fácilmente un hook/primitivo:
const {result} = renderHook(createResult)
expect(result).toBe(true)
Si usas un wrapper con renderHook, asegúrate de que siempre retorne props.children - especialmente si estás usando un contexto con código asíncrono junto con <Show>, porque esto es necesario para obtener el valor del hook y solo se obtiene síncronamente una vez. De lo contrario, solo obtendrás undefined y te preguntarás por qué sucede esto.
renderDirective
Solid.js soporta directivas personalizadas, un patrón conveniente para vincular comportamientos personalizados a elementos. Por ello, también tenemos renderDirective, que amplía renderHook para tomar una directiva como primer argumento, aceptar un initialValue para el argumento y un targetElement (string, HTMLElement o función que retorna un HTMLElement) en las options. Además, retorna arg y setArg para leer y manipular el argumento de la directiva.
function renderDirective<
Arg extends any,
Elem extends HTMLElement
>(
directive: (ref: Elem, arg: Accessor<Arg>) => void,
options?: {
...renderOptions,
initialValue: Arg,
targetElement:
| Lowercase<Elem['nodeName']>
| Elem
| (() => Elem)
}
): Result & { arg: Accessor<Arg>, setArg: Setter<Arg> };
Esto permite pruebas de directivas muy eficientes y concisas:
const {asFragment, setArg} = renderDirective(myDirective)
expect(asFragment()).toBe('<div data-directive="works"></div>')
setArg('perfect')
expect(asFragment()).toBe('<div data-directive="perfect"></div>')
Métodos asíncronos
Los cambios reactivos en Solid.js son casi instantáneos, por lo que rara vez es necesario usar waitFor(…), await findByRole(…) u otras consultas asíncronas para probar el resultado renderizado, excepto para transiciones, suspense, recursos y navegación del enrutador.
Solid.js gestiona efectos secundarios con diferentes variantes de createEffect. Si bien puedes usar waitFor para probar efectos asíncronos, este utiliza polling en lugar de permitir que la reactividad de Solid active el siguiente paso. Para simplificar las pruebas de estos efectos asíncronos, tenemos un asistente testEffect que complementa los hooks para directivas y hooks:
testEffect(fn: (done: (result: T) => void) => void, owner?: Owner): Promise<T>
// use it like this:
test("testEffect allows testing an effect asynchronously", () => {
const [value, setValue] = createSignal(0);
return testEffect(done => createEffect((run: number = 0) => {
if (run === 0) {
expect(value()).toBe(0);
setValue(1);
} else if (run === 1) {
expect(value()).toBe(1);
done();
}
return run + 1;
}));
});
Permite ejecutar el efecto dentro de un propietario definido que se recibe como
segundo argumento opcional. Esto puede ser útil en combinación con renderHook,
que proporciona un campo owner en su resultado. El valor retornado es una Promise
con el valor pasado al callback done(). Puedes esperar el resultado con await
para realizar más aserciones o devolverlo directamente a tu test runner.
Problemas conocidos
Si estás usando vitest, los tests podrían fallar porque los paquetes solid-js y @solidjs/router (si se usan) deben cargarse solo una vez, pero podrían cargarse tanto a través del servidor interno de vite como a través de node. Errores típicos que ocurren por esto son que dispose resulta indefinido o que el router no pudo cargarse.
Desde la versión 2.8.2, nuestro plugin de vite ha adquirido la capacidad de configurar todo para testing, por lo que solo deberías necesitar configuración adicional para globales, cobertura, etc.