Testing functions calls inside callback with jest - React-native - - javascript

I'm testing the behavior of a function with a success api call, i managed to mock the fetch response, but the function inside then callback are not called, even if console.log showing the function is going inside the callback.
My test is failing here:
Here is the function im testing:
tryUserLogin() {
this.setState({loading: true});
const randomPassword = Math.random()
.toString(36)
.slice(-8);
const email = this.state.inputEmail;
const name = this.state.inputName;
const formData = new FormData();
formData.append('email', email);
formData.append('name', name);
formData.append('password', randomPassword);
const query = Util.urlForAddUser();
fetch(query, {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'multipart/form-data',
},
body: formData,
})
.then(response => response.json())
.then(responseJson => {
if (responseJson.code === 200) {
firebase.analytics().logEvent('userSuccessfulLogIn', {
userId: responseJson.response.id,
});
const userData = responseJson.response;
console.log('userData',userData) // <==== i can see this in console
this.storeUserData(userData, name);
this.setState({loading: false});
this.handleModalVisibility();
this.props.handelAddComment();
console.log('finish')
} else {
Alert.alert(
this.props.t('common:title_error'),
this.props.t('common:error'),
);
this.setState({loading: false});
}
})
.catch(error => {
firebase.crashlytics().log(
`error tryUserLogin
LoginModal===>> ${error.message}`,
);
Alert.alert(
this.props.t('common:title_error'),
this.props.t('common:error'),
);
this.setState({loading: false});
});
}
And here is the test:
it('testing tryUserLogin code 200 case', async () => {
global.FormData = require('FormData');
global.fetch = jest.fn();
const userData = {
code: 200,
response: {
id: 1,
email: 'test+1234567890#t.com',
},
};
const name = 'test';
const email = 'test#t.com';
const spyStoreUserData = jest.spyOn(instance, 'storeUserData');
const spyHandelModalVisibility = jest.spyOn(
instance,
'handleModalVisibility',
);
fetch.mockImplementation(() => {
return Promise.resolve({
status: 200,
json: () => {
return Promise.resolve({
...userData,
});
},
});
});
instance.setState({inputName: name});
instance.setState({inputEmail: email});
await instance.tryUserLogin();
expect(spyStoreUserData).toBeCalledWith(userData.response, name);
expect(fetch.mock.calls[0][0]).toBe('testQuery');
expect(instance.state.loading).toBe(false);
expect(spyHandelModalVisibility).toBeCalled();
expect(mockHandelAddComment).toBeCalled();
});

Related

How are messages sent slowly?

How are messages sent slowly? I am using socket.io for sending messages but my app sending messages is working very slowly it almost takes 8-10 seconds on average to send messages how can I improve its performance? I tried using use callback but still is not sending messages fast what can i do to improve its performance?
const { otheruser } = route.params;
const [mydata, setMyData] = useState(null);
const [userid, setUserid] = useState(null);
const [roomid, setRoomid] = useState(null);
const [chat, setChat] = useState(['']);
const [currentmessage, setCurrentmessage] = useState(null);
useEffect(() => {
LoadData()
}, [])
useEffect(() => {
socket.on('receive_message', (data) => {
LoadMessages(roomid)
})
}, [socket])
const SortRoomId = (id1, id2) => {
if (id1 > id2) {
return id1 + id2
} else {
return id2 + id1
}
}
const LoadData = async () => {
try {
const value = await AsyncStorage.getItem('user');
const { token, user: { email } } = JSON.parse(value);
const res = await fetch('http://10.0.2.2:3000/userdata', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer' + token
},
body: JSON.stringify({ email })
});
const { message, user } = await res.json();
if (message === 'User Found') {
setMyData(user);
setUserid(user._id);
const ChatRoomId = await SortRoomId(otheruser[0]._id, user._id);
setRoomid(ChatRoomId);
socket.emit('joinroom', { roomid: ChatRoomId });
LoadMessages(ChatRoomId);
} else {
alert('Login Again');
navigation.navigate('Login');
}
} catch (err) {
navigation.navigate('Login');
}
};
const SendMessage = useCallback(async () => {
const MessageData = {
message: currentmessage,
RoomId: roomid,
SenderId: userid,
RecieverId: otheruser[0]._id
};
try {
const response = await fetch('http://10.0.2.2:3000/SaveMessage', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(MessageData)
});
const data = await response.json();
if (data.message === 'Message saved') {
socket.emit('sendmessage', MessageData);
LoadMessages(roomid);
console.log('message sent');
setCurrentmessage('');
} else {
alert('Network Error');
setCurrentmessage('');
}
} catch (error) {
console.error(error);
}
}, [currentmessage, roomid, userid, otheruser, socket]);
useEffect(() => {
LoadMessages(roomid)
}, [chat])
const LoadMessages = async (ChatRoomId) => {
try {
const res = await fetch('http://10.0.2.2:3000/GetMessages', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ RoomId: ChatRoomId })
});
const data = await res.json();
setChat(data);
} catch (error) {
console.error(error);
}
}

