Testing API with axios - getting triggerUncaughtException(err, true /* fromPromise */); - api

function signup(data_var) {
const options = {
method: 'POST',
url: 'xxx',
headers: {
'Content-Type': 'application/json',
Authorization: 'Bearer undefined',
},
data: data_var,
};
return axios
.request(options)
.then(function (response) {
return response;
})
.catch(function (error) {
return error;
});
}
it('should return 200 status code', async () => {
var random = Math.floor(Math.random() * 1000000);
var email = 'shadow' + random + '#gmail.com';
signup({
firstName: 'test',
lastName: 'testing',
email: email,
})
.then(function (response) {
expect(response.status)
.toBe(200);
});
});
It will create a new user but when I check status code 200 it throws this error
Error Message
>
node:internal/process/promises:245
triggerUncaughtException(err, true /* fromPromise */);
Expected: 200
Received: undefined".] {
code: 'ERR_UNHANDLED_REJECTION'
}

Related

How to catch the error code 422 in async await and display an error message to the user

I want to render an error message when the user clicks on the plan button he is currently subscribed to.
Somehow I am not able to catch the error code 422 and massage the error response in such a way that when the user clicks the same button, a call is made to the API and the API throws the message "You are already subscribed to the plan.
How can I catch the error code 422 and display the error message? Here is the code:
const [updating, setUpdating] = useState(false);
const [change, setChange] = useState(null);
const changeSubscription = async (change) => {
setChange(change);
setUpdating(true);
try {
const update = await fetch('/subscription', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
token: 'token',
},
body: JSON.stringify({
stripe_subscription_id: user.subscription.items[0].id,
product_id: tier.id,
proration_date: Math.floor(Date.now() / 1000),
}),
});
await update.json();
} catch (error) {
console.error(error);
}
};
You could just use an errMsg state to store the string representing the error and display it when not empty:
const [updating, setUpdating] = useState(false);
const [change, setChange] = useState(null);
const [errMgs, setErrMsg] = useState('');
const changeSubscription = async (change) => {
setChange(change);
setUpdating(true);
setErrMsg(''); // Reset error
try {
const update = await fetch('/subscription', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
token: 'token',
},
body: JSON.stringify({
stripe_subscription_id: user.subscription.items[0].id,
product_id: tier.id,
proration_date: Math.floor(Date.now() / 1000),
}),
});
await update.json();
} catch (error) {
// Handle error
if (error.response.status === 422) {
setErrMsg('You are already subscribed to the plan')
} else setErrMsg('Generic error')
}
};
return (
// Display error message if present
{errMsg !== '' && <>{errMsg}</>}
// Rest of JSX
...
)

React Native - FETCH Response is empty - API Status 500 - POST Call

signIn = () => {
//post data to express backend
fetch('http://10.0.2.2:3000/api/v1/auth', {
method: 'POST',
header: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: `login=${this.state.login}&password=${this.state.password}`
})
.then((response) => response.json())
.then ((res => {
if(res.status === 200) {
AsyncStorage.setItem('user', this.state.login);
this.props.navigation.navigate('Authorized')
} else {
alert("Response:", res);
}
}))
.done();
}
The above is for React-Native. And below is the express backend:
router.post('/', function(req,res){
var login= req.body.login;
var password = req.body.password;
var sql = `SELECT * FROM users WHERE username = '${login}' OR number = '${login}' AND password = ${password}`
db.query(sql, function (err, rows, fields) {
if (err) {
res.status(500).send({error: 'Something went wrong!'})
} else {
if(rows.length > 0) {
if (rows[0].password == password) {
res.status(200).send({success: 'Login Successful'})
}
} else {
res.status(404).send({error: 'Email or Password does not match!'})
}
}
})
});
I think there is nothing getting into a response or maybe some other problem which I am unable to figure out the moment.

How to send file(docx, pdf) to server in the body of fetch with other attributes React-native?

