Mocha Chai vue testing a vue component : this.$notify is not a function - unit-testing

I'm using this component : https://github.com/euvl/vue-notification
Since then, all of my Mocha chai test units are failing .
this.$notify is not a function
This is my login spec :
// Importing The testing library
import { expect } from "chai";
import { mount } from '#vue/test-utils'
// Importing The component I need to test
import Login from "#/components/Login.vue";
// Mounting the component as in real life
const wrapper = mount(Login);
describe("Login test", () => {
it("getAuth() to be a function", () => {
expect(wrapper.vm.getAuth).to.be.a("function");
});
});
I've tried out mount, shallowMount, render with no luck .
Any workaround ?
I'm calling vue-notification in main.js like this :
import Notifications from "vue-notification";
Vue.use(Notifications);
Thank you !
EDIT :
Ive tried to add
const $notify = require('vue-notification')
To my Login.vue component with no luck
EDIT 2 : Tried to call the function like this with no luck :
this.$root.$notify({
group: 'foo',
title: 'Hello ',
text: 'Cool'
});
[Vue warn]: Error in mounted hook: "TypeError: this.$root.$notify is not a function"

*EDIT : ***** Resolved by me ****** *
I was badly importing vue . Please see my working login.spec.js testing file there :
// THE ASSERTION LIBRARY
import { expect } from "chai";
// THE TESTING LIBRARY
import { mount } from "#vue/test-utils";
// THE COMPONENT THAT I WANT TO TEST
import Login from "#/components/Login.vue";
// THE EXTERNAL COMPONENTS LINKED TO MY LOGIN COMPONENT THAT I NEED TO JOIN
import Vue from 'vue';
import Vuelidate from 'vuelidate'
Vue.use(Vuelidate)
import {
required,
minLength,
between
} from "vuelidate/lib/validators";
import Notifications from "vue-notification";
import velocity from 'velocity-animate'
Vue.use(Notifications, { velocity });
// THE WRAPPER CONTAIN MY LOGIN MOUNTED COMPONENT, JUST LIKE IN THE REAL LIFE
const wrapper = mount(Login)
describe("Login test", () => {
it("getAuth() to be a function", () => {
expect(wrapper.vm.getAuth).to.be.a("function");
});
});

Related

Having issues intergrating Unit Testing into an active Vuetify 2 Project, Error with SASS (Mocha-webpack / Vue Unit Test Tools)

When trying to run a Unit Test on a Vuetify 2 app I get the error for SASS Stylesheets not being found, they are there.
The app has had no unit testing before so we need to include it to this project, I have tried to create a new fresh project and the testing works perfectly there, I have used multiple guides such as: https://vuetifyjs.com/en/getting-started/unit-testing But I get the same issues no matter what I use. I have tried mocha, mocha-webpack, chai, vue-test-utils, Jest etc.
https://imgur.com/X3zHFBE
https://imgur.com/kQoiJBB
Does not work
import { expect } from 'chai'
import { shallowMount } from '#vue/test-utils'
import Tabs from '#/components/ui/Tabs.vue'
let wrapper = shallowMount(Tabs);
console.log(wrapper);
describe('Tabs.vue', () => {
it('current tab equals empty', () => {
// wrapper.vm.clearValue();
expect(wrapper.vm.currentTab).to.equal('');
});
});
Works
import { expect } from 'chai'
import { shallowMount } from '#vue/test-utils'
import HelloWorld from '#/components/HelloWorld.vue'
describe('HelloWorld.vue', () => {
it('renders props.msg when passed', () => {
const msg = 'new message'
const wrapper = shallowMount(HelloWorld, {
propsData: { msg }
})
expect(wrapper.text()).to.include(msg)
})
})
Also tried the code examples here: https://vuetifyjs.com/en/getting-started/unit-testing
They do not work also.
I expect the tests to actually run and either return success or failed. I actually get an error for each of the stylesheets using SASS.

Mock this.$parent.$on with jest

