DEV Community

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

Posted on • Updated 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

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

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, 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)
    })
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)