Idris Stack
Idris Stack

Reputation: 566

Unit Testing methods which dispatch actions in Vue.js

I am having trouble to unit test methods in a component, I want to test validations(), clear(), and registerUser() methods but I can't seem to increase the code coverage. Below is the Component :

<template>

    <v-col class="pa-lg-10">
        <v-card class=" mx-auto">
            <form class="pa-10">
                <p class="reg-text">Registration</p>
                <v-text-field v-model="name" label="Name" required></v-text-field>
                <v-text-field v-model="email" label="E-mail" required></v-text-field>
                <v-text-field v-model="address" label="Address" required></v-text-field>
                <v-text-field v-model="phoneNumber" label="Phone Number"></v-text-field>
                <v-text-field v-model="password" label="Password" :type="'password'" required></v-text-field>
                <v-btn class="mr-4" color="primary" @click="registerUser">Register</v-btn>
                <v-btn @click="clear">clear</v-btn>
            </form>
        </v-card>
        <SnackBar/>
    </v-col>


</template>

<script>
    import {mapActions, mapGetters} from "vuex";
    import SnackBar from "./SnackBar";

    export default {
        name: "RegisterUsers",
        components: {
            SnackBar
        },
        data() {
            return {
                name: '',
                email: '',
                address: '',
                phoneNumber: '',
                password: '',
                formHasErrors: false,
            }
        },
        methods: {
            registerUser() {
                const formData = {
                    name: this.name,
                    email: this.email,
                    address: this.address,
                    number: this.phoneNumber,
                    password: this.password,
                };

                if (!this.validations()) {
                    this.register(formData);
                }
            },
            clear() {
                this.name = "";
                this.email = "";
                this.address = "";
                this.phoneNumber = "";
                this.password = "";
            },
            validations() {
                // eslint-disable-next-line no-useless-escape
                const mailFormat = /\S+@\S+\.\S+/;
                const vm = this;
                setTimeout(() => {
                    vm.reset_snackbar();
                }, 2000);
                if (this.email === '') {
                    this.toast_snackbar_on_error('Email is required');
                    return true;
                }

                if (mailFormat.test(this.email.toString()) !== true) {
                    this.toast_snackbar_on_error('Please enter a valid mail');
                    return true;
                }

                if (this.name === '') {
                    this.toast_snackbar_on_error('Name is required');
                    return true;
                }
                if (this.address === '') {
                    this.toast_snackbar_on_error('Address is required');
                    return true;
                }
                if (this.password === '') {
                    this.toast_snackbar_on_error('Password  is required');
                    return true;
                }
                return this.formHasErrors;
            },
            ...mapActions({
                register: 'register/registerUsers',
                reset_snackbar: 'register/reset_snackbar',
                toast_snackbar_on_error: 'register/toast_snackbar_on_error',

            }),
            computed: {
                ...mapGetters('register', ['snackbar_status']),
            },

        },
    };
</script>

<style scoped>
    div{
        color: inherit;
    }
    .reg-text {
        color: black;
        text-align: center;
        font-size: 20px;
        font-weight: bold;
    }
</style>

I have tried to mock some data during the insertion however, I can't seem to get hit those methods. Secondly, I wanted also to expect the message from a SnackBar but I couldn't seem to target it as well.

How can I test this component methods.

Below are my tests :

it("should expect to have input fields", () => {

        const wrapper = shallowMount(RegisterUsers);

        wrapper.setData({ name: '',
          email: '[email protected]',
          address: 'Buziga, Kampala',
          phoneNumber: '0704594180',
          password: '9393939',
          formHasErrors: false,});

        const button = wrapper.find({name: 'v-btn'})
        button.trigger('click');

        expect(wrapper.classes('s-text')).toBe(false);
    })

The css class s-text you see in the test it's the one wrapping the message of a SnackBar.

I kindly need guidance here.

Upvotes: 0

Views: 438

Answers (1)

lmiller1990
lmiller1990

Reputation: 945

You are using shallowMount. That will stub out all the components - there will be no button to find.

An alternative way to write this would

it("should expect to have input fields", () => {
  const wrapper = mount(RegisterUsers, {
    name: '',
    email: '[email protected]',
    address: 'Buziga, Kampala',
    phoneNumber: '0704594180',
    password: '9393939',
    formHasErrors: false,
  });

  const button = wrapper.find({name: 'v-btn'})
  button.trigger('click');

  expect(wrapper.classes('s-text')).toBe(false);
})

In all likelyhood this will still lead to problems. You are using Vuetify and some other plugins, which are not installed. You need to install those using localVue.

Once you get it all running without errors, you can do something like wrapper.find('button').trigger('click') which should call registerUsers. If you do not want to use a real Vuex store, do something like this:


const store = {
  dispatch: jest.fn()
}

mount(Component, {
  mocks: {
    $store
  }
}

Upvotes: 1

Related Questions