Using Vue Testing Library with Nuxt.js: A Beginner's Guide

Looking to incorporate Vue Testing Library into my Nuxt.js project. Encountered an error right after installation, where running a test results in the following message:

'vue-cli-service' is not recognized as an internal or external command, operable program or batch file.

It seems that this error occurs because Nuxt.js does not utilize vue-cli-service.

Nevertheless, is there a straightforward method to integrate Vue Testing Library with Nuxt.js?

Answer №1

Seems like there is a possibility that you have an NPM script with vue-cli-service (as shown below), which is actually meant for projects scaffolded by Vue CLI:

{
  "scripts": {
    "test:unit": "vue-cli-service test:unit" ❌ not for Nuxt projects
  }
}

But fear not, you can still set up Vue Testing Library using the methods detailed below.

Setting Up on a Fresh Project

When creating a new Nuxt project, opt for Jest as the testing framework and then install Vue Testing Library:

  1. Create a Nuxt project with create-nuxt-app, and choose Jest when prompted about the Testing framework:

    npx create-nuxt-app nuxt-testing-library-demo
    

    Example output:

    $ npx create-nuxt-app nuxt-testing-library-demo
    
    create-nuxt-app v3.5.2
    ✨  Generating Nuxt.js project in  nuxt-testing-library-demo
    [...]
    ? Testing framework: Jest
    
  2. Install Vue Testing Library (v5 is needed for Nuxt 2):

    npm install -D @testing-library/vue@5
    
  3. Execute tests using the test NPM script (generated from step 1):

    npm run test
    

Setting Up on an Existing Nuxt Project

If you already have a Nuxt project without a testing framework, follow the jest template from @nuxt/create-nuxt-app to integrate Vue Testing Library:

  1. Install the necessary NPM packages:

    npm install -D @testing-library/vue@5 \
                   vue-jest@^3 \
                   jest@^26 \
                   <a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="61030003040d4c020e130421564f514f514c0313080506044f51">[email protected]</a> \
                   babel-jest@^26
    
    npm install -D ts-jest@^26 # if using TypeScript
    

For Nuxt v2, install @testing-library/vue@5.

  1. Add an NPM script to execute Jest CLI:

    // <rootDir>/package.json
    {
      "scripts": {
        "test": "jest"
      }
    }
    
  2. Include a Jest configuration:

    // <rootDir>/jest.config.js
    module.exports = {
      moduleNameMapper: {
        '^@/(.*)$': '<rootDir>/$1',
        '^~/(.*)$': '<rootDir>/$1',
        '^vue$': 'vue/dist/vue.common.js'
      },
      moduleFileExtensions: [
        'ts', // if using TypeScript
        'js',
        'vue',
        'json'
      ],
      transform: {
        "^.+\\.ts$": "ts-jest", // if using TypeScript
        '^.+\\.js$': 'babel-jest',
        '.*\\.(vue)$': 'vue-jest'
      },
      collectCoverage: true,
      collectCoverageFrom: [
        '<rootDir>/components/**/*.vue',
        '<rootDir>/pages/**/*.vue'
      ]
    }
    
  3. Implement a Babel configuration:

    // <rootDir>/.babelrc
    {
      "env": {
        "test": {
          "presets": [
            [
              "@babel/preset-env",
              {
                "targets": {
                  "node": "current"
                }
              }
            ]
          ]
        }
      }
    }
    
  4. Create a test directory and include the sample test file illustrated below (taken from Vue Testing Library example). Note that the location of test files can be customized using the testMatch or testRegex setting in jest.config.js.

    Component Example:

    <!-- <rootDir>/components/Counter.vue -->
    <template>
      <div>
        <p>Times clicked: {{ count }}</p>
        <button @click="increment">increment</button>
      </div>
    </template>
    
    <script>
      export default {
        data: () => ({
          count: 0,
        }),
        methods: {
          increment() {
            this.count++
          },
        },
      }
    </script>
    

    Test Example:

    // <rootDir>/test/Counter.spec.js
    import {render, screen, fireEvent} from '@testing-library/vue'
    import Counter from '@/components/Counter.vue'
    
    test('increments value on click', async () => {
      render(Counter)
      expect(screen.queryByText('Times clicked: 0')).toBeTruthy()
    
      const button = screen.getByText('increment')
      await fireEvent.click(button)
      await fireEvent.click(button)
      expect(screen.queryByText('Times clicked: 2')).toBeTruthy()
    })
    
  5. Execute tests using the test NPM script (added in step 2):

    npm run test
    

Check out the GitHub demo here

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

Issues with HTTPS in Puppeteer and VUE JS

I am encountering an issue when running tests from NODE net::ERR_CONNECTION_REFUSED at https://localhost:8087 at navigate (node_modules/puppeteer/src/common/FrameManager.ts:190:13) Test Suites: 2 failed, 2 total Tests: 7 failed, 7 total Snapshots: ...

In a Vue project, classes are not being applied by TailwindCSS

