Cypress API testing. Can not find property - automated-tests

I am developing Cypress tests for my API.
The response from my API in Postman is below:
{"infected" : false}
And my Cypress test is below:
describe("Testing the result after scanning file", () => {
it("Scan file", function () {
//Declarations
const fileName = 'example.json';
cy.fixture(fileName, 'binary')
.then((file) => Cypress.Blob.binaryStringToBlob(file))
.then((blob) => {
const formData = new FormData();
formData.append("file", blob, fileName);
cy.request({
method: 'POST',
headers: {
'content-type': 'multipart/form-data'
},
body: formData,
url: '/scan'
}).then(response => {
console.log('the response is: ', response.body)
expect(response.body).to.have.property('infected').and.eq(false);
});
})
});
});
In my browser, the Cypress test fails with the message:
assert expected {} to have property infected
I really have already broken my brain with this issue and still have no clue how to tackle it. Can anybody give me an idea what is going wrong?

Try converting the response to json, you may be seeing a string version of the data.
Postman output will not be helpful, it could be converting automatically in the background.
cy.request({
...
})
.then(response => response.json())
// OR
// .then(response => response.body.json())
.then(data => {
console.log('the data is: ', data) // better debug tool than Postman
expect(data).to.have.property('infected').and.eq(false);
});

Related

Next.js APIs working locally, but throws errors when deployed to Vercel/Netlify

The issue I'm having here is that whenever I deploy my app to either Netlify or Vercel the POST requests specifically being sent to the NextJS APIs are all throwing this error;
ERROR SyntaxError: Unexpected token ' in JSON at position 0
however, when I run the application in either development mode or by building and running locally I'm not having the same issue everything works perfectly.
This is the code I'm using to send the request;
fetch('api/route', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ ... data })
})
.then(res => res.json())
.then(data => {
data.error ? reject(new Error(data.error)) : resolve(data)
})
.catch(err => {
console.log(err)
reject(new Error('Network Error'))
})
And, this is an example of the code in the API files;
export default async function handler(req, res) {
const { method } = req
switch (method) {
case 'POST':
const { ... data } = req.body
try {
// Computation
res.status(200).json({ message: 'OK' })
} catch (error) {
console.log(error)
res.status(500)
}
break;
default:
// Invalid Method
console.log(new Error('Invalid Method: ', method))
res.status(405)
}}
I would really appreciate any assistance, I'd really like to know what the problem is.

Next js upload image fail

There is no problem upload image using postman
postman
However
let data = new FormData();
randomArray.forEach(image => {
data.append('file', image.file);
})
axios.post("http://localhost:8000/preview", data, {
headers: {
'Content-Type': 'multipart/form-data'
}
})
.then((response) => {
console.log("success");
}).catch((error) => {
//handle error
console.log("fail");
});
I this code get 500 response to me.
Here is a file list example

Cypress: custom assertion

