Test case React with Node js - node.js

My site is using react and node . For that I created the test case using enzyme at react side and from server site I am using Mocha. Both are working correctly when I am using terminal command (npm test) its showing fail ans success result. But I want to do test case from ui interface .
Basically i want to backed (nodejs) function fronted with one command, Now my test case working on different terminal For example for react I am opened in one terminal and for node side test case I oped another terminal.
this is my node side code :-
const request = require('supertest');
const expect = require('chai').expect;
const req = 'http://localhost:3000';
this.user_id = '';
describe('Register form', function() {
it('User saved successfully in database', function(done) {
request(req)
.post('/users/register')
.set('Accept', 'application/json')
.set('Content-Type', 'application/json')
.send({user:{disabled: false,
email: "dineshsharma.developer#gmail.com",
firstName: "test",
lastName: "test",
password: "24234234ds",
roles: "hr",
status: "verified"}})
.expect(200)
.expect('Content-Type', /json/)
.expect(function(response) {
})
.end(done);
});
});
and this is react side code:-
import React from 'react';
import { Link } from 'react-router-dom';
import { connect } from 'react-redux';
import Select from 'react-select'
import config from 'config';
import { Alert } from 'reactstrap';
import { userActions } from '../../../src/actions';
import Enzyme, {shallow,mount,render,unmount} from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
import RegisterPage from '../../../src/features/RegisterPage/RegisterPage';
import { MemoryRouter } from 'react-router-dom';
Enzyme.configure({adapter: new Adapter()});
describe('In register page check react syntex', () => {
it('Should RegisterPage shallow correctly in "debug" mode', () => {
const component = (<RegisterPage debug />);
expect(component).toMatchSnapshot();
});
});
describe('On register page count input filed', () => {
it('Total text filed', () => {
expect(shallow(<RegisterPage />).find('input[type="text"]').length).toEqual(2)
})
it('Total email filed', () => {
expect(shallow(<RegisterPage />).find('input[type="email"]').length).toEqual(1)
})
it('Total checkbox filed', () => {
expect(shallow(<RegisterPage />).find('input[type="checkbox"]').length).toEqual(1)
})
it('Total radio filed', () => {
expect(shallow(<RegisterPage />).find('input[type="radio"]').length).toEqual(2)
})
});
describe('On Register page check firstname , lastname or email address vaildation', () => {
it('Check first name in registerpage ', () => {
const wrapper = mount(<RegisterPage />);
wrapper.find('input[name="firstName"]').simulate('change', {target: {name: 'firstName', value: 'dinesh'}});
expect(wrapper.state().user.firstName).toEqual('dinesh');
})
it('Check lastname in register page ', () => {
const wrapper = mount(<RegisterPage />);
wrapper.find('input[name="lastName"]').simulate('change', {target: {name: 'lastName', value: 'Sharma'}});
expect(wrapper.state().user.lastName).toEqual('Sharma');
})
it('Check email address in register page', () => {
const wrapper = mount(<RegisterPage />);
wrapper.find('input[name="email"]').simulate('change', {target: {name: 'email', value: 'dineshsharma.developer#gmail.com'}});
expect(wrapper.state().user.email).toEqual('dineshsharma.developer#gmail.com');
})
})

If you want to run front end and back end test together in one terminal you can modify your package.json scripts section to look something like this.
{
"scripts": {
"test": "mocha <path to node test files> && jest <path to react test files>"
}
}
Every time you run npm test both sets of tests will run.

Related

Can I apply 'setupFilesAfterEnv' to specific file in jest config?