Internal Server Error: No suitable HttpMessageConverter found for response type

status: 500, error: "Internal Server Error"
message: Could not extract response: no suitable HttpMessageConverter found for response type [class com.clone.instagram.authservice.fetchdata.model.Example] and content type [text/html;charset=utf-8]"
So strangely this error has started showing up while accessing insta API,
What's strange is this happens "only sometimes",
And never happened before.
It works some times, some times it pops this error
const request = (options) => {
const headers = new Headers();
headers.append("Content-Type", "application/json");
if (localStorage.getItem("accessToken")) {
headers.append(
"Authorization",
"Bearer " + localStorage.getItem("accessToken")
);
}
const defaults = { headers: headers };
options = Object.assign({}, defaults, options);
return fetch(options.url, options).then((response) =>
response.json().then((json) => {
if (!response.ok) {
return Promise.reject(json);
}
return json;
})
);
};
export function registerInstaUserInfo(instaUserINfoRequest){
if (!localStorage.getItem("accessToken")) {
return Promise.reject("No access token set.");
}
console.log("inside getInstaUserInfo request ");
return request({
url: properties.INSTA_USER_REGISTER ,
method: "POST",
body: JSON.stringify(instaUserINfoRequest),
});
}
const getInstaUserInfoFromService = (response) => {
//store respose.data
if (response.data.user_id) {
console.log("setting up insta user staate ", response.data);
localStorage.setItem("insta_user", response.data);
cookies.set("insta_user", response.data, { path: "/" });
console.log("cookies ", cookies.get("insta_user"));
const fb_access_token = localStorage.getItem("accessToken");
console.log("fb_access_token", fb_access_token);
const user_info = registerInstaUserInfo(response.data)
.then((res) => {
console.log(res);
setLinkedInstaAccounts([...linkedAccounts, res]);
})
.catch((err) => console.error("Hello stackoverlflowpeople this is where error happens", err));
console.log("user_info", user_info);
props.history.push("/home");
//redirecting to account.js
// props.history.push("/me");
}
};
const successResponse = (code) => {
console.log("inside success func");
console.log(code);
var bodyFormData = new FormData();
bodyFormData.append("redirect_uri", properties.INSTA_REDIRECT_URL);
bodyFormData.append("code", code);
bodyFormData.append("client_id", properties.INSTA_CLIENT_ID);
bodyFormData.append("client_secret", properties.INSTA_CLIENT_SECRECT);
bodyFormData.append("grant_type", "authorization_code");
axios({
method: "post",
url: properties.INSTA_ACCESS_TOKEN_URL,
data: bodyFormData,
headers: {
"Content-Type": "multipart/form-data",
Accept: "application/vnd.api+json",
},
})
.then(getInstaUserInfoFromService)
.catch(function (response) {
//handle error
console.log(response);
});
};
----
//component
<InstagramLogin
clientId={properties.INSTA_CLIENT_ID}
buttonText="Login"
redirectUri={properties.INSTA_REDIRECT_URL}
scope="user_profile,user_media"
onSuccess={successResponse}
onFailure={failedresponseInstagram}
/>
=====================THIS getInstaUserFromService is where error happens
const getInstaUserInfoFromService = (response) => {
//store respose.data
if (response.data.user_id) {
console.log("setting up insta user staate ", response.data);
localStorage.setItem("insta_user", response.data);
cookies.set("insta_user", response.data, { path: "/" });
console.log("cookies ", cookies.get("insta_user"));
const fb_access_token = localStorage.getItem("accessToken");
console.log("fb_access_token", fb_access_token);
const user_info = registerInstaUserInfo(response.data)
.then((res) => {
console.log(res);
setLinkedInstaAccounts([...linkedAccounts, res]);
})
.catch((err) => console.error("Hello stackoverlflowpeople this is where error happens", err));
console.log("user_info", user_info);
props.history.push("/home");
//redirecting to account.js
// props.history.push("/me");
}
};
I was using this but I have not touched headers or anything, is it something with Instagram server?

