dariusz
dariusz

Reputation: 593

Unit test for Svelte on:click event

Can anybody point me into right direction?

I'm expecting mock function to be called after click event was fired. What I've got is: Expected number of calls: 1 Received number of calls: 0

This are my components along with test file:

EventTestingWrapper.svelte

<script>
  export let testComponent
  export let clickHandler
</script>

<div data-testid="testing-wrapper">
  <svelte:component this={testComponent} on:click={clickHandler} />
</div>

Modal.svelte

<div
  class="modal-background"
  data-testid="modal-background"
  on:click|self={close}
>
lorem 
</div>

Modal.test.js

test('trying out test wrapper',()=>{

    const clickHandler = jest.fn();
  
    const { getByTestId } = render(EventTestingWrapper, {testComponent: Modal, clickHandler})
    const modalBackground = getByTestId('modal-background')
    const clickEvent = createEvent.click(modalBackground)

    fireEvent(modalBackground, clickEvent);

    expect(modalBackground).toBeInTheDocument()
    expect(clickHandler).toHaveBeenCalledTimes(1)
  })

Upvotes: 2

Views: 2202

Answers (2)

Janosh
Janosh

Reputation: 4732

This question is about jest but for people coming here in the future looking for a vitest solution, try this:

import Component from '$lib/MyComponent.svelte'
import { expect, test, vi } from 'vitest'

test(`invokes callback functions`, async () => {
  const keyup = vi.fn()
  const click = vi.fn()

  const instance = new Component({
    target: document.body,
    props: { foo: `bar` },
  })

  // register callbacks (same as passing them as `on:<event>` props to component
  instance.$on(`keyup`, keyup)
  instance.$on(`click`, click)

  const node = document.querySelector(`.some-css-selector`)

  if (!node) throw new Error(`DOM node not found`)

  node.dispatchEvent(new KeyboardEvent(`keyup`, { key: `Enter` }))
  expect(keyup).toHaveBeenCalledTimes(1)

  node.dispatchEvent(new MouseEvent(`click`))
  expect(click).toHaveBeenCalledTimes(1)
})

Upvotes: 1

TeemuK
TeemuK

Reputation: 2559

I don't know exactly if this is what you want, but to pass on:click type event listeners to @testing-library/svelte rendered components you must use the component.$on syntax.

For example:

describe('Button', () => {
  it('should render correctly', async () => {
    const results = render(Button)
    const onClick = jest.fn()
    results.component.$on('click', onClick)

    const button = results.container.querySelector('button')
    expect(button).not.toBeNull()

    // Using await when firing events is unique to the svelte testing library because
    // we have to wait for the next `tick` so that Svelte flushes all pending state changes.
    await fireEvent.click(button as HTMLElement)

    expect(results.container).toBeInTheDocument()
    expect(onClick.mock.calls.length).toEqual(1)
  })
})

This link in the testing-library docs seemed to be quite useful https://sveltesociety.dev/recipes/testing-and-debugging/unit-testing-svelte-component/

Upvotes: 2

Related Questions