Vue.js - Testing components with intricate child components

Imagine we have a simple Bootstrap powered HTML form within a custom Vue component named MyForm.vue

<template>
  <form>
    <div class="form-group">
      <label for="email">Email address</label>
      <input type="email" class="form-control" id="email">
    </div>
    <button type="submit" class="btn btn-primary">Submit</button>
  </form>
</template>

The unit test to check if the template is rendered correctly is quite straightforward

describe('MyForm', () => {

  let wrapper;

  beforeEach(...);

  it('Should be rendered', () => {

    let field = wrapper.find('#email');
    expect(field.element.value).toEqual('');
  });
});

We can access the value of field.element.value since field.element is an HTMLInputElement with the attribute value.

If we need to access an attribute of a more complex component like b-form-input, which is Bootstrap-Vue's default input element, how should we go about it? Do we cast the HtmlElement to BFormInput?

<template>
  <b-form>
    <b-form-group label="Email">
      <b-form-input type="email" id="email"></b-form-input>
    </b-form-group>
    <b-button type="submit" variant="primary">Submit</button>
  </b-form>
</template>

How do we test non-native components, especially when using TypeScript for type-safety? Any suggestions?

Edit 03/01/2020

In response to muka.gergely's answer, I came across this article. By default, shallowMount stubs all child components, including event handling. However, shallowMount allows for manual unstubbing of components, such as b-form and b-button for testing submit events.

const stubs = { // Intended for custom stubs but used here to unstub components
  BButton,
  BForm,
};

wrapper = shallowMount<MyComponent>(MyComponent, {stubs});

This approach ensures that these components are rendered instead of being stubbed, while other components like b-form-input remain stubbed automatically.

Answer №1

Prior to conducting tests, it is crucial to mount the elements. The focus should not be on testing the Vue component itself but rather on examining the rendered output.

When carrying out unit tests, it is advisable to incorporate vue-test-utils alongside your chosen unit testing library (Jest and Mocha being popular options).

Below is a basic unit test scenario for App.vue (incorporating Vuetify and vue-router):

import Vue from 'vue'
import { shallowMount, createLocalVue } from '@vue/test-utils'
import Vuetify from 'vuetify'
import VueRouter from 'vue-router'
import App from '@/App';

Vue.use(Vuetify)

const localVue = createLocalVue()
localVue.use(VueRouter)
const router = new VueRouter()

describe('App.vue', () => {
    let vuetify

    beforeEach(() => {
        vuetify = new Vuetify()
    })

    it('mounts and renders', () => {
        const wrapper = shallowMount(App, { localVue, vuetify, router });

        expect(wrapper.html()).toBeTruthy();
    });
});

In this example, shallowMount() was utilized as there was no need to test the children of App.vue individually. If a comprehensive evaluation of the children components had been needed, mount() would have been employed instead.

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

Refreshing data from firebase on each route change

I created an Angular service that retrieves items from Firebase using snapshotChanges and returns them. In my component, I subscribe to the data and store it in an array. I then display the data in cards using ngFor. However, whenever I navigate between p ...

Unable to test the subscribe functionality in Angular

There is a subscribe method in my ts file within ngAfterViewInit() that is not triggering as expected during testing and debugging. I need to manually set mock data inside the subscribe method for testing purposes. ts file import mockData from 'test ...

Guide to dynamically loading customer data into an HTML table using JavaScript

I'm looking to populate a table with data on customers including their name, customer ID, and rental cost. Can anyone help me with the JavaScript code needed to insert this data into rows of the table? Your assistance is greatly appreciated. Below is ...

Ensuring Uniform Data Types Across Objects (Using Typescript)

After much trial and error, I have finally reached this point where everything seems to be working perfectly. function test<types extends Record<string,any>>(dict: dictionary<types>){} type dictionary<types extends Record<string, a ...

The settimeout function does not seem to function properly within the context of

Currently, I am facing an issue with implementing block UI for blocking a specific div when a button is clicked. The problem I am encountering is that even though I want the blocked div to be unblocked after a certain delay, it remains permanently blocked ...