Pass query parameters to Snipcart API url inside a Netlify function

I’m trying to get JSON product data from Snipcart by querying my Netlify function as below:
const fetch = require("isomorphic-fetch");
const {SNIPCART_PRIVATE_KEY} = process.env;
const API_ENDPOINT = "https://app.snipcart.com/api/products";
const {snipcartID} = event.queryStringParameters;
const callAPI = async (event, context) => {
const auth =
'Basic ' +
Buffer.from(SNIPCART_PRIVATE_KEY + ':' + '').toString('base64');
const t = await fetch(API_ENDPOINT + "?userDefinedId=" + ${snipcartID || 'ABC'}, {
headers: {
Authorization: auth,
Accept: "application/json",
},
})
.then((response) => response.json())
.then(data => {
var results;
if (data) {
const {items} = data;
if (items) {
return {
name: items[0].name,
sales: items[0].statistics.numberOfSales,
};
}
}
return results;
})
.catch((error) => ({ statusCode: 422, body: String(error) }));
return {
statusCode: 200,
headers: {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Headers':
'Origin, X-Requested-With, Content-Type, Accept',
},
body: JSON.stringify(t),
};
};
exports.handler = callAPI;
I get the correct JSON data when I hard-code SNIPCART_ID in the function above. But I can’t pass my Snipcart id as a parameter using my page’s JavaScript as follows:
<script>
document.addEventListener("click", function (event) {
if (!event.target.matches("#collapsible")) return;
let URL = "/.netlify/functions/snipcart-getsales";
fetch(URL, "ABC")
.then((response) => response.json())
.then((data) => renderSales(data))
.catch(() => renderError());
});
function renderSales(data) {
const name = document.getElementById("name");
const sales = document.getElementById("sales");
const error = document.getElementById("error");
error.innerHTML = "";
name.innerHTML = data.name;
sales.innerHTML = data.sales;
}
function renderError() {
const error = document.getElementById("error");
error.innerHTML = "Whoops, something went wrong. Please try again later!";
}
</script>
What am I doing wrong here?
Can you console.log(event) before sending the request, to check if your function got the correct SNIPCART_ID that is send to the request.
I figured it out after some fiddling around :)
const fetch = require("isomorphic-fetch");
const {SNIPCART_PRIVATE_KEY} = process.env;
const API_ENDPOINT = "https://app.snipcart.com/api/products";
const callAPI = async (event, context) => {
const auth =
'Basic ' +
Buffer.from(SNIPCART_PRIVATE_KEY + ':' + '').toString('base64');
const querystring = event.queryStringParameters;
const userDefinedId = querystring.userDefinedId || 'ABC';
const t = await fetch(API_ENDPOINT + "?userDefinedId=" + userDefinedId, {
headers: {
Authorization: auth,
Accept: "application/json",
},
})
.then((response) => response.json())
.then(data => {
var results;
if (data) {
const {items} = data;
if (items) {
return {
name: items[0].name,
sales: items[0].statistics.numberOfSales,
};
}
}
return results;
})
.catch((error) => ({ statusCode: 422, body: String(error) }));
return {
statusCode: 200,
headers: {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Headers':
'Origin, X-Requested-With, Content-Type, Accept',
},
body: JSON.stringify(t),
};
};
exports.handler = callAPI;

