Catch a request after POST - cypress

I have a component in which a user can add a number of hours worked and post that to the server. For testing I want to remove the added hours so I can run the test again (the user cannot add hours on a day that already has hours).
There's a response on the request which has the id of the added hours. I can use a end point with that id to remove them. So the question is how do I gain access to the response of a request in Cypress?

it('Removed saved hours', () => {
cy.intercept('GET', 'api/v0/work-hours/?filter[job_id]=21173&filter[week_id]=202133').as('savedHours')
cy.get('[data-cy=jobs]').children('div').first().click()
cy.wait('#savedHours').then((res) => {
cy.request({
method: 'DELETE',
url: 'https://***/api/v0/work-hours',
headers: {
Authorization: res.request.headers.authorization,
'Content-Type': 'application/vnd.api+json',
Accept: 'application/vnd.api+json'
},
body: {
data: {
data: {
attributes: { ust_id: res.response.body.data[0].id },
type: 'work_hours'
}
}
}
})
})
})
Got it working. What's important is that you first initiatie the interceptor, then do the call and then you can handle the data.

Related

after hook doesn't work for the first time in cypress

after hook doesnt work for the first time in cypress but when i retry, it works. in the after hook i call a cy.request and i get a token from another request . i run the token request in before all the tests to make sure i got the token here is the code in the main tests
describe('test', () => {
before(() => {
Login.userLg();
});
it('first test', () => {
cy.visit('`url`);
// some code to test
});
// delete user
afterEach(() => {
user.delete();
});
});
here is the code of the user function in another file (tokenFile)
delete() {
failOnStatusCode: false
cy.request({
method: 'PATCH',
url: `url`,
headers: {
Authorization: 'Bearer ' + Cypress.env('token'),
},
body: {
name: user,
},
});
}
here is the code to get the token in a third file
describe('token', () => {
it('get operator token', () => {
cy.request({
method: 'POST',
url: 'url',
form: true,
body: {
grant_type: 'password',
username: 'user',
password: 'pass',
},
}).then((response) => {
Cypress.env('token', response.body.token);
});
});
});
i call the token request in support/e2e.ts
import './tokenFile';
i tried to put the fucntion in after hook ,put in before hook before login , also i tried afterEach and it didn'T work , i tried to put the token request in command file . nothing works
You should really clear state before tests run rather than after. This is in the official Cypress docs:
https://docs.cypress.io/guides/references/best-practices#Using-after-or-afterEach-hooks
One other benefit of doing this is that if you have a test failure you preserve all the data that the test failed with meaning you can debug the issue.

cypress intercept stub and retrieve response

Hello so am relatively new to using intercept on cypress.
Clicking a button sends a request. Intercepting and not stubbing (//1) lets me retrieve the date value in the response seen in cy.log($resp.response), but I need to stub a response too (//2) this fails to return a date value in the cy.log($resp.response). The data value is generated as it is seen in the UI
How can I retrieve the response and still stub?
cy.intercept({method: 'POST', url: '**/myURL'}).as('successfulAction') //1
cy.intercept({method: 'POST', url: '**/myURL'},{stubbed data}).as('successfulAction') //2
cy.get('button').click()
cy.wait('#successfulAction').then(($resp) => {
cy.log($resp.response)
})
On the first intercept, add the middleware flag.
This allows the true request to be caught, but pass the request on to the 2nd intercept which applies stubbed data.
cy.intercept({
method: 'POST',
url: '**/myURL',
middleware: true
}).as('successfulAction')
cy.intercept({method: 'POST', url: '**/myURL'}, {stubbed data}) // no alias needed
cy.wait('#successfulAction')
.then(($resp) => {
cy.log($resp.response)
})
You can also use a single intercept
cy.intercept({
method: 'POST',
url: '**/myURL',
middleware: true
}).(req => {
req.continue(resp => {
cy.log($resp.response)
res = stubbedData
})
})
.as('successfulAction')
Thanks for the answers I definitely gave me an idea and the below works.
cy.intercept({
method: 'POST',
url: `**/${parentAlarmsAssetsData[0].AssetNumber}`,
middleware: true
},(req) => {
req.continue((res) => {
res.send({ //add stubbed data
statusCode: 200,
body: {
"status":true,
"responseMessage":null
}
})
})
}).as('successfulAction')
cy.get(manualCheckButton).click()
cy.wait('#successfulAction').then(($resp) => {
acknowledgedDateTime = $resp.response.headers.date //set global var
})

Can I log to file all the responses made during running cypress test?

When I'm running cypress e2e tests, application makes XHR requests. How can I log all this requests and responses? I don't want to stub these requests. I with to get an artifact with all requests and responses made during test. Gitlab is used as CI.
Main test code looks like this. All these are user defined commands, interacting with the application. Interacting with the application causes different requests to be made (e.g. I click a button, this causes the request).
it('Log response to a file',function(){
cy.request({
method: 'GET',
url: 'https://<site>/home/payments/currency/confirm/*',
headers: {
'Content-Type': 'application/json',
},
body: {},
}).then((response)=>{
const someResponse = response.body;
console.log("hhhh"+someResponse);
cy.writeFile('cypress/fixtures/testResponse.json', someResponse);
cy.login(login_name, pass)
cy.typeOTPpinpad(secret)
cy.makePayment('Currency', 'amount')
cy.typeToken(secret)
cy.logout()
})
})
Here is how I tried to use regular expression to catch request (id is unique and I need to use regular expressions).
https://<mysite>/home/payments/<currency>/confirm/* - asterisk is payment id.
You could grab the request and response and write to a location as below. I have write the request and response to fixture folder as below: Try the below and let me know
it('Log request to a file',function(){
cy.request({
method: 'GET',
url: 'url_here',
headers: {
'Content-Type': 'application/json',
},
body: {},
}).then((request)=>{
const someRequest = JSON.stringify(request);
console.log("hhhh"+someRequest);
cy.writeFile('cypress/fixtures/testRequest.json', someRequest);
})
})
// The below is for response:
it('Log response to a file',function(){
cy.request({
method: 'GET',
url: 'url_here',
headers: {
'Content-Type': 'application/json',
},
body: {},
}).then((response)=>{
const someResponse = response.body;
console.log("hhhh"+someResponse);
cy.writeFile('cypress/fixtures/testResponse.json', someResponse);
})
})
The testrunner has such information on board:
[

Get a 401 error with POST and PUT Laravel passport/Vue/Axios

I am working on a Vue application with a seperate Laravel back-end API. The back-end has Laravel passport that requires an access token when doing database calls.
Normally everything goes right, I can get data back from the database but for some reason, 2 of my calls gets errors, the POST en PUT. I don't know why I get unauthenticated (401) from laravel passport back, while my get request is going well. Also, both POST and PUT are going fine in the postman application.
The get request
getSuppliers() {
axios.get(`${this.$API_URL}/api/v1/relations`, {
headers: this.headers,
})
.then((response) => {
this.loaded = true;
this.relations = response.data.data;
})
.catch(error => console.log(error));
},
The post request
axios.post(`${this.$API_URL}/api/v1/relations`, {
headers: this.headers,
data: {
company_name: this.supplier.company_name,
language_id: this.supplier.language_id,
supplier_type_id: this.supplier.supplier_type_id,
email: this.supplier.email,
website: this.supplier.website,
recognition_number: this.supplier.recognition_number,
street: this.supplier.street,
house_number: this.supplier.house_number,
zipcode: this.supplier.zipcode,
city: this.supplier.city,
country: this.supplier.country,
},
})
.then((response) => {
console.log(response);
// retrieve the id
// push the user to the show of the retrieved id
})
.catch(error => console.log(error));
Helper functions for access token
function getHeaders(token) {
return {
Accept: 'application/json',
Authorization: `Bearer ${token}`,
};
}
function getToken() {
const oauth = JSON.parse(localStorage.getItem('oauth') || '{}');
if (oauth.access_token) {
return oauth.access_token;
}
return false;
}
Somebody out there that had the same problem or similair?
After some digging, going through my other code and requests I find a solution that fixed it for me.
Instead of
axios.post(`${this.$API_URL}/api/v1/relations`, {
headers: this.headers,
data: {
company_name: this.supplier.company_name,
language_id: this.supplier.language_id,
supplier_type_id: this.supplier.supplier_type_id,
email: this.supplier.email,
website: this.supplier.website,
recognition_number: this.supplier.recognition_number,
street: this.supplier.street,
house_number: this.supplier.house_number,
zipcode: this.supplier.zipcode,
city: this.supplier.city,
country: this.supplier.country,
},
})
.then((response) => {
console.log(response);
// retrieve the id
// push the user to the show of the retrieved id
})
.catch(error => console.log(error));
I had to do
axios({
method: 'post',
url: `${this.$API_URL}/api/v1/relations`
headers: this.headers,
data: {
company_name: this.supplier.company_name,
language_id: this.supplier.language_id,
supplier_type_id: this.supplier.supplier_type_id,
email: this.supplier.email,
website: this.supplier.website,
recognition_number: this.supplier.recognition_number,
street: this.supplier.street,
house_number: this.supplier.house_number,
zipcode: this.supplier.zipcode,
city: this.supplier.city,
country: this.supplier.country,
},
})
.then((response) => {
console.log(response);
// retrieve the id
// push the user to the show of the retrieved id
})
.catch(error => console.log(error));
I don't see any difference except the style, so I don't know exactly why the second style is working and the first one is not, especially for the put and post type of requests.

Trigger.io Ajax Requests - with Parse Facebook User authentication

I'm trying to authenticate users from Trigger.io, ideally via Facebook.
I authenticate the user via Facebook (using the Parse Facebook module), and pass their access token, acess expiry date, and facebook Id to my call to Parse.
It is here things go wrong. Whenever I try and post this data via Ajax to the Parse REST API, I get an error in my forge/Trigger console reading:
{ type: 'EXPECTED_FAILURE', content: '{"code":107,"error":"This
endpoint only supports Content-Type: application/json requests, not
application/x-www-form-urlencoded."}', statusCode: '400', message:
'HTTP error code received from server: 400' }
The code I used to try and post this data is...
function auth(facebookId,accessToken,expirationDate) {
forge.logging.log('auth started');
forge.request.ajax({
url: 'https://api.parse.com/1/users',
headers: {
'X-Parse-Application-Id': config.parseAppId,
'X-Parse-REST-API-Key': config.parseRestKey,
'Content-Type': 'application/json'
},
type: 'POST',
dataType: 'json',
data: {
"authData": {
"facebook": {
"id" : facebookId,
"access_token": accessToken,
"expiration_date": expirationDate
}
}
},
success: function (data) {
forge.logging.log('auth finished 1');
forge.logging.log(data);
},
error: function(error){
forge.logging.log('auth finished 2');
forge.logging.log(error);
}
})//success
} //auth
I can't figure out how to send this as a JSON object/ in the correct format. If anyone has any ideas they'd be much appreciated. Thanks. Josh.
Whenever the data option passed to forge.requests.ajax is an object like in your example, what actually gets posted is a query string that represents the object. The contentType option merely allows you to set the Content-Type header, it does not effect how objects are encoded for the request.
However if the data option is just a string, then this string is used as the body of the request. You can generate a JSON string to use as the body using JSON.parse like so:
forge.request.ajax({
...
contentType: 'application/json',
data: JSON.stringify({
"authData": {
"facebook": {
"id" : facebookId,
"access_token": accessToken,
"expiration_date": expirationDate
}
}
})
});

Resources