Unable to achieve accurate autoformatting when saving files in Visual Studio Code using ESLint and Prettier

While using Visual Studio Code with ESLint and Prettier to work on .vue files, I've encountered an issue where the vue/max-attributes-per-line setting doesn't auto-fix correctly. Even when I have vue/max-attributes-per-line set to 'off&apos ...

Integration of Unlayer EmailEditor into React causes fatal errors in the application

I am attempting to integrate Unlayer into my React Application by using this guide: https://github.com/unlayer/react-email-editor. I have configured Webpack for this purpose. However, when I try to import EmailEditor in one of my modules: import React fr ...

Is there a way to implement seamless scrolling within an absolute element using Jquery?

Hey there! I recently implemented smooth scrolling on my website, but it seems to only work on single-page layouts. How can I make it function properly within an absolutely positioned scrollable element? Here are the link to my website and the correspond ...

Working with foreign key attributes in Django templates

Currently, I am working on managing a couple of models that are interconnected in a one-to-many relationship. In my template files, I have successfully accessed all the attributes and foreign key attributes using template tags like one.many_set.all, etc. ...

Why do my checkboxes refuse to respond separately?

I am currently experiencing an issue with the checkboxes in my JavaScript game. They do not respond to individual clicks as expected. Each time I log the output, I receive index 0 regardless of which box I click on. The checkboxes seem unresponsive but the ...

What methods are commonly suggested for managing internationalization in Vue.js applications?

Transitioning from Django to vue.js has been a challenge for me, especially when it comes to dealing with translations. In Django, the workflow for adding translations felt intuitive and fool-proof: Annotate code with translation hooks. Pull out translati ...

"Encountered a TypeError stating that Object(...) is not being recognized as a function" while attempting to import a function via a barrel

In one of my files, I have a function named merge which has the following code inside: export default (prev, next) => Object.assign({}, prev, next) Additionally, there is a barrel file that imports and exports this function like so: import fetchToNode ...

Checkbox Trouble: Troubleshooting AJAX Integration

One of the requirements I have is to implement a checkbox list that updates the page via AJAX when one of the checkboxes is clicked. $(document).on("click", ".selectlist input", update_results); My client has requested that one of the checkboxes be pre-s ...

Discovering diversity in Angular: Learn how two distinct Class Components differ from one

Within my Parent component, I am injecting data into two @Input() Child duplicate card components to display HTML. The Parent component also has a different class that marks the distinction between the two classes. My question is, when showcasing class me ...

Adding an Item to the Cart in React.js

Currently, I am delving into react.js and endeavoring to incorporate a fundamental add to cart feature. My aim is to maintain simplicity in order to grasp the entire process. The setup involves two cards - one showcasing the items and another where the sel ...

Use Bootstrap 4.3.1 to seamlessly weave text around a video on your website

I've been grappling with this, but I just can't seem to crack it. <div class="container-fluid"> <div class="row"> <div class="col-lg-4 order-1 mb-auto mt-auto"> & ...

Angular ng-boostrap modal automatically refreshes upon detecting mouse movement with an embedded video

Currently, I am facing an issue with my Angular 7 ng-bootstrap modal. The problem arises when the modal, which includes a video player within an <iframe>, is moved to the production system. Whenever there is any mouse movement detected, the video get ...

Having issues with the display of Bootstrap SelectPicker dropdown in a dataTable?

I am currently populating data into a jQuery datatable dynamically with the help of AJAX. Each row in the table contains a dropdown selectpicker from Bootstrap, displayed as follows: https://i.sstatic.net/g0czE.png However, I am experiencing issues with ...

Vue Custom Element encountering issues when generating independent JavaScript files in the Dist directory

I recently followed the instructions for registering and utilizing custom elements as outlined here: https://alligator.io/vuejs/custom-elements/ For my project, I am using the standard Webpack template for Vue. After executing the command npm run buil ...

Converting API data to an array map in React with Typescript

There is an array data retrieved from an API that needs to be rendered in a React TypeScript file using the map function. { "data":{ "cart":{ "1":{ "product_id":1, "name":"Product 1", "quantity":1, ...