Encodera

Thanks for reading!

Donate to the site — we work hard for you.

Contents

Testing basics

An automated test is code that renders a component, performs user actions and checks the result. Tests run with one command and tell you right away if a change broke something. Vite projects usually use Vitest, and for Solid components there is the @solidjs/testing-library package.

Installation

npm install -D vitest jsdom @solidjs/testing-library

vitest runs the tests, jsdom imitates a browser inside Node.js, and the testing library renders components and finds elements the way a user sees them.

Setup

Add a test section to vite.config.js:

// vite.config.js
import { defineConfig } from 'vite';
import solidPlugin from 'vite-plugin-solid';
 
export default defineConfig({
  plugins: [solidPlugin()],
  server: { port: 3000 },
  test: {
    environment: 'jsdom',
  },
});

In package.json, add the line "test": "vitest" to the scripts section.

The first test

Let us check the counter from the lesson on signals. A test sits next to the component in a file ending in .test.jsx:

// src/components/Counter.test.jsx
import { describe, it, expect } from 'vitest';
import { render, screen, fireEvent } from '@solidjs/testing-library';
import Counter from './Counter';
 
describe('Counter', () => {
  it('increments the number on click', () => {
    render(() => <Counter />);
 
    fireEvent.click(screen.getByRole('button', { name: 'Mark done' }));
 
    expect(screen.getByText('Tasks done: 1')).toBeTruthy();
  });
});
npm test

The terminal shows a line with a green check mark and the test name. Vitest keeps watching the files and reruns the test on every save.

What happens here

LineMeaning
render(() => <Counter />)Render the component; as in src/index.jsx, a function is passed
screen.getByRole(...)Find the button by its role and label
fireEvent.click(...)Click it
screen.getByText(...)Find an element with the text; if it is missing, the test fails

Signals in Solid update the DOM immediately, so the check can come right after the click, without waiting.

Testing data

Functions without UI are even easier to test — no render needed. Suppose you moved the filter logic from the Switch lesson into src/utils/filterTodos.js as a function filterTodos(todos, filter):

// src/utils/filterTodos.test.js
import { it, expect } from 'vitest';
import { filterTodos } from './filterTodos';
 
it('keeps only active tasks', () => {
  const todos = [{ id: 1, done: true }, { id: 2, done: false }];
 
  expect(filterTodos(todos, 'active')).toEqual([{ id: 2, done: false }]);
});

Such checks are fast and a good place to start.

Common mistake

Finding elements by classes or markup structure, such as container.querySelector('.btn'). Any layout change breaks such a test, although nothing changed for the user. Find elements by role and text — the way a person finds them.

Thanks for reading!

Donate to the site — we work hard for you.