How to test socket io from vue jest? - vue.js

this is my code from vue.js:
async getUserInformation(user_id){
return await new Promise((resolve, reject) => {
this.$socket.client.emit('getUserInfo', user_id, (err,res) => {
err ? reject(err) : resolve(res)
})
})
},
async selectAction() {
let getReponse= await this.getUserInformation(this.user_id)
this.userInformation = getResponse
}
this is my code from vue jest
describe('editUser.vue', () => {
let wrapper
beforeEach(() => {
wrapper = shallowMount(editUser, {
mixins: [global]
})
});
it('trigger submit button w/o data input from text fields', async () => {
await wrapper.find('[data-testid="get_user_button"]').trigger('click')
});
});
Picture below is the error message I received after I run unit testing

Related

Vue unit test is holds old component code in wrapper

I am doing unit test of vue component methods through vue-test-utils and facing an weird issue. wrapper.vm.somemthod() is executing old code that was written earlier inside the method. It's printing old console.log statements. If I put new console.log statement, it's not printing that at all. Am I missing something?
import { mount, shallowMount } from '#vue/test-utils'
import TestComponent from '#/components/TestComponent.vue'
const mockMixin = {
methods: {
InnerMethod() {
return 2;
},
}
}
describe('Test Screen', () => {
let wrapper;
let mock;
beforeAll(() => {
mock = new MockAdapter(api);
})
beforeEach(() => {
jest.resetModules();
wrapper = mount(TestComponent, {
i18n,
vuetify,
mixins: [mockMixin],
data() {
},
mocks: {
$t: (msg) => msg,
$config: (value) => value,
$store: (value) => value,
$route: (value) => value,
}
});
})
afterEach(() => {
mock.reset();
wrapper.destroy();
wrapper = null;
});
describe('Component Test', () => {
it('getdata', async () => {
expect(wrapper.vm.somedata.length).toBe(0);
const spy = jest.spyOn(wrapper.vm, 'InnerMethod');
wrapper.vm.someMethod();
expect(spy).toBeCalledTimes(1);
expect(wrapper.vm.somedata.length).toBe(2);
});
});
});

Unit tests, check if function have been called

I need to implement a test that checks if the function has been called on the button click
onSave (e) {
this.$qiwaApi.createDimension()
.then(() => {})
.catch(err => this.showSnackbar(err.message))}
I need to test the function createDimension. In my test i mocked it
const createComponent = () => {
wrapper = mount(dimensions, {
store,
localVue,
mocks: {
$qiwaApi: {
createDimension: function (e) {
return new Promise((resolve) => { resolve({}) })
}
}
},
router
})
}
In the project, the function exported this way
export default $axios => ({
createDimension (data, surveyId) {
return $axios.post(`/lmi-admin/surveys/${surveyId}/dimension`, {
data: {
attributes: {
...data
}
}
})
}
})
I expect this test to work. But for some reason wrapper.qiwaApi or wrapper.createDimension return undefined
expect(wrapper.$qiwaApi.createDimension).toHaveBeenCalled()
The wrapper doesn't provide access to your mocks that way.
You would have to hold a reference to a jest.fn(), and then verify the calls on that reference directly instead of trying to pull it out of the wrapper:
it('calls createDimension on button click', async () => {
const createDimension = jest.fn(() => Promise.resolve())
const wrapper = mount(dimensions, {
mocks: {
$qiwaApi: {
createDimension
}
}
})
await wrapper.find('[data-testid="save"]').trigger('click')
expect(createDimension).toHaveBeenCalled()
})
demo

How can I test my custom react hook that uses fetch?

