DEV Community

Cover image for Riot Component Unit Test with Vitest (Node env)
Steeve
Steeve

Posted on • Edited on

Riot Component Unit Test with Vitest (Node env)

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); read this article to learn more

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 + Riot-SSR: Next Generation Testing Framework

Vite is used as a development server to provide real-time rendering of my Riot application. Using Vitest for testing offers 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 
Enter fullscreen mode Exit fullscreen mode

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

{ "scripts": { "test": "vitest" } } 
Enter fullscreen mode Exit fullscreen mode

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 
Enter fullscreen mode Exit fullscreen mode

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

As 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>') }) }); 
Enter fullscreen mode Exit fullscreen mode

Code Breakdown:

  1. Modules and the component are loaded.
  2. 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
  3. 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.
  4. 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 
Enter fullscreen mode Exit fullscreen mode

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) 
Enter fullscreen mode Exit fullscreen mode

✅ The test succeeds; everything is good. Vitest is listening to changes, and it will print the result when a new test is created.

Advanced Tests

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

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) }) 
Enter fullscreen mode Exit fullscreen mode

Code Details:

  1. First the expected HTML result is stored into a constant
  2. The Component is built with a props value: "Firstname"
  3. 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) }) 
Enter fullscreen mode Exit fullscreen mode

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

I covered another testing method in a JsDom environment, to compare the two solutions:

  • For extensive but verbose Riot testing: use a JsDom environment
  • For fast, no-brain but limited Riot testing: use a Node Server Environment with Riot-SSR

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

Have a great day! Cheers 🍻

Top comments (0)