Jest 'toHaveBeenCalled' for click events only works after two clicks? (Testing a Vue app)










0















A simple component:



<template>
<div>
<p>
count
</p>
<button @click="increment" data-test="increment">Increment</button>
</div>
</template>
<script>
export default
data ()
return
count: 0

,
methods:
increment ()
this.count++



</script>


And my test:



import TestExperiment from '@/components/TestExperiment'
import createLocalVue, shallowMount from '@vue/test-utils'

const localVue = createLocalVue()

describe('testexperiment.test.js', () =>
const cmp = shallowMount(TestExperiment,
localVue
)

const increment = jest.spyOn(cmp.vm, 'increment')
const incrementButton= cmp.find('[data-test="increment"]')

test('clicking increment button calls increent', () =>

expect(incrementButton.exists()).toBe(true)

incrementButton.trigger('click')

// Checking call here fails:
// expect(increment).toHaveBeenCalled()

// Function was still obviously called
expect(cmp.vm.count).toBe(1)

incrementButton.trigger('click')

// Checking call here passes:
expect(increment).toHaveBeenCalled()
)

)


As you can see, I trigger a click on incrementButton twice.



After the first call, if I test if the method 'increment' was called, it returns false. However, count is indeed incremented. After the second call, it registers that it was in fact called (if I test how many times it was called, it asserts that it was called one time, even if count is 2, clearly having been incremented twice).



What am I missing about how Jest/Vue works?










