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: 'ab#gmail.com',
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.
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: 'ab#gmail.com',
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
}
}
Related
The fireEvent.submit(form) call doesn't seem to be submitting the form. How can I submit the form?
BasicInfo/index.test.tsx
import { fireEvent, render, screen, waitFor } from '#testing-library/react';
import userEvent from '#testing-library/user-event';
import BasicInfo from '.';
describe('BasicInfo', () => {
it('can submit form', async () => {
const handleSubmit = jest.fn();
render(<BasicInfo onSubmit={handleSubmit} />);
const user = userEvent.setup();
await user.type(screen.getByLabelText('Event title'), 'Event title 1');
await user.type(screen.getByLabelText('Featured game'), 'Scrabble');
await user.type(screen.getByLabelText('Venue location'), '21 2nd St.');
await user.type(screen.getByLabelText('Event starts'), '2017-06-01T08:30');
await user.type(screen.getByLabelText('Event ends'), '2017-06-01T08:30');
const form = screen.getByTestId<HTMLFormElement>('basic-info');
fireEvent.submit(form);
await waitFor(() => {
expect(handleSubmit).toHaveBeenCalledWith({
title: 'Event title 1',
game: { name: 'Scrabble' },
address: '21 2nd St.',
starts_at: '2017-06-01T08:30',
ends_at: '2017-06-01T08:30',
});
});
});
});
BasicInfo/index.tsx
import { Form, Formik, FormikErrors, FormikHelpers, FormikProps } from 'formik';
import Image from 'next/image';
import Link from 'next/link';
import { useLocation } from '../../context/location';
import { Event } from '../../hooks/useEvents';
import useGames, { Game } from '../../hooks/useGames';
import useMapbox, { Feature, Coords } from '../../hooks/useMapbox';
import useThrottle from '../../hooks/useThrottle';
import { parseAddress } from '../../lib/helpers';
import AddressItem from '../AddressItem';
import AutoComplete from '../AutoComplete';
import Button from '../Button';
import FormSection from '../FormSection';
import InputGroup from '../InputGroup';
import GameItem from '../GameItem';
export interface BasicInfoValues {
title: string;
game: Game;
address: string;
starts_at: string;
ends_at: string;
coords: string;
}
interface Props {
event?: Event;
initialValues?: BasicInfoValues;
onSubmit: (values: BasicInfoValues) => Promise<void>;
}
function BasicInfo({ event, initialValues: initialVals, onSubmit }: Props) {
const { coords } = useLocation();
const { data: places, forward, getStaticMapUrl } = useMapbox();
const { data: games, search, leanGame } = useGames();
const throttle = useThrottle();
const initialValues: BasicInfoValues = initialVals || {
title: '',
game: { name: '' },
address: '',
starts_at: '',
ends_at: '',
coords: '',
};
const validate = (values: BasicInfoValues) => {
const errors: FormikErrors<BasicInfoValues> = {};
if (values.title.length < 3) {
errors.title = 'Must be at least 3 characters';
}
if (values.title.length > 50) {
errors.title = 'Must be less than 50 characters';
}
if (!values.game.name) {
errors.game = 'Must select a game' as FormikErrors<Game>;
}
if (!values.coords) {
errors.coords = 'Must select a location';
}
if (!values.starts_at) {
errors.starts_at = 'Required';
}
if (!values.ends_at) {
errors.ends_at = 'Required';
}
return errors;
};
const handleSubmit = async function (
values: BasicInfoValues,
formikHelpers: FormikHelpers<BasicInfoValues>
) {
try {
await onSubmit(values);
formikHelpers.setSubmitting(false);
} catch (error) {
console.error(error);
}
};
const renderLocation = function ({
setFieldValue,
values,
handleChange,
errors,
touched,
handleBlur,
}: FormikProps<BasicInfoValues>) {
const handleEditLocationClick = function () {
setFieldValue('address', '');
setFieldValue('coords', '');
};
const { coords: coordinates, address } = values;
if (coordinates && address) {
const staticMapUrl = getStaticMapUrl({
coords: JSON.parse(coordinates),
width: 600,
height: 165,
});
const { street, city } = parseAddress(address);
return (
<div className="basic-info__location">
<div className="basic-info__location__image-container">
<Image
src={staticMapUrl}
alt="static map"
layout="fill"
objectFit="fill"
/>
</div>
<div className="basic-info__location__address-container">
<div className="basic-info__location__address-container__address">
<span className="basic-info__location__street">{street}</span>
<span className="basic-info__location__city">{city}</span>
</div>
<Button
text="Edit location"
color="secondary"
size="small"
onClick={handleEditLocationClick}
/>
</div>
</div>
);
} else {
return (
<AutoComplete<Feature>
name="address"
value={values.address}
onChange={(e) => {
if (!handleChange) return;
handleChange(e);
throttle.wait(() => {
if (!e.target.value) return;
if (!coords) return;
forward({
coords,
q: e.target.value,
});
}, 500);
}}
label="Venue location"
placeholder="Search for a venue or address"
items={places}
Input={InputGroup}
itemRenderer={(item) => <AddressItem placeName={item.place_name} />}
onItemClick={(item) => {
if (!setFieldValue) return;
setFieldValue('address', item.place_name);
setFieldValue('coords', JSON.stringify(item.center));
}}
onBlur={handleBlur}
error={errors.coords && touched.address ? errors.coords : undefined}
/>
);
}
};
return (
<Formik
initialValues={initialValues}
onSubmit={handleSubmit}
validate={validate}
>
{(formikProps) => {
const {
values,
handleChange,
setFieldValue,
errors,
touched,
handleBlur,
} = formikProps;
return (
<Form id="basic-info" className="basic-info" data-testid="basic-info">
<FormSection
title="Basic Info"
description="Name your event and tell gamers what game will be played. Add
details that highlight what makes it unique."
icon="segment"
>
<InputGroup
name="title"
value={values.title}
onChange={handleChange}
onBlur={handleBlur}
label="Event title"
placeholder="Be clear and descriptive"
error={errors.title && touched.title ? errors.title : undefined}
/>
<AutoComplete<Game>
name="game.name"
value={values.game.name}
onBlur={handleBlur}
onChange={(e) => {
handleChange(e);
throttle.wait(() => {
if (!e.target.value) return;
search({ name: e.target.value, limit: 5 });
}, 500);
}}
label="Featured game"
placeholder="Search games"
Input={InputGroup}
items={games}
itemRenderer={(item) => <GameItem game={item} />}
onItemClick={(item) => {
const game = leanGame(item);
setFieldValue('game', game);
}}
error={
errors.game && touched.game
? (errors.game as string)
: undefined
}
/>
<span>
Need game ideas?{' '}
<Link href="/" passHref>
<a className="link">Browse games by category</a>
</Link>
</span>
</FormSection>
<FormSection
title="Location"
description="Help gamers in the area discover your event and let attendees know where to show up."
icon="map"
>
{renderLocation(formikProps)}
</FormSection>
<FormSection
title="Date and time"
description="Tell gamers when your event starts and ends so they can make plans to attend."
icon="date_range"
>
<InputGroup
name="starts_at"
value={values.starts_at}
onChange={handleChange}
onBlur={handleBlur}
label="Event starts"
placeholder="Search for a venue or address"
type="datetime-local"
// icon="calendar_today"
error={
errors.starts_at && touched.starts_at
? errors.starts_at
: undefined
}
/>
<InputGroup
name="ends_at"
value={values.ends_at}
onChange={handleChange}
onBlur={handleBlur}
label="Event ends"
placeholder="Search for a venue or address"
type="datetime-local"
// icon="calendar_today"
error={
errors.ends_at && touched.ends_at ? errors.ends_at : undefined
}
/>
</FormSection>
</Form>
);
}}
</Formik>
);
}
export default BasicInfo;
My form validation was preventing me from submitting
I have a component that I want to test that uses Vuex.
components/Main/Header.vue
<template>
<v-container fluid grid-list-xl>
<v-card flat class="header" color="transparent">
<v-layout align-center justify-start row fill-height class="content">
<v-flex xs5>
<v-img :src="avatar" class="avatar" aspect-ratio="1" contain></v-img>
</v-flex>
<v-flex xs7>
<div class="main-text font-weight-black">
WELCOME
</div>
<div class="sub-text">
{{currentLocation.description}}
</div>
<div #click="showStory" class="show-more font-weight-bold">
Explore More
</div>
</v-flex>
</v-layout>
</v-card>
</v-container>
</template>
<script>
import avatar from '../../assets/images/home/avatar.png';
export default {
name: 'Header',
computed: {
currentLocation() {
return this.$store.getters.getCurrentLocation;
},
avatar() {
return avatar;
}
},
methods: {
showStory() {
this.$router.push( { name: 'Stories', params: { name: 'Our Story' } });
}
}
}
</script>
and from /test/unit/components/Main/Header.spec.js
import Vuex from 'vuex'
import { shallowMount, createLocalVue } from "#vue/test-utils"
import Header from "#/components/Main/Header.vue"
const localVue = createLocalVue()
localVue.use(Vuex)
const store = new Vuex.Store({
state: {
currentLocation: {
name: 'this is a name',
description: "lorem ipsum",
latitude: '1.123123',
longitude: '103.123123',
radius: '5000'
}
},
getters: {
getCurrentLocation: (state) => state.currentLocation
}
})
describe('Header', () => {
const wrapper = shallowMount(Header, {
store,
localVue
})
it('should render a computed property currentLocation', () => {
expect(Header.computed.currentLocation()).toBe(store.getters.getCurrentLocation)
});
});
The error I'm getting is from the computed property currentLocation
TypeError: Cannot read property 'getters' of undefined
I am learning about unit-testing in Vue and try to test component according to this article https://alligator.io/vuejs/testing-vue-with-jest/
I have a component
<template>
<div>
<h1 :style="headingStyles">{{title}}</h1>
</div>
</template>
<script>
export default {
data() {
return {
headingStyles: {
color: this.color
}
};
},
props: ["title", "color"]
};
</script>
and file with test cases
import Vue from 'vue';
import FancyHeading from '../../src/components/FancyHeading';
function mountComponentWithProps (Component, propsData) {
console.log('props Data', propsData)
const Constructor = Vue.extend(Component);
const vm = new Constructor({
propsData
}).$mount();
return vm.$el;
}
describe('FancyHeading.vue', () => {
it('should be the correct color', () => {
const headingData = mountComponentWithProps(FancyHeading, { color: 'blue' });
const styleData = headingData.style.getPropertyValue('color');
console.log(styleData)
expect(styleData).toEqual('blue');
});
it('should have the correct title', () => {
const headingData = mountComponentWithProps(FancyHeading, { title: 'Hello, Vue!' });
const titleData = headingData.textContent;
expect(titleData).toEqual('Hello, Vue!');
});
});
When I run yarn test:unit I receive error
FancyHeading.vue › should be the correct color
expect(received).toEqual(expected) // deep equality
Expected: "blue"
Received: ""
Looks like color is empty xtring, but I don't understand why. Can someone explain me and help to pass test?
I am testing that form data are sent after submit.
ContactForm.spec.js
import Vue from "vue";
import Vuex from "vuex";
import { mount, shallowMount } from "#vue/test-utils";
import VeeValidate from "vee-validate";
import i18n from "#/locales";
import Vuetify from "vuetify";
import ContactForm from "#/components/Home/ContactForm.vue";
Vue.use(VeeValidate, { errorBagName: "errors" });
Vue.use(Vuetify);
Vue.use(Vuex);
describe("ContactForm.vue", () => {
let store;
let wrapper;
let options;
let input;
const v = new VeeValidate.Validator();
beforeEach(() => {
const el = document.createElement("div");
el.setAttribute("data-app", true);
document.body.appendChild(el);
});
it("should sendMessage - valid form", async () => {
// given
store = new Vuex.Store({
state: {
language: "en",
loading: false
}
})
options = {
sync: false,
provide: {
$validator () {
return new VeeValidate.Validator();
}
},
i18n,
store
};
wrapper = mount(ContactForm, options);
// when
const radioInput = wrapper.findAll('input[type="radio"]');
radioInput.at(1).setChecked(); // input element value is changed, v-model is not
radioInput.at(1).trigger("change"); // v-model updated
input = wrapper.find('input[name="givenName"]');
input.element.value = "John"; // input element value is changed, v-model is not
input.trigger("input"); // v-model updated
input = wrapper.find('input[name="familyName"]');
input.element.value = "Doe"; // input element value is changed, v-model is not
input.trigger("input"); // v-model updated
input = wrapper.find('input[name="email"]');
input.element.value = "john.doe#example.com"; // input element value is changed, v-model is not
input.trigger("input"); // v-model updated
input = wrapper.find('textarea[name="messageContent"]');
input.element.value = "Hello World!"; // input element value is changed, v-model is not
input.trigger("input"); // v-model updated
const contactForm = wrapper.find("form");
contactForm.trigger("submit");
await wrapper.vm.$nextTick();
// then
console.log("DATA: ", wrapper.vm.$data.contactLang);
expect(wrapper.vm.validForm).toEqual(true);
});
});
Validation is successful ( so validForm is set to true in the component )
BUT the test does not pass
console.log
✕ should sendMessage - valid form (476ms)
● ContactForm.vue › should sendMessage - valid form
expect(received).toEqual(expected)
Expected value to equal:
true
Received:
false
The component vue is
ContactForm.vue
<template>
<form id="contactForm" #submit="sendMessage()">
<input v-model="contactLang" type='hidden' data-vv-name="contactLang" v-validate="'required'" name='contactLang'>
<v-layout row wrap align-center>
<v-flex xs12 sm3 md3 lg3>
<v-radio-group row :mandatory="false" v-model="gender" name="gender">
<v-radio :label='genderLabel("f")' value="f" name="female"></v-radio>
<v-radio :label='genderLabel("m")' value="m" name="male"></v-radio>
</v-radio-group>
</v-flex>
<v-flex xs12 sm4 md4 lg4>
<v-text-field
v-model="givenName"
browser-autocomplete="off"
:label="$t('lang.views.home.contactForm.givenName')"
data-vv-name="givenName"
:error-messages="errors.collect('givenName')"
v-validate="'required'"
name="givenName">
</v-text-field>
</v-flex>
<v-flex xs12 sm5 md5 lg5>
<v-text-field
v-model="familyName"
browser-autocomplete="off"
:label="$t('lang.views.home.contactForm.familyName')"
data-vv-name="familyName"
:error-messages="errors.collect('familyName')"
v-validate="'required'"
name="familyName">
</v-text-field>
</v-flex>
</v-layout>
<v-text-field
browser-autocomplete="off"
v-model="email"
:label="$t('lang.views.home.contactForm.email')"
data-vv-name="email"
:error-messages="errors.collect('email')"
v-validate="'required|email'"
name="email">
</v-text-field>
<v-textarea v-model="messageContent" :label="$t('lang.views.home.contactForm.message')" :error-messages="errors.collect('messageContent')" :rules="[(v) => v.length <= 200 || 'Max 200 characters']" :counter="200" v-validate="'required'" data-vv-name="messageContent" name="messageContent"></v-textarea>
<v-btn id="btnClear" round #click.native="clear">{{ $t('lang.views.global.clear') }}</v-btn>
<v-btn round large color="primary" type="submit">{{ $t('lang.views.global.send') }}
<v-icon right>email</v-icon><span slot="loader" class="custom-loader"><v-icon light>cached</v-icon></span>
</v-btn>
</form>
</template>
<script>
import swal from "sweetalert2";
import { mapState } from "vuex";
import appValidationDictionarySetup from "#/locales/appValidationDictionary";
export default {
name: "contactForm",
$_veeValidate: { validator: "new" },
data() {
return {
contactLang: "",
gender: "f",
givenName: "",
familyName: "",
email: "",
messageContent: "",
validForm: false
};
},
...
methods: {
...
sendMessage: function() {
console.log("sendMessage()...");
this.$validator
.validateAll()
.then(isValid => {
console.log("VALIDATION RESULT: ", isValid);
this.validForm = isValid;
if (!isValid) {
console.log("VALIDATION ERROR");
// console.log("Errors: ", this.$validator.errors.items.length);
const alertTitle = this.$validator.dictionary.container[
this.language
].custom.error;
const textMsg = this.$validator.dictionary.container[this.language]
.custom.correct_all;
swal({
title: alertTitle,
text: textMsg,
type: "error",
confirmButtonText: "OK"
});
return;
}
console.log("validation success, form submitted validForm: ", this.validForm);
return;
})
.catch(e => {
// catch error from validateAll() promise
console.log("error validation promise: ", e);
this.validForm = false;
return;
});
},
clear: function() {
this.contactLang = "";
this.gender = "f";
this.givenName = "";
this.familyName = "";
this.email = "";
this.messageContent = "";
this.validForm = false;
this.$validator.reset();
}
},
mounted() {
appValidationDictionarySetup(this.$validator);
this.$validator.localize(this.language);
this.contactLang = this.language;
}
};
</script>
</style>
and the console.log debugging is
console.log src/components/Home/ContactForm.vue:90
sendMessage()...
console.log tests/unit/ContactForm.spec.js:242
DATA: en
console.log src/components/Home/ContactForm.vue:94
VALIDATION RESULT: true
It's weird to see that the DATA ( contactLang ) value is false in the console.log from the spec ... displayed before the validation result
console.log src/components/Home/ContactForm.vue:90
sendMessage()...
console.log tests/unit/ContactForm.spec.js:242
DATA: en
console.log src/components/Home/ContactForm.vue:94
VALIDATION RESULT: true
console.log src/components/Home/ContactForm.vue:112
validation success, form submitted validForm: true
I guess there is async problem ... timout ?
thanks for feedback
SOLVED
It's actually a timeout issue
expect.assertions(1); // Otherwise jest will give a false positive
await contactForm.trigger("submit");
// then
setTimeout(() => {
expect(wrapper.vm.validForm).toEqual(true);
}, 2000);
I propose to use jest faketimers
jest.useFakeTimers()
contactForm.trigger("submit");
await wrapper.vm.$nextTick();
// then
jest.runTimersToTime(2000)
expect(wrapper.vm.validForm).toEqual(true);
I suggest to first make the test fail to avoid false positives
for more information about jest faketimers
https://jestjs.io/docs/en/timer-mocks.html
i did a simple test for my login form of component, in case it helps someone
it("submit form call method login", () => {
const login = jest.fn()
const wrapper = shallowMount(Login, {
methods: {
login
}
})
wrapper.findAll("v-form").at(0).trigger("submit")
expect(login).toBeCalled()
})
I have a react-redux application, in which i am trying to run test cases for a react component something like below:
class Login extends Component {
componentWillMount() {
this.props.checkUserAuth();
}
componentDidMount() {
this.props.getEnvConfig();
}
componentDidUpdate() {
if (!this.props.isAuthenticating && this.props.isAuthenticated) {
hashHistory.push('/dashboard');
}
}
getAbc() {
return this.props.abc;
}
anotherLogin() {
return () => {
const anotherURL = `${this.props.envConfig.AuthUrl}?response_type=code&client_id=${this.props.envConfig.ClientId}&redirect_uri=${this.props.envConfig.CallbackUri}&state=8.0`;
/* global window */
window.location.assign(anotherURL);
};
}
myLogin() {
return () => {
const loginUrl = `${this.props.envConfig.AuthUrl}?
scope=urlScope&client_id=${this.props.envConfig.ClientId}&redirect_uri
=${this.props.envConfig.RedirectUri}&response_type=token`;
/* global window */
window.location.assign(loginUrl);
};
}
render() {
if (this.props.isAuthenticating && !this.props.isAuthenticated) {
return (<div>loading</div>); // needs to implement and include loading
component
} else if (!this.props.isAuthenticating && !this.props.isAuthenticated) {
return (
<Grid fluid="true">
<Row>
<Col md={6} bsClass="xyz">
<div className="left-login-container">
<LoginLeft
logo={logo}
box={box}
abc={this.abc()}
/>
</div>
</Col>
<Col md={6} bsClass="xyz">
<div className="right-login-container">
<LoginRight
myLogin={this.myLogin()}
anotherLogin={this.anotherLogin()}
/>
</div>
</Col>
</Row>
</Grid>
);
}
return null;
}
}
Login.defaultProps = {
abc: '0',
getEnvConfig: () => {},
envConfig: {
sfdcAuthUrl: '',
sfdcCallbackUri: '',
sfdcClientId: '',
},
isAuthenticating: true,
isAuthenticated: false,
checkUserAuth: () => {},
};
Login.propTypes = {
abc: PropTypes.string.isRequired,
getEnvConfig: PropTypes.func.isRequired,
envConfig: PropTypes.shape({
AuthUrl: PropTypes.string.isRequired,
CallbackUri: PropTypes.string.isRequired,
ClientId: PropTypes.string.isRequired,
}),
isAuthenticating: PropTypes.bool.isRequired,
isAuthenticated: PropTypes.bool.isRequired,
checkUserAuth: PropTypes.func.isRequired,
};
function mapDispatchToProps(dispatch) {
return {
myLogin: (data) => {
dispatch(myLogin(data));
},
getEnvConfig: () => {
dispatch(getEnvConfig());
},
checkUserAuth: () => {
dispatch(getUserInfo());
},
};
}
function mapStateToProps(state, ownProps) {
return {
abc: state.Login.Summary.Report,
envConfig: state.EnvConfig.envConfig,
isAuthenticating: state.Auth.isAuthenticating,
isAuthenticated: state.Auth.isAuthenticated,
};
}
export default connect(mapStateToProps, mapDispatchToProps)(Login);
I am going somewhere wrong in mocking the store and creating the shallow for his login component before even writing a test case i am getting the error "Uncaught TypeError: WEBPACK_IMPORTED_MODULE_0__compose.a.apply(...) is not a function" Not sure abt the reason behind it. Here is the spec file content:
import React from 'react';
import { createStore, applyMiddleware } from 'redux';
import { shallow, mount } from 'enzyme';
import configureStore from 'redux-mock-store';
import LoginReducer from '../../../reducers/rootReducers';
import thunk from 'redux-thunk'
import Login from './LoginPage';
const mockStore = configureStore([LoginReducer]);
const initialState = {
SummaryStats: {
Reports: '0',
},
isAuthenticated: false,
isAuthenticating: true,
userInfo: {
firstName: 'Ruchir',
},
envConfig: {},
};
const store = mockStore(initialState);
const dummyData = {
abc: '0',
getEnvConfig: () => {},
envConfig: {
AuthUrl: '',
CallbackUri: '',
ClientId: '',
},
};
const LoginWrapper = shallow(<Login
store={store}
{...dummyData}
/>);
describe('<Login />', () => {
it('check componentDidMount method', () => {
LoginWrapper.componentDidMount();
expect(LoginWrapper.props().getEnvConfig).toHaveBeenCalled();
});
});