I'm trying to write a custom assertion in Cypress. I'm testing my API routes using cy.request and found myself duplicating a lot of tests.
context('POST', () => {
it('returns a 405 with an error message', () => {
cy.request({
method: 'POST',
url: getCurrentUserRoute,
failOnStatusCode: false,
}).then(response => {
expect(response.status).to.equal(405);
const actual = response.body;
const expected = {
message: 'This endpoint only supports the GET method.',
};
expect(actual).to.deep.equal(expected);
});
});
});
Rinse and repeat for every route and their forbidden methods.
So I wanted to abstract that logic away into a custom Cypress command that acts as a custom assertion.
import { map, toLower, without } from 'ramda';
const asyncForEach = async <T>(
array: T[],
callback: (element: T, index: number, array: T[]) => void | Promise<void>,
) => {
for (let index = 0; index < array.length; index++) {
await callback(array[index], index, array);
}
};
const httpMethods = ['get', 'post', 'put', 'delete'];
Cypress.Commands.add(
'validateMethods',
(allowedMethods: string[], route: string) => {
const forbiddenMethods = without(map(toLower, allowedMethods), httpMethods);
return cy.wrap(
asyncForEach<string>(forbiddenMethods, async method => {
context(method, () => {
it('returns a 405 with an error message', () => {
return cy
.request({
method: 'POST',
url: route,
failOnStatusCode: false,
})
.then(response => {
const actual = response.status;
const expected = 405;
expect(actual).to.deep.equal(expected);
});
});
});
}),
);
},
);
The problem is, when I run this command, Cypress complains:
The following error originated from your test code, not from Cypress.
> Cannot call cy.validateMethods() outside a running test.
This usually happens when you accidentally write commands outside an it(...) test.
If that is the case, just move these commands inside an it(...) test.
Check your test file for errors.
When Cypress detects uncaught errors originating from your test code it will automatically fail the current test.
Cypress could not associate this error to any specific test.
We dynamically generated a new test to display this failure.
Check your console for the stack trace or click this message to see where it originated from.
How would I approach this? Should I don't care about abstracting this logic away? Or is there a way to create a helper function that does this for you in Cypress?
You can use cypress-each to iterate over the the routes and their forbidden methods. Each test will run regardless any previous test failures.
const routesAndForbiddenMethods = [
{ route: '/route1', forbiddenMethod: 'POST', supportedMethod: 'GET' },
{ route: '/route1', forbiddenMethod: 'PUT', supportedMethod: 'GET' },
{ route: '/route3', forbiddenMethod: 'DELETE', supportedMethod: 'POST' }
]
it.each(
routesAndForbiddenMethods,
(scenario) => `${scenario.forbiddenMethod} to ${scenario.route} returns a 405 with an error message`,
(scenario) => {
// your test code
cy.request({
method: scenario.forbiddenMethod,
url: scenario.route,
failOnStatusCode: false,
}).then(response => {
expect(response.status).to.equal(405);
const actual = response.body;
const expected = {
message: `This endpoint only supports the ${supportedMethod} method.`,
};
expect(actual).to.deep.equal(expected);
})
}
)

javascript post fetch request gone wrong

please, help me check this post request.
I've been looking at it since yesterday, I don't know what is wrong with it
maybe I need another developer's pairs of eyes.
thanks in advance
buttons.addEventListener('click', ()=>{
fetch("https://jsonplaceholder.typicode.com/comments", config)
.then(res=>{
res.json();
}).then(datae=>{
console.log(datae);
})
});
const config = {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(newName)
}
buttons.addEventListener('click', () => {
fetch('https://jsonplaceholder.typicode.com/comments', config)
.then((res) => {
return res.json()
})
.then((datae) => {
console.log(datae)
})
})
you just need to return res.json()
this should work, but remember that the function you pass to the .then function has access to the returned value from the previous .then.
fetch returns a promise that resolves into an object with the .json function
so in the first .then it will get that object and you need to return res.json() which returns a promise that will be resolved to the JSON data
so in the next .then you can use that data
I hope I was clear
note:
.then function returns a promise ( always )
also maybe you have an error in the config variable, what you pass to the JSON.stringify function should be a valid javascript object
const config = {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ name: 'rowadz' }),
}

mystery request proc_name= &params=

Trying to debug a new React-native application -- pretty large and it has no backend so I am trying to stub something out.
The request format is pretty foreign to me. Does anyone recognize this format or know how to handle it?
proc_name=customer_ref&params={"fields" : ["customerId"],"conditions":[{"mailAddress":"dsadsa"},{"pinCode":"ZHNhZHNh"},{"mailReceiveFlag":"1"}],"order" : ["customerCode desc"],"limit" : "1","table_name" : "Customer"}
React-native request code looks like this:
try{
let result = await fetch(apiUrl, {
method: 'POST',
headers: {
'X_contract_id': contact_id,
'X_access_token': access_token,
'Content-Type': 'application/x-www-form-urlencoded',
'charset':'UTF-8',
},
body: 'proc_name='+proc_name+'&params={'+params+'}'
}).then((response) => response.json())
.then((responseJson) => {
return responseJson.result;
})
return result;
}catch(e){
console.log(e);
}
The application errors out with Unhandled Promise Rejection before even making it to the server I whipped up. Pretty new here; am I doing something wrong at the frontend layer?
Try changing your fetch structure to be like this.
async functionName(){
try{
let result = await fetch(apiUrl, {
method: 'POST',
headers: {
'X_contract_id': contact_id,
'X_access_token': access_token,
'Content-Type': 'application/x-www-form-urlencoded',
'charset':'UTF-8',
},
body: 'proc_name='+proc_name+'&params={'+params+'}'
});
let resultjson = await result.json();
return resultjson.result;
}catch(e){
console.log(e);
}
}
https://facebook.github.io/react-native/docs/network.html

Resources