I'm working on appling prisma unit testing and Integration testing
I want to apply unit testing for *.service.test.ts files
and intergration testing for *.test.ts files.
I followed the Prisma document, but there is something that doesn't work.
singleton.ts
import { mockReset, mockDeep, DeepMockProxy } from "jest-mock-extended";
import { PrismaClient } from "#prisma/client";
import Prisma from "../src/db/prisma";
jest.mock("../src/db/prisma", () => {
return {
__esModule: true,
default: mockDeep<PrismaClient>(),
};
});
beforeEach(() => {
// eslint-disable-next-line no-use-before-define
mockReset(prismaMock);
});
export const prismaMock = Prisma as unknown as DeepMockProxy<PrismaClient>;
jest.config.ts
When turing off setupFilesAfterEnv option, testing *.test.ts files are working.
So I Want turn off setupFilesAfterEnv option in Integration testing
Is it applicable only when unit testing?
...
setupFilesAfterEnv: [
"./jest/singleton.ts"
]
I think your question is a bit incomplete, but I might know what you are talking about because I am running into a similar problem.
If you are trying to do the integration tests from prisma documentation, you need to unmock your prisma client on your integration tests. Otherwise it will still be mocked by your singleton.ts file
something like this:
myTest.test.js (integration test file)
jest.unmock("../src/db/prisma");
Another way of doing it, is just to remove the singleton from setupFilesAfterEnv and just import the prisma client from the singleton file inside your tests.
What I did:
I created 2 tests files (one for integration and another one for unit testing: CreateData.unit.test.ts and CreateData.int.test. I also created 2 singleton files:
singleton.unit.ts (I wanted that to be applied on my unit tests)
import { PrismaClient } from '#prisma/client';
import { mockDeep, mockReset, DeepMockProxy, mock } from 'jest-mock-extended';
import prismaClient from '../prismaClient';
jest.mock('../prismaClient', () => ({
__esModule: true,
default: mockDeep<PrismaClient>(),
}));
beforeEach(() => {
mockReset(prismaMock);
});
export const prismaMock = prismaClient as unknown as DeepMockProxy<PrismaClient>;
singleton.int.ts (I wanted that applied in my integration tests)
import prismaClient from '../prismaClient';
afterAll(async () => {
const deleteData = prismaClient.data.deleteMany();
await prismaClient.$transaction([
deleteData,
]);
await prismaClient.$disconnect();
});
export { prismaClient };
I removed setupFilesAfterEnv from jest.config.js
Then create your unit tests and integration tests. You don't need to unmock prisma client if you removed the singleton from setupFilesAfterEnv in jest.config.ts
myTest.unit.test.ts
import { prismaMock } from "<path>/singleton.unit";
import { CreateData } from "<path>/CreateData";
let createData;
let createDate = new Date();
const data = {
id: "randomId1234",
name: "Bob Singer",
email: "bob#gmail.com",
password: "123456",
};
beforeEach(() => {
createData = new CreateData();
});
describe('CreateData', () => {
it("should create new data", async () => {
const result = createData.execute(data);
prismaMock.data.create.mockResolvedValue(data);
await expect(result).resolves.toEqual({
id: "randomId1234",
name: "Bob Singer",
email: "bob#gmail.com",
password: "123456",
});
});
});
myTest.int.test.ts
import prismaClient from "<path>/singleton.int";
import { CreateData } from "<path>/CreateData"
let createData;
let createDate = new Date();
const data = {
id: "randomId1234",
name: "Bob Singer",
email: "bob#gmail.com",
password: "123456",
};
beforeEach(() => {
createData = new CreateData();
});
describe('CreateTrainer', () => {
it("should create new trainer", async () => {
const result = await createData.execute(data);
const newData = await prismaClient.data.findUnique({
where: {
email: "bob#gmail.com"
}
});
console.log(result);
expect(newData?.email).toEqual(data.email);
});
});

How to test a function in React Component with Jest + Enzyme?

I am using the testing-library/jest-dom + Enzyme to do the unit testing.and here I need to test a funtion inside a React function.
import React, { useEffect } from 'react';
function Component1() {
useEffect( async () => {
fetchSomeData();
}, [])
const fetchSomeData = async () =>{
console.log('fetchSomeData')
}
return <div>Component1</div>;
}
export default Component1;
and my test file:
Enzyme.configure({adapter:new Adapter()})
describe('Name of the group', () => {
it('should ', () => {
const wrapper = shallow( <Component1/>)
expect(wrapper.exists());
});
});
in fact I don't need to test the correctness , I just need the code be covered in jest. but whatever I tried , it seems not covered by jest:

Jest unit test to spy on lower-level method (NodeJS)

Trying to spy and override a function two levels down using Jest.
The test results say, "Expected mock function to have been called, but it was not called."
// mail/index.unit.test.js
import mail from './index';
import * as sib from '../sendinblue';
describe('EMAIL Util', () =>
test('should call sibSubmit in server/utils/sendinblue/index.js', async() => {
const sibMock = jest.spyOn(sib, 'sibSubmit');
sibMock.mockImplementation(() => 'Calling sibSubmit()');
const testMessage = {
sender: [{ email: 'foo#example.com', name: 'Something' }],
to: [{ email: 'foo#example.com', name: 'Something' }],
subject: 'My Subject',
htmlContent: 'This is test content'
};
await mail.send(testMessage);
expect(sibMock).toHaveBeenCalled();
})
);
mail.send() comes from here...
// mail/index.js
import { sibSendTransactionalEmail } from '../sendinblue';
export default {
send: async message => {
try {
return await sibSendTransactionalEmail(message);
} catch(err) {
console.error(err);
}
}
};
Which uses SendInBlue's API via axios (why I need to mock)...
// sendinblue/index.js
import axios from 'axios';
import config from '../../config/environment';
export async function sibSubmit(method, url, data) {
let instance = axios.create({
baseURL: 'https://api.sendinblue.com',
headers: { 'api-key': config.mail.apiKey }
});
try {
const response = await instance({
method,
url,
data
});
return response;
} catch(err) {
console.error('Error communicating with SendInBlue', instance, err);
}
}
export const sibSendTransactionalEmail = message => sibSubmit('POST', '/v3/smtp/email', message);
I assumed mail.send() would call sibSendTransactionalEmail() in the other module and it would call sibSubmit(), the focus of jest.spyOn(). Wondering where I went wrong.
jest.spyOn replaces the method on the object it is passed with a spy.
In this case you are passing sib which represents the ES6 module exports from sendinblue.js, so Jest will replace the module export for sibSubmit with the spy and give the spy the mock implementation you provided.
mail.send then calls sibSendTransactionalEmail which then calls sibSubmit directly.
In other words, your spy is not called because sibSendTransactionalEmail does not call the module export for sibSubmit, it is just calling sibSubmit directly.
An easy way to resolve this is to note that "ES6 modules support cyclic dependencies automatically" so you can simply import the module into itself and call sibSubmit from within sibSendTransactionalEmail using the module export:
import axios from 'axios';
import config from '../../config/environment';
import * as sib from './'; // import module into itself
export async function sibSubmit(method, url, data) {
let instance = axios.create({
baseURL: 'https://api.sendinblue.com',
headers: { 'api-key': config.mail.apiKey }
});
try {
const response = await instance({
method,
url,
data
});
return response;
} catch(err) {
console.error('Error communicating with SendInBlue', instance, err);
}
}
export const sibSendTransactionalEmail = message => sib.sibSubmit('POST', '/v3/smtp/email', message); // call sibSubmit using the module export
Note that replacing ES6 module exports with jest.spyOn like this works because Jest transpiles the ES6 modules to Node modules in a way that allows them to be mutated
Another way to work around this problem is to rewire the function you're spying on within the module, which is nicer since you don't have to modify the original code for the purposes of testing. You can use the rewire module if before ES6, or babel-rewire for ES6:
// mail/index.unit.test.js
import mail from './index';
import * as sib from '../sendinblue';
describe('EMAIL Util', () =>
test('should call sibSubmit in server/utils/sendinblue/index.js', async() => {
const sibMock = jest.spyOn(sib, 'sibSubmit');
sibMock.mockImplementation(() => 'Calling sibSubmit()');
//============ force the internal calls to use the mock also
sib.__set__("sibSubmit", sibMock);
//============
const testMessage = {
sender: [{ email: 'foo#example.com', name: 'Something' }],
to: [{ email: 'foo#example.com', name: 'Something' }],
subject: 'My Subject',
htmlContent: 'This is test content'
};
await mail.send(testMessage);
expect(sibMock).toHaveBeenCalled();
})
);

Testing if external component method is called in jest

I am using jest and enzyme for unit testing. Below is my index.js file. I need to test openNotification and uploadErrorNotification function of the file. However, only uploadErrorNotification function is exported. So, How do I test both the functions.
Also, I don't want to use any other libray except jest and enzyme.
//index.js
import {
notification
} from 'antd';
const openNotification = (message, description, className) => {
notification.open({
key: 'upload-template',
message,
description,
placement: "bottomRight",
duration: null,
});
};
const uploadErrorNotification = (uploadFailedText, errorMsg) => {
openNotification(uploadFailedText, errorMsg, 'error');
};
export {
uploadErrorNotification
}
This is my test file:
//test.js
import { uploadErrorNotification } from '../index.js
jest.mock('notification', () => ({ open: () => jest.fn() })); // was trying this but I couldn't understand how it will work
describe('Notification validation functions testing', () => {
uploadErrorNotification('Upload failed', 'Something went wrong.');
expect("openNotification").toHaveBeenCalledTimes(1); // want to do something like this
});
You have to mock the external depenency:
first mock antd so that notification.open is a spy
jest.mock('antd', () => ({notification: open: {jest.fn()}}))
Then import the module into your test
import { notification } from 'antd';
Know you can use it like this:
expect(notification.open).toHaveBeenCalledTimes(1);
If you want to test notification without overwrite other antd component, you can add jest.requireActual('antd').
jest.mock('antd', () => {
return {
...jest.requireActual('antd'),
notification: {
open: jest.fn(),
},
};
});

Using socket.io with React and Google App Engine

I've created a Node(express)/React app that uses socket.io and Redux's store as follows:
import io from "socket.io-client";
import * as types from "../actions/types";
import { cancelReview, startReview } from "./actions";
const socket = io("http://localhost:8080", {
transports: ["websocket"]
});
export const init = store => {
socket.on("connect", () => {
console.log("websocket connection successful...");
socket.on("cancelReview", (id, name) => {
cancelReview(store, id, name);
});
socket.on("startReview", (id, name) => {
startReview(store, id, name);
});
});
};
This function is then called from store.js as follows:
import { createStore, applyMiddleware } from "redux";
import { composeWithDevTools } from "redux-devtools-extension/developmentOnly";
import thunk from "redux-thunk";
import rootReducer from "./reducers";
import { init } from "./socket/socket";
// Initial state
const initialState = {};
// Middleware
const middleware = [thunk];
const store = createStore(
rootReducer,
initialState,
composeWithDevTools(applyMiddleware(...middleware))
);
init(store);
export default store;
Everything works fine on my local machine, but I'm now realizing after doing some research that this will not work on Google's app engine because instead of http://localhost:8080 I need to get the actual IP address from Google's metadata server and pass in EXTERNAL_IP + ":65080". So I'm able to get the external IP in my express app as follows:
const METADATA_NETWORK_INTERFACE_URL =
"http://metadata/computeMetadata/v1/instance/network-interfaces/0/access-configs/0/external-ip";
function getExternalIp(cb) {
const request = axios.create({
baseURL: METADATA_NETWORK_INTERFACE_URL,
headers: { "Metadata-Flavor": "Google" }
});
request
.get("/", (req, res) => {
return cb(res.data);
})
.catch(err => {
console.log("Error while talking to metadata server, assuming localhost");
return cb("localhost");
});
}
However, if I pass this value into my render function as seen below, React creates a prop to pass into components (as far as I understand from the info I could find):
app.get("*", (req, res) => {
getExternalIp(extIp => {
res.render(path.resolve(__dirname, "client", "build", "index.html"), {
externalIp: extIp
});
});
I am not able to access this value via the window global. So my question is, how do I access this external IP from my store initialization, since it is not an actual React component?
Thanks in advance.

Resources