Add a doc about unit testing Stimulus controllers

Hey Stimulus maintainers, it would be great to have a section about unit testing on the Stimulus handbook web site. So people don’t spend too much time to figure it out on their own. Here is what I came up with for Jest. Is there a better way to do this?

hello_controller.js

import { Controller } from '@hotwired/stimulus';

export default class extends Controller {
  connect() {
    this.element.textContent = 'Hello World!';
  }
}

hello_controller.spec.js (jest/jest-dom unit test)

import HelloController from './hello_controller';
import { Application } from '@hotwired/stimulus';

describe('HelloController', () => {
  beforeEach(() => {
    document.body.innerHTML = '<div data-controller="hello" />';
    window.Stimulus = Application.start();
    Stimulus.register('hello', HelloController);
  });

  it('shows hello world', () => {
    const el = document.querySelector('[data-controller="hello"]');
    expect(el).toHaveTextContent('Hello World!');
  });
});

Stop Stimulus

Add the teardown, in setup-jest.js, added to setupFilesAfterEnv Jest setting:

afterEach(() => {
  if (window.Stimulus) {
    Stimulus.stop();
    delete window.Stimulus;
  }
});
5 Likes

Our approach is the same, although you might be able to avoid the teardown by using beforeAll().

import HelloController from './hello_controller';
import { Application } from '@hotwired/stimulus';

describe('HelloController', () => {
  beforeAll(() => {
    window.Stimulus = Application.start();
    Stimulus.register('hello', HelloController);
  });

  beforeEach(() => {
    document.body.innerHTML = '<div data-controller="hello" />';
  });

  it('shows hello world', () => {
    const el = document.querySelector('[data-controller="hello"]');
    expect(el).toHaveTextContent('Hello World!');
  });
});
1 Like

For those who are looking for a minimalistic node-based runtime allowing to execute unit/integration tests for Stimulus Controllers, I wrote a short article about Testing Stimulus