1

I have a component with an anchor tag with an associated handler, onSelectLink().

<a
  :href="$t('footer.termsUrl')"
  target="_blank"
  name="termsAndConditions"
  @click="onSelectLink($event.target.name)">{{ $t('terms') }}</a>

The onSelectLink() function...

onSelectLink (buttonName) {
      buttonName === 'termsAndConditions'
        ? this.logButtonClick(ANALYTICS.TERMS_AND_CONDITIONS)
        : this.logButtonClick(ANALYTICS.PRIVACY_POLICY)
    }

My unit test

describe('onSelectLink()', () => {
    it('[positive] should track analytics when user selects `Terms and Conditions` link', () => {
      const buttonName = 'termsAndConditions'
      jest.spyOn(wrapper.vm, 'onSelectLink')

      wrapper.find('a').trigger('click')
      wrapper.vm.onSelectLink(buttonName)

      expect(wrapper.vm.logButtonClick).toHaveBeenCalledWith(ANALYTICS.TERMS_AND_CONDITIONS)
    })

    it('[positive] should track analytics when user selects `Privacy Policy` link', () => {
      const buttonName = 'privacyPolicy'
      jest.spyOn(wrapper.vm, 'onSelectLink')

      wrapper.find('a').trigger('click')
      wrapper.vm.onSelectLink(buttonName)

      expect(wrapper.vm.logButtonClick).toHaveBeenCalledWith(ANALYTICS.PRIVACY_POLICY)
    })

My questions are:

  1. Are these tests each invoking onSelectLink() twice?

  2. Do I actually need to use "wrapper.find('a').trigger('click')"

  3. Is this a good/robust test to make sure onSelectLink() is called with right argument?

When I comment out "wrapper.find('a').trigger('click')" the test still seem to pass. I thought I had to trigger the DOM event and then call the handler.

1 Answer 1

2

You're currently triggering the onSelectLink twice in each test.

Once by

wrapper.find('a').trigger('click') // normal flow

and once by

wrapper.vm.onSelectLink(buttonName) // you run `onSelectionLink` directly on vm

The second one is wrong, in principle. You don't want to trigger the method by calling it directly on vm, because your users can't do that.
The only way they can do it is by clicking the link and that's what you should test.

const logger = jest.spyOn(wrapper.vm, 'logButtonClick')
expect(logger).not.toHaveBeenCalled();
wrapper.find('a[name="termsAndConditions"]').trigger('click')
expect(logger).toHaveBeenCalledWith(ANALYTICS.TERMS_AND_CONDITIONS);

Remember you can always use console.log() in your tests and you'll see the logged values in CLI and figure out what's going on.

Sign up to request clarification or add additional context in comments.

5 Comments

One thing, in another component, I have a switch/case with 4 different cases. Each case is similar to 'termsAndConditions' and 'privacyPolicy',etc. The more accurate test you suggested works very well with the onSelect() function I have above. However, with the switch/case, the statement, expect(logger).not.toHaveBeenCalled(), fails the next test. For example, test one, 'termsAndConditions' passes, then the next, 'privacyPolicy' fails, and so forth. What can be done to clear the previous call. Also, does this happen because the test suite is reading off a stack of function calls?
I believe the caller results are actually an array, but for the case when it has only been called once expect(caller) automagically returns its only call ([0]) - because it's the most common case. I might be wrong and I have no means of testing now. But I do expect(caller[0]).toEqual(yourFirstCall) && expect(caller[1]).toEqual(yourSecondCall).
@KevinT, However, you don't have to test them in the same test. You can test them in separate tests and they'd be good tests (as in, if there's any issue with one of them, that particular test will fail). But I get your desire to test them in the same test. It seems more elegant.
Yeah, I have one test suite and 4 'it' blocks. My code reviewers would complain about breaking them up!
By test I meant what you mean by it block. And, in fact, they're synonyms. it(description, handler) is an alias for test(description, handler).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.