Two Vue 3 projects were developed using Vite - a Design System and the main project that will make use of the Design System. Each project has its own repository. The design system is imported into the main project by referencing it in the package.json as ...

Dynamic data display issue in Vue with Chart.js

Seeking to utilize the reactive data mixin for vue-chartjs The mounted function for setting the initial data is functioning properly, and I can visualize the chart accurately with the API response: fetchSessionTrends() { axios.get(endpoint) .then ...

Tips for adding comments to VueJs Single-File-Components

As I develop my VueJs app with typescript, I have transitioned to using Vue's new script setup syntax for my single file components (SFC). However, I am unsure of the proper way to write comments that will show up in VSCode's intellisense. I aim ...

Whenever attempting to detach(), I am encountering the following error message: local.ERROR: Call to a member function programs() on an integer

I am dealing with a Many to Many relationship between Courses and Programs. The insertion of new courses and adding multiple programs works correctly. However, the issue arises during updates. When I update a course, I want to detach all related programs a ...

Converting HTML elements into Vue.js Components

In my Vue.js application, I am utilizing a d3.js plugin to generate a intricate visualization. I am interested in implementing a customized vue directive to the components that were incorporated by the d3 plugin. It seems that the $compile feature, which ...

Is it possible to utilize the output of a function to determine the styling of a div element in Vue?

Hi, I'm trying to use the v-bind:style in my div to apply the textposit function with the textpos prop as a parameter. The function should adjust the style of the div based on the value of the parameter. <div class="container" :style=&qu ...

Contrasts in the immutability strategies of Vuex and Redux

After exploring Vuex and noticing how simple it is to mutate states with mutation handlers using basic assignment, I am currently delving into redux. I have come to realize that redux emphasizes immutability, which can make coding a bit more verbose. This ...

Using vue-router within a pinia store: a step-by-step guide

I'm currently setting up an authentication store using Firebase, and I want to direct users to the login/logged page based on their authentication status. My goal is similar to this implementation: https://github.com/dannyconnell/vue-composition-api- ...

Display an error message when the button is clicked and the input field is left empty in a Vue 3 script setup

Hello, I am currently exploring Vue 3 and embarking on a new Vue 3 project venture. However, I seem to be encountering a challenge when it comes to displaying an error message if the button is clicked while the input field remains empty in my Vue 3 script ...

VueGapi does not perform any actions when attempting to request multiple scopes simultaneously

Here is the Vue3 main.js file that I'm working with: app.use(VueGapi, { apiKey: 'MyApiKey', clientId: 'myClientId.apps.googleusercontent.com', discoveryDocs: ['https://classroom.googleapis.com/$discovery/rest?versi ...

Having trouble receiving responses from pusher when attempting to utilize private channels, without any error notifications being displayed

While utilizing a public channel, I receive the responses without any issue. However, when I switch to a private channel and the channels.php check returns true, I am not receiving any response. According to Pusher's logs, the message is being success ...

Ways to access deeply nested data in Vuex store

I am facing an issue with my Vue project. I need to watch some Vuex store values and here is the code I have written: computed: { serverCategories: { get() { return this.$store.state[this.storeName].serverFilters.categories[0].value ...

Executing a function in Vue.js upon state changes

I am trying to trigger a function when the state changes in my Vue app. In my component, I can retrieve the boolean state of isOpen. The goal is to execute a function that sets focus on my form input when the modal opens and isOpen is true. I attempted ...

Error: Unable to locate attribute 'indexOf' within null object in vuejs when using consecutive v-for directives

I've been struggling with this issue for hours. I'm using vuejs' v-for to render items in <select> element's <options>, but I keep getting a type error. I've tried changing the :key values, but it still won't rende ...

Exploring the new features of FabricJS version 3.4.0: Enhancing performance with filters and understanding the limitations of maxTexture

Introduction: I have been experimenting with fabricJS image filtering features to incorporate them into my web application, but I have encountered the following issue. It appears that fabricJS default sets the image size cap (textureSize) on filters at 2 ...

Is it possible to generate unique identifiers for v-for keys using vue-uuid?

I'm attempting to utilize a random string (UUID v4) using vue-uuid for existing items and future additions to the list in my to-do list style application. However, I'm uncertain about the correct syntax to use. After installation, I included it ...

Interactive Vue components with dynamic children and sub-children

In my Vue application, I have a component called Address.vue which contains a child component called Contact.vue. One address can contain multiple components What I have accomplished: I have implemented the functionality in the Address.vue component t ...

What is the best way to connect data so that when a user clicks on a specific card, it appears on a popup card

When a user clicks on any card containing data retrieved from a backend API GET method, that data should be displayed in a pop-up card. In my situation, I have two components: DisplayNotes.vue and UpdateNotes.vue. Whenever a user clicks on a displayed card ...

Is it possible to extract the body from the post request using req.body.item?

After working with Express, I learned how to extract body data from a post request. Most examples showed that using req.body.item should retrieve the desired value for tasks like inserting into a table. However, in my case, I found that I couldn't ac ...