Mock .get() Function using Jest on VueJS - vue.js

I am trying to mock a GET request to get some Posts using the ID. This is the code I am trying to mock:
getPost() {
this.refreshToken();
http
.get(`/posts/${this.$cookie.get('postid')}`, {
headers: {
"Authorization": `Bearer ${this.$cookie.get('token')}`,
"Content-type": "application/json",
},
})
.then((response) => {
this.post = response.data;
})
.catch((error) => {
console.log(error.response);
});
}
This is my attempt at a test:
import {getPost} from '#/views/Post.vue'
import axios from 'axios';
jest.mock('axios');
describe('get Post by ID', () => {
afterEach(() => {
jest.resetAllMocks();
});
it('should return empty when axios.get failed', async () => {
const getError = new Error('error');
axios.get = jest.fn().mockRejectedValue(getError);
const actualValue = await getPost();
expect(actualValue).toEqual(new Map());
expect(axios.get).toBeCalledWith('/posts/postid');
});
it('should return users', async () => {
const mockedUsers = [{ postID: 1 }];
axios.get = jest.fn().mockResolvedValue(mockedUsers);
const actualValue = await getPost(['1']);
expect(actualValue).toEqual(mockedUsers);
expect(axios.get).toBeCalledWith('/posts/postid');
});
})
The error I am getting is:
TypeError: (0 , _Post.getPost) is not a function
I am not sure what to do, and any help would be super appreciated. Thanks!

Assuming you have getPost() defined in the Post component's methods, you can't use named imports to access getPost. Instead, you'll have to mount the component, and use the wrapper's vm:
// Post.spec.js
import { shallowMount } from '#vue/test-utils'
import Post from '#/views/Post.vue'
it('...', () => {
const wrapper = shallowMount(Post)
await wrapper.vm.getPost()
expect(wrapper.vm.post).toEqual(...)
})
Also make sure to return the axios call in getPost() so that it could be awaited:
// Post.vue
export default {
methods: {
getPost() {
this.refreshToken();
👇
return http.get(/*...*/)
.then(/*...*/)
.catch(/*...*/);
}
}
}

Related

How do I make this axios call inside my own API route?

This is my first time trying to make an API call to a third party while inside my own API route. The following code does not work because I get the error "Cannot use import statement outside a module." This code is called by a thunk at the front end.
If I can't import axios, what's an alternative?
EDIT: I got rid of the error by doing 'const axios = require('axios') but now the results I'm getting is undefined.
EDIT2: Resolved. Through use of the following:
router.get("/:zip", async (req, res, next) => {
try {
let data = [];
await axios
.get(`https://api.yelp.com/v3/businesses/search`, {
headers: {
Authorization: `Bearer ${process.env.SECRET_KEY_YELP}`,
},
params: {
location: req.params.zip,
// categories: "coffee",
},
})
.then((response) => {
data = response.data;
});
res.send(data);
} catch (err) {
next(err);
}
});
ORIGINAL CODE WITH ISSUE:
const router = require("express").Router();
module.exports = router;
import axios from "axios";
router.get("/:zip", async (req, res, next) => {
try {
//const restaurants = await Test.findAll({})
const result = await axios.get(
`https://api.yelp.com/v3/businesses/search?location=${req.params.zip}`,
{
headers: {
Authorization: `Bearer ${process.env.SECRET_KEY_YELP}`,
},
params: {
categories: "coffee",
},
}
).data;
res.send(result);
} catch (err) {
next(err);
}
});
Posted above. It needed a .then snippet.
let data = [];
await axios
.get(`https://api.yelp.com/v3/businesses/search`, {
headers: {
Authorization: `Bearer ${process.env.SECRET_KEY_YELP}`,
},
params: {
location: req.params.zip,
// categories: "coffee",
},
})
.then((response) => {
data = response.data;
});
res.send(data);

UseEffect to run a function and that function set hook from another file

