Hotwire Discussion

Testing Stimulus, Jest

This is nice article about testing Stimulus + Jest

4 Likes

I was able to get going with your examples very well. Thank you for writing this up. Where I am now having trouble is when I have an element

<a id="anchor" href="#" data-action="foo.bar">dosomething</a>

and the foo controller#bar function uses fetch to get a response from the server and replace an item in the dom with the response

bar(event) {
  event.preventDefault();
  fetch(this.data.get("url"))
   .then(response => response.text())
   .then(data => this.itemTarget.innerHTML = data)
   .catch(error => console.log('Error ',error));
}

a jest test looks something like

it("fetches the url and calls #replaceItem with the response", () => {
  fetchMock.get(editAction, new Promise(res => res(formItem)));
  let anchor = document.getElementById("anchor");
  anchor.click();
  expect(fetchMock).toHaveBeenCalledWith(editAction);

  let item = document.getElementById("test-item");
  expect(item.innerHTML).toEqual(formItem);
  fetchMock.reset();
});

I can see that the foo method is being called after the click, but I cannot figure out the incantation to use either done, or async/await, etc. to get the item.innerHTML test to work (it comes back unchanged).

I was able to solve my own problem. Here is how I did it for posterity, using process.nextTick

it("fetches the url and calls #replaceItem with the response", () => {
  fetchMock.get(editAction, new Promise(res => res(formItem)));
  let anchor = document.getElementById("anchor");
  anchor.click();
  expect(fetchMock).toHaveBeenCalledWith(editAction);

  process.nextTick(() => {
    let item = document.getElementById("test-item");
    expect(item.innerHTML).toEqual(formItem);
    fetchMock.reset();
  });
});
1 Like