We are using vuejs, typescript, vuex and jest. We are currently using test-utils to mock the store.
But I cannot find out how to mock a call to this.$parent.$on
Here is one of our components (very simplified):
AnalysisList.ts:
import Component from 'vue-class-component'
import {Getter} from 'vuex-class'
import {UserVO} from '#/valueObjects/UserVO'
import {Vue} from 'vue-property-decorator'
#Component
export default class AnalysisList extends Vue {
#Getter('getCurrentUser') private currentUser: UserVO
private searchString = ''
public mounted() {
this.$parent.$on('resetAnalyses', this.reset)
}
public reset() {
this.searchString = ''
}
}
AnalysisList.vue:
<template lang="pug">
text test
</template>
<script lang="ts" src="./AnalysisList.ts">
</script>
AnalysisList.spec.ts:
import {shallowMount} from '#vue/test-utils'
import AnalysisList from '#/components/analysis/AnalysisList'
import Vuex from 'vuex'
import {Vue} from 'vue-property-decorator'
import VueRouter from 'vue-router'
Vue.use(Vuex)
Vue.use(VueRouter)
describe('AnalysisList.vue', () => {
const store = new Vuex.Store( {
modules: {
user: {
state: {currentUser: 'test'},
getters: {
getCurrentUser: (state: any) => state.currentUser,
},
},
},
})
it('minimum test', (done) => {
const wrapper = shallowMount(AnalysisList, {store})
done()
})
})
When I run the test, I have the following error message, because $parent is not mocked:
TypeError: Cannot read property '$on' of undefined
at VueComponent.mounted (src/components/analysis/AnalysisList/AnalysisList.vue:73:20)
at callHook (node_modules/vue/dist/vue.runtime.common.js:2919:21)
at mountComponent (node_modules/vue/dist/vue.runtime.common.js:2800:5)
at VueComponent.Object.<anonymous>.Vue.$mount (node_modules/vue/dist/vue.runtime.common.js:7997:10)
at mount (node_modules/#vue/test-utils/dist/vue-test-utils.js:5381:8)
at shallowMount (node_modules/#vue/test-utils/dist/vue-test-utils.js:5414:10)
at Object.done (tests/unit/AnalysisList.spec.ts:20:53)
If I try to add a new property to shallowMount parameter:
const wrapper = shallowMount(AnalysisList, {store, parent: {$on: ()=>{}}})
I obtain a type error:
TS2345: Argument of type 'VueConstructor<Vue>' is not assignable to parameter of type 'FunctionalComponentOptions<Record<string, any>, PropsDefinition<Record<string, any>>>'.   Property 'functional' is missing in type 'VueConstructor<Vue>'.
Do you have any clue to help me mock this.$parent.$on ? Thanks.
I got the same issue with vue-test-utils and Jest (under the Vue, Vuex and Typescript environment)
For me, createLocalVue() of vue-test-utils library fixed the issue. This function creates a local copy of Vue to use when mounting the component. Installing plugins on this copy of Vue prevents polluting the original Vue copy. (https://vue-test-utils.vuejs.org/api/options.html#localvue)
Adding this to my test file fixed the issue:
const EventBus = new Vue();
const GlobalPlugins = {
install(v) {
// Event bus
v.prototype.$bus = EventBus;
},
};
// create a local instance of the global bus
const localVue = createLocalVue();
localVue.use(GlobalPlugins);
Hope this helps others, thanks :)

Vue component register warning in unit tests with element-ui

By element-ui documentation, it can be imported "entirely, or just import what you need". I have imported it entirely in application entry point main.js.
main.js
import Vue from 'vue'
import ElementUI from 'element-
import 'element-ui/lib/theme-chalk/index.css'
Vue.use(ElementUI)
const Component = () => import(/* webpackChunkName: "component" */ './views/Component.vue')
// eslint-disable-next-line no-new
new Vue({
el: '#app',
components: {Component}
})
Like that it is possible to use all element-ui components in my custom components. For example I've used button component in Component.vue. That looks fine and button is rendered in App.vue.
Component.vue
<template>
<div>
<el-button>{{ buttonText }}</el-button>
</div>
</template>
<script>
export default {
name: 'component',
data () {
return {
buttonText: 'Button Text'
}
},
components: {}
}
</script>
Now I have created test against this component using vue-jest and #vue/test-utils where I am testing is text in the button is rendered correctly. The test passed but I have Vue warning that button component is not registered:
[Vue warn]: Unknown custom element: - did you register the
component correctly? For recursive components, make sure to provide
the "name" option.
This is probably happening because I have imported all element-ui components directly in main.js file (as they propose in documentation) and not in Component.vue. Does anybody know how can I avoid this warning or how can I import component in the test?
Component.spec.js
import { shallow } from '#vue/test-utils'
import Component from '../Component.vue'
describe('Component.vue', () => {
test('sanity test', () => {
expect(true).toBe(true)
})
test('renders button title', () => {
const wrapper = shallow(Component)
wrapper.setData({buttonText: 'This is text'})
expect(wrapper.text()).toEqual('This is text')
})
})
In your tests, create a local Vue, call .use in it and pass it to shallow:
import { shallow , createLocalVue} from '#vue/test-utils'; // changed
import Vue from 'vue'; // added
import ElementUI from 'element-ui'; // added
import Component from '../Component.vue'
const localVue = createLocalVue(); // added
localVue.use(ElementUI); // added
describe('Component.vue', () => {
test('sanity test', () => {
expect(true).toBe(true)
})
test('renders button title', () => {
const wrapper = shallow(Component, {localVue}) // changed
Try to import the required module using Vue.use(Module) in your .spec file.
// + Vue.use(ElementUI)
describe('Component.vue', () => {
...
})
You might get an error stating that you cannot import entire module because preventFullImport setting is true. To prevent it, modify your .babelrc or equivalent file and change your settings accordingly. All I did was preventFullImport: false (personally for test cases only).
TESTED
Hello, after many hours of looking I find an another answer, here you dont need to manually set each custom component, as in the first answer.
add a components.js file where you register all of your global vue components:
componentsbind.js
import Vue from 'vue'
//this are the components I want to import
import MyHeader from '#/components/MyHeader'
import MyNav from '#/components/MyNav'
Vue.component('MyHeader', MyHeader)
Vue.component('MyNav', MyNav)
In jest.config.js add
modules.exports = {
moduleNameMapper:{
"~(.*)$": "<rootDir>/resources/js/$1",
},
setupFilesAfterEnv: ['<rootDir>resources/src/tests/setup.js']
}
add a setup.js file in test folder
import '../componentsbind.js'
structure
└── src
├── assets
├── components
└── tests
└─ unit
└─ example.spec.js
└─ setup.js
└── etc
└──index.js //here in my case I register all of my global vue components
└──componentsbind.js //that is why I put my components.js file in this place
and last run! this works for me!
npm run test:unit
for more info:
https://github.com/vuejs/vue-test-utils/issues/1116

Testing Angular 2 service with mocha

I am trying to implement unit tests for an Angular 2 app. But I can't get it it to work.
As test runner mocha is used and executed like this:
mocha -r ts-node/register -t 10000 ./**/*.unit.ts
Consider the following test file where I define two test cases which basically should do the same thing, but neither one is working.
shared.service.unit.ts
import { TestBed, async, inject } from '#angular/core/testing';
import { SharedService } from './shared.service';
import * as Chai from 'chai';
import 'mocha';
const expect = Chai.expect;
describe('SharedService', () => {
beforeEach(() => {
TestBed.configureTestingModule({
declarations: [SharedService],
providers: [SharedService]
});
});
it('should be an object',
inject([SharedService], (service: SharedService) => {
expect(service).to.be.an('object');
})
);
});
describe('SharedService without the TestBed', () => {
let service: SharedService;
beforeEach(() => {
service = new SharedService();
});
it('should be an object', () => {
expect(service).to.be.an('object');
});
});
The first one 'SharedService' uses the Angular Testing Utility. Running it gives:
ReferenceError: Zone is not defined
The second one 'SharedService without TestBed'does not use any Angular code (similar to this example from Angular 2 Testing guide). Running it gives:
TypeError: Reflect.getMetadata is not a function
After adding these lines to the test file:
import 'core-js/es6';
import 'core-js/es7/reflect';
import 'zone.js/dist/zone';
Both test cases give the same error (from zone.js\dist\zone.js):
TypeError: Cannot read property 'prototype' of undefined
What am I doing wrong?
Got it, just needed to import 'core-js/es7/reflect':
import 'core-js/es7/reflect';
import 'mocha';
import * as Chai from 'chai';
let expect = Chai.expect;
import { SharedService } from './shared.service';
describe('SharedService', () => {
let service: SharedService;
beforeEach(() => {
service = new SharedService();
})
it('should be an object', () => {
expect(service).to.be.an('object');
})
});
You need to load all that stuff - angular, ngzone, metadata, es shims, etc. - statically in the mocha's - or systemjs or whatever you use for setting this stuff up - configuration.

Jest with React - How do you render an entire component and test it?

Let's say I have a simple App component and I am running a test for it to see if it simply returns a div that prints Hello World to the screen. What is the function helper in order to render App inside my testing file? Furthermore, what is the function to call in the expect call in order to test the HTML being rendered?
import React from 'react'
import ReactDOM from 'react-dom'
import App from './App'
describe("App", () => {
it('prints "HELLO WORLD" to the screen', () => {
expect(**App??**).**toRENDER??**("HELLO WORLD")
}
}
Thanks
It's a good practice to use enzyme library from airbnb.
There is an example of using both together
Your code can looks like the next:
import React from 'react'
import ReactDOM from 'react-dom'
import App from './App'
import {shallow} from 'enzyme'
describe("App", () => {
it('prints "HELLO WORLD" to the screen', () => {
const wrapper = shallow(<App />)
expect(wrapper.text()).toBe("HELLO WORLD")
}
}
You would want to look at Jest's snapshot testing for this. This is as simple as calling:
import renderer from 'react-test-renderer';
describe('snapshot testing', () => {
it('should render App', () => {
const component = renderer.create(<App />);
const tree = component.toJSON();
expect(component).toMatchSnapshot();
});
});
A snapshot file will be stored in a __tests__/__snapshots__ folder. Make sure you commit these snapshot files into your Git repository so other contributors can have a snapshot to their components against.
For more information on how to setup Jest snapshot testing with React, refer to this docs here as you will need to install some npm dependencies.