how to test the fetch post request using jest - reactjs

How to mock the fetch statement using jest
export default function Login() {
function LoginUser() {
const requestOptions = {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Accept: 'application/json',
},
body: JSON.stringify({ username: username, password: password }),
};
fetch('http://localhost:8080/post', requestOptions)
.then((response) => {
if (response.status === 200) {
console.log('succesfull');
} else {
throw new Error('Invalid credentials');
}
})
.catch((err) => {
console.log(err);
});
}
<Button
block
size='lg'
type='submit'
onClick={LoginUser}
disabled={!validateForm()}
>
Login
</Button>;
}
The above code should be unit tested using mock jest on click the loginuser the function is fetch the post request.

Related

How to handle authorization headers on API call in React?

I'm trying to make a GET request to retrieve Total balance for a payment summary. I get a 401 unauthorized error on the console.
const getPay = () => {
Axios({
method: "GET",
url: `apiEndpoint/${variable}`,
headers: {
'Content-Type': 'application/json',
'x-access-token': "Available upon request"
}
})
.then((response) => {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
}
useEffect(() => {
getPay()
}, [])
The API docs states "Every request to any of the endpoints must contain the headers." The headers above were stated but I get an error 401(Unauthorized). please how do I go about this?
Just add Authorization in your headers
const getPay = () => {
Axios({
method: "GET",
url: `apiEndpoint/${variable}`,
headers: {
'Content-Type': 'application/json',
'x-access-token': "Available upon request",
Authorization: `Bearer YOUR_TOKEN`
}
})
.then((response) => {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
}
useEffect(() => {
getPay()
}, [])
Also, It is better to implement axios interceptors so that you dont have to pass headers in each call
// Request interceptor
API.interceptors.request.use(
async axiosConfig => {
const token = await getToken()
if (token && axiosConfig.headers) {
axiosConfig.headers.Authorization = `Bearer ${token}`
}
return axiosConfig
},
error => Promise.reject(error),
)

How to add user authentication with ReactJS Components

I want to implement a user authentication based on ReactJS component. I'm new to ReactJS and it's a group software project, so we don't use webhooks but components. The Authentication itself is working but not the rendering afterwards of the content.
In the app.js file I used conditional rendering, to either show the content or the login page:
if (this.getToken('token') === null || this.getToken('token') === undefined) {
shownComponent = <LoginComponent token={this.state.token} setToken={this.setToken} />;
} else {
shownComponent = <MainComponent />;
}
In the LoginComponent I implemented the following logic:
registerUser = () => {
const data = {
userName: this.state.userName,
userPassword: this.state.userPassword
}
return fetch('/users/createUser', {
method: 'post',
mode: 'cors',
headers:{
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*',
'Accept': 'application/json'
},
body: JSON.stringify(data),
})
.then((data) => {
if(data.status === 200){
console.log('User has been stored to database');
return true
}
})
.catch((error) => console.log( error.response.request) );
}
loginUser = () => {
return fetch('/login',{ headers:{
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*',
'Accept': 'application/json'
} })
.then((response) =>{
return response.json();
})
.then((data) =>{
return data;
});
}
login = async () => {
this.setState({loggedin: true})
const registered = await this.registerUser()
const userToken = await this.loginUser();
this.props.setToken(userToken)
}
after calling the login function from the login form (not copy pasted in here) it would only re-render the login page but not redirect back to the app.js and render now the main content.

Error of connecting with RASA POST webhook API into React web UI

This is a react server-side code to connect the RASA webhook API. I getting status as 0. but in the RASA framework working properly and sending answers for this request. the problem is I can't fetch the rerun answer of the API call.
import React, { Component } from 'react'
export const rasaAPI = async function RASA(name, dialogue) {
// POST request using fetch with error handling
await fetch('http://192.168.8.100:5005/webhooks/rest/webhook', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'charset':'UTF-8'
},
body: JSON.stringify({ "sender": name, "message": dialogue }),
})
.then(function(response) {
if(response.ok) {
return response.blob();
}
throw new Error(response.status);
})
.then(response => response.json())
.then(result => {
console.log('Success:', result);
})
.catch(error => {
console.error('Error:', error);
});
}
This is the console error of the API request.
Correct answer :
React app:
import React, { Component } from 'react'
export const rasaAPI = async function RASA(name, dialogue) {
// POST request using fetch with error handling
await fetch('/webhook', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'charset':'UTF-8',
},
credentials: "same-origin",
body: JSON.stringify({ "sender": name, "message": dialogue }),
}).then(response => {
return response.json();
}).then(massage => {
console.log(massage);
});
}
ADD Url into package.json file.

axios.post returns bad request of 400 React Native