I must send the description of person with it`s Resume to server I have API but when i google this problem there was just sources with fetch of files but I have to send file with name... So I see library document-picker but cant imagine how to concantenate this fetch.
There props
constructor(props){
super(props)
this.state={
token: {
accessToken:""
},
nameCan: '',
surename: '',
experience: '',
city: '',
phone: '',
email: '',
file: {},
}
}
There code of button to Download
_pickDoc = async() => {
let result = await DocumentPicker.getDocumentAsync({});
alert(result.uri);
this.setState(this.state.file = result);
console.log(result);
}
There code of Fetch
async createCV(){
let url = this.state.file.uri; //The url you received from the DocumentPicker
const split = url.split('/');
const name = split.pop();
const inbox = split.pop();
const realPath = `${RNFS.TemporaryDirectoryPath}${inbox}/${name}`;
const uploadBegin = (response) => {
const jobId = response.jobId;
console.log('UPLOAD HAS BEGUN! JobId: ' + jobId);
};
const uploadProgress = (response) => {
const percentage = Math.floor((response.totalBytesSent/response.totalBytesExpectedToSend) * 100);
console.log('UPLOAD IS ' + percentage + '% DONE!');
};
RNFS.uploadFiles({
toUrl: 'myurl',
files: [{
name,
filename:name,
filepath: realPath,
}],
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
Authorization: 'Bearer ' + this.state.token.accessToken,
},
body: JSON.stringify({
name: this.state.nameCan + ' ' + this.state.surename,
location: this.state.city,
experience: this.state.experience,
email: this.state.email,
phone: this.state.phone,
file: realPath
}),
begin: uploadBegin,
beginCallback: uploadBegin,
progressCallback: uploadProgress,
progress: uploadProgress
}).then((response) => {
console.log(response,"<<< Response");
}).catch((err) => {
if (err.description) {
switch (err.description) {
case "cancelled":
console.log("Upload cancelled");
break;
case "empty":
console.log("Empty file");
default:
//Unknown
}
} else {
//Weird
}
console.log(err);
});
}

Best way to handle CRUD testing?

I want to write a test for my CRUD endpoints. But I want to test 'UPDATE', 'DELETE' endpoints rely on created document in 'CREATE' endpoint.
For example:
let createdAccount = null;
it("should create an account", async () => {
const response = await Server.inject({
method: "POST",
url: "/v1/accounts",
payload: JSON.stringify({
name: "TEST",
email: "test#test.com"
})
});
expect(response.statusCode).to.equal(200);
expect(response.result).to.a.object();
expect(response.result._id).to.exists();
createdAccount = response.result;
});
it("should delete an account", async () => {
const deleteResponse = await Server.inject({
method: "DELETE",
url: `/v1/accounts/${createdAccount._id}`
});
expect(deleteResponse.statusCode).to.equal(200);
expect(deleteResponse.result).to.a.object();
expect(deleteResponse.result._id).to.exists();
});
What's the best way to handle this? Should I create a test case which is rely on another one's result?
Note: I'm using hapijs, hapi/lab, hapi/code for testing.
Your use case is perfectly OK. We also use similar approaches in our test cases.
Here is a piece of test code from a real-world application.
describe('Validate campaign routes', () => {
let server, token, cookie, campaignId;
before(async () => {
server = await Glue.compose(serverConfig.manifest, options);
// custom my api related stuff, such as JTW token generation user creation etc.
});
after(async () => {
await mongoose.connection.db.dropDatabase();
await server.stop();
await helpers.delay(100);
});
it("should create a campaign", async () => {
const res = await server.inject({
url: '/campaign',
method: 'post',
payload: {
name: "Sample Campaign",
active: true
},
headers: {
"Authorization": token,
}
});
expect(res.statusCode).to.equal(200);
expect(res.result.created).to.exist();
expect(res.result.created.name).to.equal("Sample Campaign");
expect(res.result.status).to.equal(true);
campaignId = res.result.created.id;
});
it("should fetch all campaigns", async () => {
const res = await server.inject({
url: '/campaign?page=1',
method: 'get',
headers: {
"Authorization": token,
}
});
expect(res.statusCode).to.equal(200);
expect(res.result.status).to.equal(true);
expect(res.result.results).to.be.an.array();
expect(res.result.results).to.have.length(1);
expect(res.result.results[0].name).to.equal('Sample Campaign');
});
it("should fetch campaign details", async () => {
// fetch campaign details
const res2 = await server.inject({
url: `/campaign/${campaignId}`,
method: 'get',
headers: {
"Authorization": token,
}
});
expect(res2.statusCode).to.equal(200);
expect(res2.result).to.be.an.object();
expect(res2.result.name).to.equal('Sample Campaign');
});
it("should update campaign", async () => {
const res = await server.inject({
url: `/campaign/${campaignId}`,
method: 'put',
payload: {
name: "Updated Campaign Title",
maxImpression: 1000,
endDate: "01-04-2019"
},
headers: {
"Authorization": token,
}
});
expect(res.statusCode).to.equal(200);
expect(res.result).to.be.an.object();
expect(res.result.updated.name).to.equal('Updated Campaign Title');
expect(res.result.updated.maxImpression).to.equal(1000);
});
it("should delete campaign", async () => {
const res = await server.inject({
url: `/campaign/${campaignId}`,
method: 'delete',
headers: {
"Authorization": token,
}
});
expect(res.statusCode).to.equal(200);
expect(res.result.deleted).to.equal(campaignId);
const res2 = await server.inject({
url: '/campaign',
method: 'get',
headers: {
"Authorization": token,
}
});
expect(res2.statusCode).to.equal(200);
expect(res2.result.status).to.equal(true);
expect(res2.result.results).to.be.an.array();
expect(res2.result.results).to.have.length(0);
});
});

WordPress REST API returns 401 Unauthorized when posting via Axios & valid JWT

I am attempting to post data from a form to the WordPress REST API via my Vue/Nuxt application using Axios and JWT.
I am able to obtain a valid token and save it as a cookie, but when I attempt to post the data to the API, I get a 401 Unauthorised error with the message "rest_cannot_create" - Sorry you are not allowed to post as this user.
The user in question is the one authorised by JWT. I have tried it with them as both an Author (create and edit their own posts) and Editor (can create, edit and delete their own posts), but both have the same result.
My code is below:
submitForm: function() {
let formData = {
type: 'kic_enquiries',
title: {
rendered: 'Enquiry from ' + this.firstname + ' ' + this.lastname + ' [' + new Date() + ']'
},
acf: {
enquiry_name: this.firstname + ' ' + this.lastname,
enquiry_email: this.emailaddress,
enquiry_phone: this.phonenumber,
enquiry_message: this.message
}
};
this.formSubmission.push(formData);
const bodyFormData = new FormData();
bodyFormData.set('username', 'username');
bodyFormData.set('password', 'password');
axios ({
method: 'post',
url: url + '/wp-json/jwt-auth/v1/token',
data: bodyFormData,
config: {
headers: { 'Content-Type': 'multipart/form-data' }
}
})
.then(res => {
this.$cookies.set("cookiename", res.data.token, "3MIN");
}).catch(function(error) {
console.error( 'Error', error );
}).finally(() => {
console.log('Posting form...');
axios ({
method: 'post',
url: url + '/wp-json/wp/v2/kic-enquiries',
data: JSON.stringify(this.formSubmission),
config: {
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
'Authorization:': 'Bearer ' + this.$cookies.get("cookiename")
}
}
})
.then(submitResponse => {
console.log('Form submitted...' + submitResponse)
return submitResponse;
}).catch(function(error) {
console.error( 'Error', error );
});
});
Do I need to use Interceptors? I've seen a lot about them online but I can't find anything that explains how I need to use them for my situation.
UPDATE
Further investigation shows the token works when sent with the same settings and data as the app via Postman, so it seems to be a code issue.
Is the post failing because I'm sending the token wrongly?
UPDATE 2 - 15 Feb 2019
I've modified my code to use await/async and a watcher to check for the token to be generated, but I'm still getting the 401 error. Updated code is below:
<script>
import axios from 'axios'
export default {
data: function() {
return {
firstname: null,
lastname: null,
emailaddress: null,
phonenumber: null,
message: null,
formSubmission: [],
res: [],
authStatus: false,
token: null
}
},
methods: {
submitForm: async function() {
let formData = {
type: 'kic_enquiries',
title: {
rendered: 'Enquiry from ' + this.firstname + ' ' + this.lastname + ' [' + new Date() + ']'
},
acf: {
enquiry_name: this.firstname + ' ' + this.lastname,
enquiry_email: this.emailaddress,
enquiry_phone: this.phonenumber,
enquiry_message: this.message
},
status: 'draft'
};
this.formSubmission.push(formData);
console.log(JSON.stringify(this.formSubmission));
await this.getToken();
},
getToken: function() {
console.info('Getting token...');
const bodyFormData = new FormData();
bodyFormData.set('username', 'user');
bodyFormData.set('password', 'pass');
axios ({
method: 'post',
url: link,
data: bodyFormData,
config: {
withCredentials: true,
headers: { 'Content-Type': 'multipart/form-data' },
}
})
.then(res => {
this.$cookies.set("XSRF-TOKEN", res.data.token, "30MIN");
console.log('Cookie:' + this.$cookies.get("XSRF-TOKEN"));
}).catch(function(error) {
console.error( 'Error', error );
}).finally(() => {
this.authStatus = true;
this.token = this.$cookies.get("XSRF-TOKEN");
});
}
},
watch: {
authStatus: function() {
if (this.authStatus == true) {
console.info('Posting form...');
axios ({
method: 'post',
url: 'link,
data: this.formSubmission,
config: {
withCredentials: true,
headers: {
'Authorization:': 'Bearer ' + this.token
}
}
})
.then(submitResponse => {
console.log('Form submitted...' + submitResponse)
return submitResponse;
}).catch(function(error) {
console.error( 'Error', error );
});
}
else {
console.error('Token not generated')
}
}
}
}
</script>
So now, the form submission has to wait for the token to be generated and applied before it attempts to make the request to the API.
In the error documents I've noticed withCredentials is being set to false even though it's set to true in the config. Why would that be?
Try this
let headers = {
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + 'Authorization:': 'Bearer ' + this.token
}
this.axios.post('link', JSON.stringify(this.formSubmission), {headers: headers})
Follow this link