So what I want to do is throw my APIs in one file. This way it makes my app way more reusable.
Problem is that I don't know how to do what I'm doing.
My parent file holds all the Hooks I need for data.
I am trying to get the Parent file to call the API, run the call to get the data, then that data then calls back and sets the hook in the parent.
Parent File
import { handleDepartments } from './API/API';
export default function App() {
const [departments, setDepartments] = useState([]);
useEffect(() => {
handleDepartments;
}, []);
The API file..
export const handleDepartments = async () => {
console.log('getting Departments');
const data = await axios
.get(`URI`, {
headers: {
Authorization: 'API_KEY',
Accept: 'application/json',
},
})
.then((response) => {
setDepartments(response.data.departments);
})
.catch((err) => {
console.log(err);
});
};
You're on the right track but its not a great idea to pass down a setState function into the api to update the parent component. Instead, its better practice to make the api call only return data, then the parent can decide how to deal with it.
Api:
export const handleDepartmentsApi = async () => {
await axios
.get(`URI`, {
headers: {
Authorization: 'API_KEY',
Accept: 'application/json',
},
})
.then((response) => {
return data;
})
.catch((err) => {
return err;
});
};
Parent:
export default function App() {
const [departments, setDepartments] = useState([]);
const getDepartments = async () => {
try {
const response = await handleDepartmentsApi();
setDepartments(response.data.departments)
} catch (err) {
//handle error or do whatever
}
}
useEffect(() => {
getDepartments();
}, []);
return (<></>)
}

Axios.post mock function is not called with Jest, VueJS

I want to test my action.
My action has 1 AXIOS request and 1 mutation.
I mocked my axios with jest.mock(“axios” …). I return a Promise.
I defined a mock value with the method mockResolvedValue().
But when I test if my axios.post is called with the method toHaveBeenCalledTimes(1), Jest tells me 0 time.
My test:
My action:
My error:
Someone knows why my axios.post is not called ?
This is the solution:
import actions from '#/store/actions'
import mutations from '#/store/mutations'
import state from '#/store/state'
import store from '#/store'
import axios from 'axios'
let url = ''
let body = {}
jest.mock("axios", () => ({
post: jest.fn((_url, _body) => {
return new Promise((resolve) => {
url = _url
body = _body
resolve(true)
})
})
}))
//https://medium.com/techfides/a-beginner-friendly-guide-to-unit-testing-the-vue-js-application-28fc049d0c78
//https://www.robinwieruch.de/axios-jest
//https://lmiller1990.github.io/vue-testing-handbook/vuex-actions.html#testing-actions
describe('getGameList', () => {
test('Success: should return the game list of the user and update gameList in the store', async () => {
const context= {
state: {
user: {
id:1
}
},
commit: jest.fn()
}
const response = {
data: [
{ id:1, name:"game_name1" },
{ id:2, name:"game_name2" }
]
};
axios.post.mockResolvedValue(response) //OR axios.post.mockImplementationOnce(() => Promise.resolve(response));
await actions.getGameList(context)
expect(axios.post).toHaveBeenCalledWith("api/game_list_of_user",{"user_id":1});
expect(axios.post).toHaveBeenCalledTimes(1)
expect(context.commit).toHaveBeenCalledWith("UpdateGameList", response.data)
});
test('Error: an error occurred', () => {
const errorMessage = 'Error';
axios.post.mockImplementationOnce(() =>
Promise.reject(new Error(errorMessage))
);
});
});

Action Creator return undefined axios

Can successfully register the user using my action creator but it returns undefined. I think it's the way how am returning my dispatch
axiosInstance
import axios from 'axios';
import AsyncStorage from '#react-native-community/async-storage';
// import base url
import {API_URL} from '../constants';
const instance = axios.create({
baseURL: API_URL,
timeout: 2000,
});
instance.interceptors.request.use(
async(config) => {
const token = await AsyncStorage.getItem('token');
if(token) {
config.headers.Autherization = `${token}`;
}
return config;
},`enter code here`
(err) => {
return Promise.reject(err);
}
)
export default instance;
SignUP Action.
import axiosInstance from '../../api/axiosInstance';
import {REGISTER_USER_SUCCESS, REGISTER_USER_FAIL} from '../actionTypes/index';
const registerSuccess = (payload) => {
return{
type: REGISTER_USER_SUCCESS,
data: payload
}
};
const registerError = (payload) => {
return {
type: REGISTER_USER_FAIL,
data: payload
}
};
export const SignUp = (registerData) => async dispatch => {
axiosInstance.post('/users/register', registerData)
.then((response)=> {
dispatch(registerSuccess(response.data));
})
.catch((error) => {
dispatch(registerError(error));
});
}
Here is how am using my action creator .. the result is undefined . I want to have a check some that I can redirect the screen to another login screen or home screen
SignUP Submit function
dispatch(registerAction.SignUp(values))
.then( (result) => {
console.log('klhadsghaj',result.status);
if(result.success) {
try {
navData.navigation.navigate("Login");
}catch (err) {
console.log(err)
}
} else {
Alert.alert('Registration failed. Try Again')
}
})
.catch(err => console.log(err))

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