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
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