S
SolidJS13mo ago
oneiro

Is there a way to debug how callbacks are called, when firing an event with testing-library?[SOLVED]

Hey, I am having a hard time testing my code and would like to find out if and how some of my event handlers are actually being called, when I run fireEvent.click() on a button. Some background: I am running solid inside a Tauri-Application which works very well. However my issue is, that on the click of a button nothing observable seems to happen (it works perfectly fine in the real running application). Basically what I am trying to do, is to setup some stores, render my app, find a button that should start a timer, advance these timers by using vitests fake timers and afterwards inspect, that a stop button is being rendered and the time has been adjusted accordingly. My current (simplified without timers) test looks like this:
it('should run on toggle start', async () => {
// Arrange
render(() => <App />, { location: '/' })
const TEST_ID = 'TEST_ENTRY'
setTimeEntries(TEST_ID, {
id: TEST_ID,
savedTimeInMs: 0,
date: '2023-07-02T00:00:00.000Z',
description: 'This is a test entry',
isBillable: true,
isFavorite: false,
})
setRunningTimer({
timeEntryId: TEST_ID,
savedTimeInMs: 0,
isRunning: false,
})
setIsHydrating(false)

// Act
const currentTimerStartButton = await screen.findByRole('button', { name: 'start-current-timer' })

mockIPC(() => {
fireEvent.click(currentTimerStartButton)
})

// Assert
expect(await screen.findByRole('button', { name: 'stop-current-timer' })).toBeInTheDocument()
expect(await screen.findByTestId('running-timer-time')).toHaveTextContent('00:00:03')
})
it('should run on toggle start', async () => {
// Arrange
render(() => <App />, { location: '/' })
const TEST_ID = 'TEST_ENTRY'
setTimeEntries(TEST_ID, {
id: TEST_ID,
savedTimeInMs: 0,
date: '2023-07-02T00:00:00.000Z',
description: 'This is a test entry',
isBillable: true,
isFavorite: false,
})
setRunningTimer({
timeEntryId: TEST_ID,
savedTimeInMs: 0,
isRunning: false,
})
setIsHydrating(false)

// Act
const currentTimerStartButton = await screen.findByRole('button', { name: 'start-current-timer' })

mockIPC(() => {
fireEvent.click(currentTimerStartButton)
})

// Assert
expect(await screen.findByRole('button', { name: 'stop-current-timer' })).toBeInTheDocument()
expect(await screen.findByTestId('running-timer-time')).toHaveTextContent('00:00:03')
})

(continuation in thread)
3 Replies
oneiro
oneiro13mo ago
The relevant part of my component (also simplified):
function CurrentTimer() {
const handleStart = () => {
setRunningTimer('isRunning', true)
}

return (
<div>
<Show
when={runningTimeEntrySelectors.isRunning()}
fallback={
<button
type="button"
aria-label="start-current-timer"
onClick={handleStart}
disabled={!runningTimeEntrySelectors.currentEntry}
class="group"
>
<FaSolidCirclePlay
/>
</button>
}
>
<button type="button" onClick={() => pauseTimeEntry()} class="group" aria-label="stop-current-timer">
<FaSolidCirclePause

/>
</button>
</Show>
function CurrentTimer() {
const handleStart = () => {
setRunningTimer('isRunning', true)
}

return (
<div>
<Show
when={runningTimeEntrySelectors.isRunning()}
fallback={
<button
type="button"
aria-label="start-current-timer"
onClick={handleStart}
disabled={!runningTimeEntrySelectors.currentEntry}
class="group"
>
<FaSolidCirclePlay
/>
</button>
}
>
<button type="button" onClick={() => pauseTimeEntry()} class="group" aria-label="stop-current-timer">
<FaSolidCirclePause

/>
</button>
</Show>
timeEntries and runningTimer are both stores which reside inside their own files. runningTimeEntrySelectors basically look like this (simplified):
export const runningTimeEntrySelectors = createRoot(() => {
const isRunning = () => runningTimer.isRunning
return {
isRunning,
...
}
}
export const runningTimeEntrySelectors = createRoot(() => {
const isRunning = () => runningTimer.isRunning
return {
isRunning,
...
}
}
What I noticed is, that the fireEvent call does not seem to lead to the runningTimer-store to be updated at all. Any idea what I could be doing wrong here? Thanks in advance Ok, I think I made at least some progress: My call to mockIPC from Tauri was probably wrong. I should not wrap the click handler with that. Instead I needed to mock the actual backend commands (which makes sense). Now I am also able to log from the click handler. Which answers my initial question. The only issue I am still having is related to advancing fake timers - however before I open a new issue for that, I'll have a look at this with a fresh mind tomorrow 😄
Alex Lohr
Alex Lohr13mo ago
Fake timers are related to vitest, not to testing-library. However, I will try to support you to the best of my abilities.
oneiro
oneiro13mo ago
Thanks a ton @lexlohr your effort is really appreciated. (Actually its amazing to see how much help you provide over here in the discord and how fast you usually respond! ❤️ ) Ha, got it to work (and learned a ton in the process 😊) The last issue I was having, was that the interval I was running had an async callback and I accidentally used vi.advanceTimersByTime instead of await vi.advanceTimersByTimeAsync(...)