Timeout simulation not working with testing-library and useFakeTimers

1.2k views Asked by At

I'm working on a vueJS component that allows to display a modal after 5 seconds. the component works well as expected.

<template>
    <vue-modal v-if="showModal" data-testid="modal-testid" />
</template>
<script>
export default {
    name: "TimeoutExample",
    data() {
        return {
          showModal: false,
        }
    },
    mounted() {
        setTimeout(() => this.displayModal(), 5000)
    },
    methods: {
        displayModal: function() {
            this.showModal = true;
        }
    }
};
</script>

I implemented the unit tests using jest, testing-library and I wanted to use jest.useFakeTimers to simulate the timeout, but the test is KO.

// testing file
describe.only('Vue Component (mobile) 2', () => {
    beforeAll(() => {
      isMobile.mockImplementation(() => true)
    })

    beforeEach(() => {
      jest.useFakeTimers()
    })

    afterEach(() => {
      jest.runOnlyPendingTimers()
      jest.useRealTimers()
    })

    it('should render title after `props.delay` milliseconds', () => {
      const { queryByTestId } = myRender({
        localVue: myMakeLocalVue(),
      })

      jest.advanceTimersByTime(5001)

      expect(queryByTestId('modal-testid')).toBeVisible()
    })
})

do you have any idea how i can test this behavior?

2

There are 2 answers

0
Mahmoud On BEST ANSWER

It works for me after calling advanceTimersByTime inside waitFor.

describe.only('Vue Component (mobile) 2', () => {
    beforeAll(() => {
      isMobile.mockImplementation(() => true)
    })

    beforeEach(() => {
      jest.useFakeTimers()
    })

    afterEach(() => {
      jest.runOnlyPendingTimers()
      jest.useRealTimers()
    })

    it('should render title after `props.delay` milliseconds', async () => {
      const { queryByTestId } = myRender({
        localVue: myMakeLocalVue(),
      })

      await waitFor(() => {
        jest.advanceTimersByTime(5001)
      })

      expect(queryByTestId('modal-testid')).toBeVisible()
    })
})
3
Andrey Nelubin On
  1. remove this jest.spyOn(global, 'setTimeout'). jest will do it's own magic with for this with useFakeTimers
  2. I suppose you can not use async and done callback in one test case. Which version of jest do you use?
  3. Add await localVue.$nextTick() after advanceTimersByTime to wait until Vue apply all the changes