`Vue component event handler testing done right`

I have a component containing 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 checks...

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

Below are details of 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)
    })

Some questions I have:

  1. Are these tests calling onSelectLink() function twice each?

  2. Is it necessary to use "wrapper.find('a').trigger('click')" in the test cases?

  3. Do you think this is a strong test for ensuring onSelectLink() takes the correct argument?

Even if I remove "wrapper.find('a').trigger('click')" from the test, it still passes. I thought simulating the DOM event was important before calling the handler.

Answer №1

You are currently invoking the onSelectLink function twice during each test.

First by

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

and secondly by

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

The second approach is problematic in principle. It is not ideal to trigger the method by calling it directly on vm, as users cannot do that.
The proper way is to simulate user interaction, such as clicking the link, which should be tested.

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);

Keep in mind that you can always use console.log() in your tests to view logged values and understand what is happening in the CLI.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Utilizing Angular to efficiently download and showcase PDF files

Presently utilizing https://github.com/stranger82/angular-utf8-base64 as well as https://github.com/eligrey/FileSaver.js/ for the purpose of decoding a base64 encoded PDF file that I am fetching from a rest API. It successfully decodes and downloads, ...

Create a JavaScript function that uses regular expressions to parse URLs from a given string and turns

I struggle with Regular Expressions, but can usually decipher them. However... For my chat room project, I need to parse text strings. This involves converting any pasted URLs into clickable hyperlinks. The RegExp I typically use for this task has been ...

What could be the reason my JavaScript alert is not functioning properly?

Having some trouble with my form validation using Bootstrap - the alerts aren't showing up when I submit the form. Not all of the alerts have been added yet. <!DOCTYPE html> <html> <head> <meta charset="utf-8"> ...

Is there a way to retrieve the data instead of receiving an undefined result when making an asynchronous call?

subject in user.subjects = subjects below is undefined instead of being an array of subjects. Context: I am working with three database tables - users, subjects, and a relationship table between users and subjects known as users_subjects. The objective i ...

Navigating over two JSON arrays using Ajax

My goal is to fetch data from a JSON file by utilizing the ID obtained from a previous AJAX call and looping through the second array based on the retrieved ID. I have attempted to achieve this with the following code: $(document).on('click', ...

Ways to update row background color based on specific column values

I need to customize the background color of my table rows based on the value in the "Category" column. For example: Name Category Subcategory A Paid B C Received D If the Category value is 'Paid', I want the ro ...

Utilize animation effects in jQuery to make text slide upwards and smoothly transition to a new text

I am currently working on developing a website that requires dynamic data changes. To enhance user experience, I aim to display the information in an animated format where text gracefully transitions by moving up and being replaced by new content emerging ...

Is it possible for a website to detect if Marionette is being used in conjunction with Firefox?

To run Firefox using Selenium, the Geckodriver is necessary due to compatibility issues with the JSON Wire Protocol and the Gecko Engine. The Geckodriver acts as an intermediary between Selenium and the browser by serving commands and translating them with ...

Refresh the webpage after a mobile device is awakened from sleep mode

I have developed a custom countdown clock using Javascript, HTML, PHP, and MySQL. Upon clicking "Start Countdown," the epoch time is saved in the database and the countdown begins. After reloading the page, the script retrieves the initial countdown star ...

Loading an HTML page inside a tab's content in Angular: A seamless and efficient approach

There are multiple tabs within the master.html page, each loading a different tab*.html page with AngularJS code. The problem arises when I try to load the tab*.html pages separately; they work fine. Here is a Plunker example for a single page: Plunker fo ...

Creating a regular expression to capture a numerical value enclosed by different characters:

export interface ValueParserResult { value: number, error: string } interface subParseResult { result: (string | number) [], error: string } class ValueParser { parse(eq: string, values: {[key: string] : number}, level?: number) : ValueParse ...

The mail listener sometimes encounters authentication issues

The Issue: We are facing a challenge with multiple tests that require the verification of the test user's email as part of the testing process. This is especially crucial for scenarios involving two-factor authentication and email notifications. Cur ...

Flipping over every single card, but only desire to flip them one at a time

My attempt to flip these cards individually has resulted in them all flipping together. I suspect there may be an error in my JavaScript code. In the original code, I used images in front and an unordered list in the back, but here I have simplified it t ...

Developing a fresh project using Npm and Vue

After running the command npm i -g @vue/cli, I attempted to create a new project using vue create test. However, I encountered an error that keeps popping up: NPM ERR! cb() never called! NPM ERR! This is an issue with npm itself. If you come across this ...

Maintain the selected bootstrap tab even after the page is refreshed, even when the content is loaded dynamically

I am currently facing an issue with loading tabs using Angular. Whenever a tab is clicked, the id is saved to localStorage. Now, I want to programmatically click on the same tab using jQuery when the page refreshes. However, since the DOM element for the ...

Discovering when the DOM has finished rendering in AngularJS with ng-repeat

I am looking for a way to trigger an alert or message upon completion of rendering in my HTML DOM using AngularJS, specifically when dealing with multiple ng-repeats. HTML Code: <body> <div ng-controller="Ctrl"> <div ng-repeat= ...

Transforming textarea input into a JavaScript object - possible?

Looking for some guidance as a junior developer. I have a text area where an array of objects will be inputted like this: [ { utc: "xxxxxx", battery_level: 12, lat: 2345678, lng: 234567, }, { utc: "xxxxxx&quo ...

Why doesn't AngularJS validation function properly with input elements of type "number"?

Struggling with Angularjs validation here. Ng-pattern seems to work fine only when the input type is text. However, when the input type is number, ng-pattern doesn't seem to work, although required, min, and max attributes still function. <input t ...

Reactjs - Creating a video component with a placeholder that loads the video seamlessly

I created a Video component that utilizes the React.Suspense component to show a placeholder while the video is loading. However, I'm facing an issue where it seems like the functionality isn't working as intended. When I set the network to "slow ...

Show the id value of the event triggered by eventclick

I am currently attempting to retrieve the id of the event so that I can remove it from the database. My approach involves using eventClick, where a dialog pops up when the user clicks an event prompting them to remove it. In order to proceed with this oper ...