My first api request always fails after page load

I'm having a problem with my API request that always fails after page load. Don't really know where Im wrong.
Here's my request and I call it when I interact with handleOpen function.
const stock = {
method: 'GET',
url: 'https://morningstar1.p.rapidapi.com/live-stocks/GetRawRealtimeFigures',
params: {Mic: props.mic, Ticker: clickedElement.ticker},
headers: {
'x-rapidapi-key': 'XXX',
'x-rapidapi-host': 'morningstar1.p.rapidapi.com'
}
}
const getStock = async () => {
try {
const res = await axios.request(stock);
return res.data;
}
catch (error) {
setOpen(false);
console.error("catch api error: ", error);
}
}
const handleOpen = name => {
let findClickedStock = props.stocksArray.find(item => item.ticker === name)
setClickedElement(findClickedStock)
getStock().then((dataFromStockApi) => {
let combined1 = { ...dataFromStockApi, ...findClickedStock }
setStockObject(combined1);
});
setOpen(true);
};
ERROR:
It's because your Ticker parameter is empty.
When you create "stock", clickedElement.ticker is undefined.
Do this:
// pass name in as a parameter
getStock(name).then(...)
Make getStock like like this:
const getStock = async (ticker) => {
try {
const res = await axios.request({
method: 'GET',
url: 'https://morningstar1.p.rapidapi.com/live-stocks/GetRawRealtimeFigures',
params: {Mic: props.mic, Ticker: ticker},
headers: {
'x-rapidapi-key': 'XXX',
'x-rapidapi-host': 'morningstar1.p.rapidapi.com'
}
});
return res.data;
}
catch (error) {
setOpen(false);
console.error("catch api error: ", error);
}
}

What happens when Axios makes a post request?

I'm building an App using reactjs and I'm questioning axios.
I have an axios.post
and following that I call a function
this.props.onChangeStep1()
with the way it is written...am I safe ?
Will this.props.onChangeStep1() always wait for res.data to be full ?
onChangeHandler = event => {
console.log(event.target.files[0]);
this.setState(
{
selectedFile: event.target.files[0],
fileName: event.target.files[0].name,
loaded: 0
},
() => {
console.log(this.state.selectedFile);
console.log(this.state.loaded);
const formData = new FormData();
formData.append("file", this.state.selectedFile);
axios
.post(`/upload`, formData, {
headers: {
"Content-Type": "multipart/form-data"
}
})
.then(res => {
console.log(res);
console.log(res.data);
});
this.props.onChangeStep1(); //<---- Will this wait for res.data ?
}
);
No. It won't wait. You should put it into .then:
onChangeHandler = event => {
console.log(event.target.files[0]);
this.setState(
{
selectedFile: event.target.files[0],
fileName: event.target.files[0].name,
loaded: 0
},
() => {
console.log(this.state.selectedFile);
console.log(this.state.loaded);
const formData = new FormData();
formData.append("file", this.state.selectedFile);
axios
.post(`/upload`, formData, {
headers: {
"Content-Type": "multipart/form-data"
}
})
.then(res => {
console.log(res);
console.log(res.data);
this.props.onChangeStep1();
});
}
In your example onChangeStep will be executed before the result from axios.
You can call this.props.onChangeStep1() inside .then() block:
axios
.post(`/upload`, formData, {
headers: {
"Content-Type": "multipart/form-data"
}
})
.then(res => {
console.log(res);
console.log(res.data);
this.props.onChangeStep1();
});
Or you can use async/await
postData = async () => {
const formData = new FormData();
formData.append("file", this.state.selectedFile);
try {
const result = await axios.post(`/upload`, formData, /* all your headers..*/)
this.props.onChangeStep1(); // this line will be executed after post request
} catch(error){
// do something with error.
}
}
}
onChangeHandler = event => {
this.setState(
{
selectedFile: event.target.files[0],
fileName: event.target.files[0].name,
loaded: 0
},
this.postData)
}

Categories

Resources