Riot Component Unit Test with Vitest (Node env)

Rmag Breaking News

This article covers testing Riot Input components using Vitest and Riot/SSR in a Node environment.

A second method exists: Vitest into a JsDom environment (or HappyDom); I’ll cover the subject in another article.

Before going forward, ensure you have a base Riot+Vite project and have created at least one component. If not, you can read my previous article on creating an Input Component.

These articles form a series focusing on RiotJS paired with BeerCSS, designed to guide you through creating components and mastering best practices for building production-ready applications. I assume you have a foundational understanding of Riot; however, feel free to refer to the documentation if needed: https://riot.js.org/documentation/

Riot + Vitest: Next Generation Testing Framework

As I am using Vite as a development server to get a real-time rendering of my Riot application, using Vitest for testing brings many advantages:

A test runner that uses the same configuration as Vite (vite.config.js).
It provides a compatible Jest API (one of the most used test runners)
Performances: it uses Worker threads to run as much as possible in parallel.
Easy setup and configuration (almost none).

Add Vitest to your Riot project:

npm install -D vitest

To execute the test, add the following section to your package.json:

{
“scripts”: {
“test”: “vitest”
}
}

And that’s it for Vitest! If you need a specific configuration, add test property in your Vite config vite.config.js. Configuration documentation: https://vitest.dev/config/

Write a first Test with Riot-SSR

Our tests will use Riot SSR (Riot Server-Side Rendering) because it is a module that renders riot components on the server.

First, add Riot-SSR to your project:

npm i -D @riotjs/ssr

The module takes a component and renders it as HTML; we must assert if we don’t get the expected result.

The HTML rendering is only a String, so we can’t test Component events, such as value changes, button clicks, key types, etc. A Browser Dom environment, such as JsDom, is required to test Riot Component reactivity.

Here is the minimum test we can create with Vitest and Riot-SSR:

import { assert, describe, it } from vitest
import render from @riotjs/ssr

import cInput from ../components/c-input.riot

describe(Component c-input, () => {
it(should render the input without props, () => {
const html = render(c-input, cInput, {})

assert.strictEqual(html, <c-input><div class=”field border”><input value=”” type=”text”></div></c-input>)
})
});

Code Breakdown:

Modules and the component are loaded.
Vitest provides common utilities for testing, similar to Mocha and Jest:

describe() is used to define a group of tests

it() for defining a test

assert() for validating tests

The render() function takes 3 arguments:

First: The component name built as String
Second: The component module
Third: Optional props are properties passed to the components.

Validate the result of the rendered HTML as String with the assert.strictEqual(result, expected).

Now start the test through the NPM command:

npm run test

We get the following result:

DEV v1.4.0 /riot-beercss

✓ tests/c-input.test.js (1)
✓ Component c-input (1)
✓ should load a basic input without props

Test Files 1 passed (1)
Tests 1 passed (1)
Start at 13:41:34
Duration 242ms (transform 108ms, setup 0ms, collect 128ms, tests 6ms, environment 0ms, prepare 35ms)

✅ The test succeeds; everything is good. Vitest is listening to changes, and we can continue writing new tests and it will print the result on save .

Advanced Tests

The goal now is to try all input states by passing props to the components, render it, and it should render the expected result.

One test should validate one state of the input.

Let’s try testing a default value for the input:

it(should render the input with a default value, () => {
const _htmlExpected = <c-input><div class=”field border”><input value=”Firstname” type=”text”></div></c-input>;
const _html = render(c-input, cInput, { value: Firstname})

assert.strictEqual(_html, _htmlExpected)
})

Code Details:

First the expected HTML result is stored into a constant
The Component is built with a props value: “Firstname”

The result is validated with the assert expression. In this case, everything is fine.

Now we can replicate this testing method for all props and multiple props combined: Let’s create a rounded small input with a “Password” type, label, and an error.

it(should render multiple props: label, type, error and round, () => {
const _htmlExpected = <c-input><div class=”field border round invalid label”><input value=”” type=”password”><label>Password</label><span class=”error”>The password is too show, minimum 20 characters.</span></div></c-input>;
const _html = render(c-input, cInput, { label: Password, type: password, error: The password is too show, minimum 20 characters., round: true})

assert.strictEqual(_html, _htmlExpected)
})

Code Breakdown:

Multiple props are passed to the render() function
A constant is created with the expected HTML result based on the component’s logic.

The test pass ✅

Find all input tests the following GitHub repository:
https://github.com/steevepay/riot-beercss/blob/main/tests/c-input.test.js

Conclusion

Combining Riot-SSR with Vitest is a good method for quickly testing the rendering of Riot Components, but it does not provide a Browser for testing HTML events.

An article is coming for testing events of Riot components thanks to JsDOM + Vitest

Feel free to comment if you have questions or need help about RiotJS.

Have a great day! Cheers 🍻

Leave a Reply

Your email address will not be published. Required fields are marked *