I'm getting my token from an API but unfortunately my API is returning 400 bad request. I've already checked my api via Postman and it's working fine there. Kindly let me know solution or any mistake.
async componentWillMount(){
axios.post('http://api.myapiurl.com/token', {
grant_type: 'PASSWORD',
username: 'MY_USERNAME',
password: 'MY_PASSWORD'
}, {
headers: {
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
}
}).then(response => {
console.log(response.data)
}).catch(err => console.log("api Erorr: ", err.message))
}
error in response below
Request failed with status code 400
- node_modules\axios\lib\core\createError.js:16:24 in createError
- node_modules\axios\lib\core\settle.js:18:6 in settle
- ... 10 more stack frames from framework internals
It is Solved by using QueryString.stringify(). I just pass the body into QueryString.stringify() like below:
axios.post('http://api.apiurl.com/token', QueryString.stringify({
grant_type: 'MY_GRANT_TYPE',
username: 'MY_USERNAME',
password: 'MY_PASSWORD'
}), {
headers: {
"Content-Type": "application/x-www-form-urlencoded",
}
}).then(response => {
console.log(response.data)
}).catch(err => console.log("api Erorr: ", err.response))
From what I can see you are sending json data, but your Content-Type header is set to application/x-www-form-urlencoded; charset=UTF-8. if your api is expecting json then it should be application/json.
try using fetch instead, might be some axios bug, you dont need to add any libraries, here is an example:
fetch("http://api.myapiurl.com/token", {
method: "POST", // *GET, POST, PUT, DELETE, etc.
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
grant_type: "PASSWORD",
username: "MY_USERNAME",
password: "MY_PASSWORD"
})
})
.then(res => {
res.json();
})
.then(data => console.log(data)) // ur data is here
.catch(err => console.log("api Erorr: ", err));
First install the package axios from the url https://www.npmjs.com/package/react-native-axios
Then create two service for handling get and post request so that you can reuse them
GetService.js
import axios from 'axios';
let constant = {
baseurl:'https://www.sampleurl.com/'
};
let config = {
headers: {
'Content-Type': 'multipart/form-data',
'Accept': 'application/json'
}
};
export const GetService = (data,Path,jwtKey) => {
if(jwtKey != ''){
axios.defaults.headers.common['Authorization'] = 'Bearer '+jwtKey;
}
try{
return axios.get(
constant.baseUrl+'api/'+Path,
data,
config
);
}catch(error){
console.warn(error);
}
}
PostService.js
import axios from 'axios';
let constant = {
baseurl:'https://www.sampleurl.com/'
};
let config = {
headers: {
'Content-Type': 'multipart/form-data',
'Accept': 'application/json'
}
};
export const PostService = (data,Path,jwtKey) => {
if(jwtKey != ''){
axios.defaults.headers.common['Authorization'] = 'Bearer '+jwtKey;
}
try{
return axios.post(
constant.baseUrl+'api/'+Path,
data,
config
);
}catch(error){
console.warn(error);
}
}
Sample code for using get and post services is given below
import { PostService } from './PostService';
import { GetService } from './GetService';
let uploadData = new FormData();
uploadData.append('key1', this.state.value1);
uploadData.append('key2', this.state.value2);
//uploadData.append('uploads', { type: data.mime, uri: data.path, name: "samples" });
let jwtKey = ''; // Authentication key can be added here
PostService(uploadData, 'postUser.php', jwtKey).then((resp) => {
this.setState({ uploading: false });
// resp.data will contain json data from server
}).catch(err => {
// handle error here
});
GetService({}, 'getUser.php?uid='+uid, jwtKey).then((resp) => {
// resp.data will contain json data from server
}).catch(err => {
// handle error here
});
Reference from one of my another post Post action API with object parameter within the URL
If you have any doubts, feel free to know

React-Native : How to get callback of api call in another class

I am calling a web service
Here is my code:
var result;
export function callPostApi(urlStr, params)
{
fetch(urlStr, {method: "POST", headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify(params)})
.then((response) => response.json())
.then((responseData) => {
result = JSON.stringify(responseData)
})
.catch((error) => { console.error(error);
Alert.alert('Alert Title failure' + JSON.stringify(error))
})
.done();
return result
}
I am calling from here:
callapi(){
var dict = {
email: 'at#gmail.com',
password: '123456',
}
result = callPostApi('http://demo.com', dict)
}
Currently, it is calling in Async mode that we want but code is written below this method getting execute immediately after calling of above method
i want callback when result from sever has received so that i can execute code written below the above method is execute after receiving response from server.
You need to use Promises.
Change your callPostApi function to return a Promise, then you can chain additional then, catch and finally calls.
export function callPostApi(urlStr, params) {
return fetch(urlStr, {
method: "POST",
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify(params)
})
.then((response) => response.json())
.then((responseData) => {
result = JSON.stringify(responseData)
})
.catch((error) => {
console.error(error);
Alert.alert('Alert Title failure' + JSON.stringify(error))
});
}
callapi() {
callPostApi('http://demo.com', {
email: 'at#gmail.com',
password: '123456',
})
.then((response) => {
// Continue your code here...
});
}

Resources