lodash icon indicating copy to clipboard operation
lodash copied to clipboard

How to test a Vue debounced method?

Open geeksilva97 opened this issue 4 years ago • 2 comments

I have a Vue application that uses the debounce function in a search input. I want to test my search input component but it's not being fired. I've tried to test using Jest fake timers but it didn't work, debounce is never fired (then my method is never fired too).

My code is shown below:

<template>
  <input type="text" @input="onSearchInput" />
</template>

<script>
import { debounce } from 'lodash';

export default {
  name: 'CommonFilter',
  emits: ['change'],
  methods: {
     onSearchInput: debounce(function(e) {
       // do something
      this.$emit('change', {search: e.target.value});
     }, 700),
  }
};
</script>

I tried to test using the following code.

it('emits @change event when type', async () => {
        jest.useFakeTimers();
        
        const wrapper = mount(CommonFilter);
        const $input = wrapper.find('.search-input');
        await $input.setValue('jackfruit');

        jest.runOnlyPendingTimers();

        expect(wrapper.emitted().change).toBeTruthy();
    });

Thank you for any help.

geeksilva97 avatar Nov 23 '21 13:11 geeksilva97

@geeksilva97

<script>
export default {
  name: "Header",
  data() {
    return {
      searchText: "github",
    };
  },
  methods: {
    // If the user types very fast, will allow the execution of func only when the user has stopped typing in the search bar
    DebounceFn: function () {
      if (this.searchText.length >= 3) {
        // schedule the execution after user stopped typing in the search bar
        setTimeout(() => {
          this.$emit("onSearch", this.searchText);
        }, 1000);
      }
    },
  },
};
</script>
it("emits an event with search text", async () => {
    jest.useFakeTimers();
    const wrapper = mount(Header);
    // calling emitEvent twice
    wrapper.vm.DebounceFn();
    wrapper.vm.DebounceFn();
    
    jest.runOnlyPendingTimers();

    // you can console it and check
    console.log(wrapper.emitted().onSearch[0]);

    expect(wrapper.emitted().onSearch[0]).toEqual(["github"]);
  });

截圖 2022-01-23 下午3 29 35

Vue Testing Handbook

ruofanwei avatar Jan 23 '22 07:01 ruofanwei

@geeksilva97 How did you solve this? The above answer only applies to setTimeout not _.debounce

madiha-right avatar Jun 22 '22 03:06 madiha-right

According to this comment https://github.com/facebook/jest/issues/3465#issuecomment-351186130 you can workaround this issue by mocking debounce with jest.mock('lodash/debounce', () => jest.fn(fn => fn)); in your setupJest.js.

lynx-r avatar Oct 14 '22 14:10 lynx-r

@geeksilva97 How did you solve this? The above answer only applies to setTimeout not _.debounce

I couldn't. All the answers here are about mock. Looks like a kind of integration test with the real debounce doesn't work.

abarbosa-godaddy avatar Oct 17 '22 14:10 abarbosa-godaddy

According to this comment jestjs/jest#3465 (comment) you can workaround this issue by mocking debounce with jest.mock('lodash/debounce', () => jest.fn(fn => fn)); in your setupJest.js.

this worked for me, thanks

orlandCasta avatar Feb 06 '24 17:02 orlandCasta

@geeksilva97 How did you solve this? The above answer only applies to setTimeout not _.debounce

I couldn't. All the answers here are about mock. Looks like a kind of integration test with the REAL debounce doesn't work.

@geeksilva97 How did you solve this? The above answer only applies to setTimeout not _.debounce

I couldn't. All the answers here are about mock. Looks like a kind of integration test with the REAL debounce doesn't work.

(just realized I had commented with the wrong account)

geeksilva97 avatar Feb 06 '24 17:02 geeksilva97