I have created a custom react hook which uses fetch from whatwg-fetch. I have tests for the components that make use of the hook and can mock the whole hook, but now am trying to write tests for the hook itself and my goal is to mock the fetch response. This is my hook.
import { useState, useEffect } from "react";
import "whatwg-fetch";
export default function useFetch(url) {
const [data, setData] = useState(undefined);
const [response, setResponse] = useState(undefined)
const [isLoading, setLoading] = useState(true);
const [error, setError] = useState(undefined);
useEffect(() => {
try {
const fetchData = async () => {
const result = await fetch(url);
setResponse(result);
const responseText = await result.text();
setData(responseText);
setLoading(false);
};
fetchData();
} catch (error) {
setError(error);
}
}, [url]);
return { data, response, isLoading, error };
}
export { useFetch }
Currently, this is how my test looks like. Feels like I cannot mock the fetch to return the desired value.
I have tried writing tests by looking at several tutorials with no luck. I have tried the following tutorials:
Test Custom Hooks Using React Hooks Testing Library
Testing custom react hooks with jest
A Complete Guide to Testing React Hooks
UPDATE: Changed tests, my first test passes (resolve) my second one does not. Based on the third tutorial.
NEW TESTS
import React from "react";
import { render, unmountComponentAtNode } from "react-dom";
import { act } from "react-dom/test-utils";
import useFetch from "./useFetch";
function sleep(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
let container = null;
describe("useFetch tests", () => {
beforeEach(() => {
// setup a DOM element as a render target
container = document.createElement("div");
document.body.appendChild(container);
});
afterEach(() => {
// cleanup on exiting
unmountComponentAtNode(container);
container.remove();
container = null;
});
it("useFetch returns data on success", async () => {
function fetchMock(url) {
return new Promise((resolve) => setTimeout(() => {
resolve({
status: 200,
ok: true,
text: () => Promise.resolve({
data: "data from api"
})
});
}, 300));
}
jest.spyOn(global, "fetch").mockImplementation(fetchMock);
act(() => {
render(<TestComponent url="url1" />, container);
});
expect(container.textContent).toBe("loading");
await sleep(500);
expect(container.textContent).toBe("data from api");
});
it("useFetch return error on fail", async () => {
// const a = 200 + Math.random() * 300;
// console.log(a)
// let promise = new Promise(function (resolve, reject) {
// // after 1 second signal that the job is finished with an error
// setTimeout(() => reject("error"), a);
// });
// function fetchMock(url) {
// return promise;
// }
function fetchMock(url) {
return new Promise((resolve) => setTimeout(() => {
resolve({
status: 404,
ok: true,
text: () => Promise.resolve({
data: "data from api"
})
});
}, 200 + Math.random() * 300));
}
jest.spyOn(global, "fetch").mockImplementation(fetchMock);
act(() => {
render(<TestComponent url="url1" />, container);
});
expect(container.textContent).toBe("loading");
await sleep(500);
expect(container.textContent).toBe("error");
});
});
function TestComponent({ url }) {
const {
data, response, isLoading, error
} = useFetch(url);
if (isLoading) {
return <div>loading</div>;
}
if (data) {
return <div>{data.data}</div>
}
if (error) {
return <div>error</div>
}
return <div></div>;
}
OLD TESTS
import { useFetch } from "../../../src/utils/custom-hooks/useFetch";
describe("useFetch tests", () => {
beforeEach(() => {
jest.spyOn(window, "fetch");
});
it("200", () => {
window.fetch.mockResolvedValueOnce({
ok: true,
status: 200,
})
const { result, rerender } = renderHook(
(url) => useFetch(url),
{
url: "url1"
}
);
expect(result.current.response).toBe(undefined);
rerender("url2");
expect(result.current.status).toBe(200);
});
});

Jest Mocking with Quasar and Typescript

I want to mock Amplify Auth service in my test. There is no error, but test doesn't work because of my mock.
Here is the code I'm about to test:
signIn(): void {
if (!this.valid) return;
this.loading = 1;
this.$Auth
.signIn(this.email, this.password)
.then(() => this.$router.push({ name: "homeManagement" }))
.catch((err: any) => (this.errorMessage = err.message))
.finally(() => (this.loading = 0));
}
Here is the test:
const $t = jest.fn();
$t.mockReturnValue("");
const $Auth = jest.fn();
$Auth.mockReturnValue({
code: "UserNotFoundException",
name: "UserNotFoundException",
message: "User does not exist."
});
const factory = mountFactory(LoginForm, {
mount: {
mocks: {
$Auth
}
}
});
describe("LoginForm", () => {
it("User not found", async () => {
const wrapper = factory();
await wrapper.setData({
email: "david#gmail.com",
password: "Qwer321"
});
await wrapper.vm.signIn();
expect(wrapper.vm.$data.errorMessage.length).not.toEqual(0);
});
});
Figured out a solution, but maybe there is a better one flush-promises to mock Amplify call:
const $Auth = jest.fn();
$Auth.signIn = () => Promise.resolve();
describe("LoginForm", () => {
it("User does not exist", async () => {
const wrapper = factory();
await wrapper.setData({
email: "david#gmail.com",
password: "Qwer321",
valid: true
});
await wrapper.vm.signIn();
await flushPromises();
expect(wrapper.vm.$data.errorMessage.length).not.toEqual(0);
});
});

How to mock axios call within a method?

I am trying to mock an axios call within a vuejs method. Is this possible?
Here is my vue component (SomeObj):
methods:{
callAxiosMethod() {
const callApi= axios.create();
callApi.defaults.timeout = 10000;
callApi.get(mockedUrl)
.then(response => {
console.log('response is ' + response);
})
.catch(e => {});
}
}
Here is my spec.js
let mockData = {};
beforeEach(() => {
jest.spyOn(axios, 'get').mockReturnValue(Promise.resolve(mockData));
});
let wrapper = shallowMount(SomeObj, {
stubs: [], localVue, mocks: {
mockUrl: mockUrl,
$route: {
params: { testId: "123" }
}
}
});
it('is a Vue instance', () => {
expect(wrapper.isVueInstance()).toBeTruthy();
axios.get.mockResolvedValue(mockData);
wrapper.vm.callAxiosMethod();
})
When I looked at the coverage, the system says the callApi is not covered. Any idea on how I can mock the axios call within the function?
Your code calls axios.create so you need to mock that function to return a mock callApi object.
Here is a simplified working example:
code.js
import * as axios from 'axios';
const mockedUrl = 'http://mock-url';
export const callAxiosMethod = () => {
const callApi = axios.create();
callApi.defaults.timeout = 10000;
return callApi.get(mockedUrl); // <= return the Promise so it can be awaited
}
code.test.js
import { callAxiosMethod } from './code';
jest.mock('axios', () => ({
create: jest.fn().mockReturnValue({
defaults: {},
get: jest.fn().mockResolvedValue('mocked data')
})
}));
test('callAxiosMethod', async () => { // <= async test function
const response = await callAxiosMethod(); // <= await the Promise
expect(response).toBe('mocked data'); // Success!
});