share|improve this question




























    0















    A simple component:



    <template>
    <div>
    <p>
    count
    </p>
    <button @click="increment" data-test="increment">Increment</button>
    </div>
    </template>
    <script>
    export default
    data ()
    return
    count: 0

    ,
    methods:
    increment ()
    this.count++



    </script>


    And my test:



    import TestExperiment from '@/components/TestExperiment'
    import createLocalVue, shallowMount from '@vue/test-utils'

    const localVue = createLocalVue()

    describe('testexperiment.test.js', () =>
    const cmp = shallowMount(TestExperiment,
    localVue
    )

    const increment = jest.spyOn(cmp.vm, 'increment')
    const incrementButton= cmp.find('[data-test="increment"]')

    test('clicking increment button calls increent', () =>

    expect(incrementButton.exists()).toBe(true)

    incrementButton.trigger('click')

    // Checking call here fails:
    // expect(increment).toHaveBeenCalled()

    // Function was still obviously called
    expect(cmp.vm.count).toBe(1)

    incrementButton.trigger('click')

    // Checking call here passes:
    expect(increment).toHaveBeenCalled()
    )

    )


    As you can see, I trigger a click on incrementButton twice.



    After the first call, if I test if the method 'increment' was called, it returns false. However, count is indeed incremented. After the second call, it registers that it was in fact called (if I test how many times it was called, it asserts that it was called one time, even if count is 2, clearly having been incremented twice).



    What am I missing about how Jest/Vue works?










    share|improve this question


























      0












      0








      0








      A simple component:



      <template>
      <div>
      <p>
      count
      </p>
      <button @click="increment" data-test="increment">Increment</button>
      </div>
      </template>
      <script>
      export default
      data ()
      return
      count: 0

      ,
      methods:
      increment ()
      this.count++



      </script>


      And my test:



      import TestExperiment from '@/components/TestExperiment'
      import createLocalVue, shallowMount from '@vue/test-utils'

      const localVue = createLocalVue()

      describe('testexperiment.test.js', () =>
      const cmp = shallowMount(TestExperiment,
      localVue
      )

      const increment = jest.spyOn(cmp.vm, 'increment')
      const incrementButton= cmp.find('[data-test="increment"]')

      test('clicking increment button calls increent', () =>

      expect(incrementButton.exists()).toBe(true)

      incrementButton.trigger('click')

      // Checking call here fails:
      // expect(increment).toHaveBeenCalled()

      // Function was still obviously called
      expect(cmp.vm.count).toBe(1)

      incrementButton.trigger('click')

      // Checking call here passes:
      expect(increment).toHaveBeenCalled()
      )

      )


      As you can see, I trigger a click on incrementButton twice.



      After the first call, if I test if the method 'increment' was called, it returns false. However, count is indeed incremented. After the second call, it registers that it was in fact called (if I test how many times it was called, it asserts that it was called one time, even if count is 2, clearly having been incremented twice).



      What am I missing about how Jest/Vue works?










      share|improve this question
















      A simple component:



      <template>
      <div>
      <p>
      count
      </p>
      <button @click="increment" data-test="increment">Increment</button>
      </div>
      </template>
      <script>
      export default
      data ()
      return
      count: 0

      ,
      methods:
      increment ()
      this.count++



      </script>


      And my test:



      import TestExperiment from '@/components/TestExperiment'
      import createLocalVue, shallowMount from '@vue/test-utils'

      const localVue = createLocalVue()

      describe('testexperiment.test.js', () =>
      const cmp = shallowMount(TestExperiment,
      localVue
      )

      const increment = jest.spyOn(cmp.vm, 'increment')
      const incrementButton= cmp.find('[data-test="increment"]')

      test('clicking increment button calls increent', () =>

      expect(incrementButton.exists()).toBe(true)

      incrementButton.trigger('click')

      // Checking call here fails:
      // expect(increment).toHaveBeenCalled()

      // Function was still obviously called
      expect(cmp.vm.count).toBe(1)

      incrementButton.trigger('click')

      // Checking call here passes:
      expect(increment).toHaveBeenCalled()
      )

      )


      As you can see, I trigger a click on incrementButton twice.



      After the first call, if I test if the method 'increment' was called, it returns false. However, count is indeed incremented. After the second call, it registers that it was in fact called (if I test how many times it was called, it asserts that it was called one time, even if count is 2, clearly having been incremented twice).



      What am I missing about how Jest/Vue works?







      vue.js jestjs vue-test-utils






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Nov 15 '18 at 20:33









      skyboyer

      4,18811333




      4,18811333










      asked Nov 15 '18 at 19:25









      Benjamin FriedmanBenjamin Friedman

      12




      12






















          1 Answer
          1






          active

          oldest

          votes


















          0














          You need to use the Vue Test Utils setMethod method:



          const wrapper = mount(Foo)
          const clickMethodStub = sinon.stub()

          wrapper.setMethods( clickMethod: clickMethodStub )
          wrapper.find('button').trigger('click')

          expect(clickMethodStub.called).toBe(true)


          The reason it does not work in your example is because the element that you dispatch a click on has the original handler that the component created when it was instantiated.



          It works after two calls to trigger because the initial call causes a re render, and the patched element has its handler updated to use the stub method that you added to the instance.






          share|improve this answer























            Your Answer






            StackExchange.ifUsing("editor", function ()
            StackExchange.using("externalEditor", function ()
            StackExchange.using("snippets", function ()
            StackExchange.snippets.init();
            );
            );
            , "code-snippets");

            StackExchange.ready(function()
            var channelOptions =
            tags: "".split(" "),
            id: "1"
            ;
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function()
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled)
            StackExchange.using("snippets", function()
            createEditor();
            );

            else
            createEditor();

            );

            function createEditor()
            StackExchange.prepareEditor(
            heartbeatType: 'answer',
            autoActivateHeartbeat: false,
            convertImagesToLinks: true,
            noModals: true,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: 10,
            bindNavPrevention: true,
            postfix: "",
            imageUploader:
            brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
            contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
            allowUrls: true
            ,
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            );



            );













            draft saved

            draft discarded


















            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53326620%2fjest-tohavebeencalled-for-click-events-only-works-after-two-clicks-testing-a%23new-answer', 'question_page');

            );

            Post as a guest















            Required, but never shown

























            1 Answer
            1






            active

            oldest

            votes








            1 Answer
            1






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes









            0














            You need to use the Vue Test Utils setMethod method:



            const wrapper = mount(Foo)
            const clickMethodStub = sinon.stub()

            wrapper.setMethods( clickMethod: clickMethodStub )
            wrapper.find('button').trigger('click')

            expect(clickMethodStub.called).toBe(true)


            The reason it does not work in your example is because the element that you dispatch a click on has the original handler that the component created when it was instantiated.



            It works after two calls to trigger because the initial call causes a re render, and the patched element has its handler updated to use the stub method that you added to the instance.






            share|improve this answer



























              0














              You need to use the Vue Test Utils setMethod method:



              const wrapper = mount(Foo)
              const clickMethodStub = sinon.stub()

              wrapper.setMethods( clickMethod: clickMethodStub )
              wrapper.find('button').trigger('click')

              expect(clickMethodStub.called).toBe(true)


              The reason it does not work in your example is because the element that you dispatch a click on has the original handler that the component created when it was instantiated.



              It works after two calls to trigger because the initial call causes a re render, and the patched element has its handler updated to use the stub method that you added to the instance.






              share|improve this answer

























                0












                0








                0







                You need to use the Vue Test Utils setMethod method:



                const wrapper = mount(Foo)
                const clickMethodStub = sinon.stub()

                wrapper.setMethods( clickMethod: clickMethodStub )
                wrapper.find('button').trigger('click')

                expect(clickMethodStub.called).toBe(true)


                The reason it does not work in your example is because the element that you dispatch a click on has the original handler that the component created when it was instantiated.



                It works after two calls to trigger because the initial call causes a re render, and the patched element has its handler updated to use the stub method that you added to the instance.






                share|improve this answer













                You need to use the Vue Test Utils setMethod method:



                const wrapper = mount(Foo)
                const clickMethodStub = sinon.stub()

                wrapper.setMethods( clickMethod: clickMethodStub )
                wrapper.find('button').trigger('click')

                expect(clickMethodStub.called).toBe(true)


                The reason it does not work in your example is because the element that you dispatch a click on has the original handler that the component created when it was instantiated.



                It works after two calls to trigger because the initial call causes a re render, and the patched element has its handler updated to use the stub method that you added to the instance.







                share|improve this answer












                share|improve this answer



                share|improve this answer










                answered Nov 23 '18 at 17:32









                EddEdd

                2,42711532




                2,42711532





























                    draft saved

                    draft discarded
















































                    Thanks for contributing an answer to Stack Overflow!


                    • Please be sure to answer the question. Provide details and share your research!

                    But avoid


                    • Asking for help, clarification, or responding to other answers.

                    • Making statements based on opinion; back them up with references or personal experience.

                    To learn more, see our tips on writing great answers.




                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function ()
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53326620%2fjest-tohavebeencalled-for-click-events-only-works-after-two-clicks-testing-a%23new-answer', 'question_page');

                    );

                    Post as a guest















                    Required, but never shown





















































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown

































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown







                    這個網誌中的熱門文章

                    How to read a connectionString WITH PROVIDER in .NET Core?

                    Node.js Script on GitHub Pages or Amazon S3

                    Museum of Modern and Contemporary Art of Trento and Rovereto