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

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.

Related

React: Enzyme shallow: "Expected: 1; Received: undefined

I am using React-typescript for my app. I am really new in testing world. I have created two components. Then I am imported the components to the App component. I am using Enzyme's shallow for testing the component. I am watching one tutorial from udemy. I followed the test code exactly as it is in video. But my test failed.
This is my app component
import React from 'react';
import CommentBox from './components/commentbox';
import CommentList from './components/commentlist'
function App() {
return (
<div className="App">
<CommentBox />
<CommentList />
</div>
);
}
export default App;
This is my test
import { cleanup } from '#testing-library/react';
import App from '../App';
import CommentBox from '../components/commentbox';
describe('whole app component', () => {
afterEach(cleanup)
it('renders Comment Box component', () => {
const wrapped = shallow(<App />);
expect(wrapped.find(CommentBox).lenght).toEqual(1) //I Received Undefined
});
});

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

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

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.

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.