Getting 403: forbiden responce when i navigate to link using loop - cypress

I am checking the API response using loop but getting 403: Forbidden for the last two scripts.
Here is my script.
Please check below image XPath //a[5] and XPath //a[6] working fine but getting an error in XPath //a[7]
Also, get the status code 200 when I check in Postman. Here are screenshots for postman please check them.
What is the problem here anyone can help me.
This is my test code. getting error for only XPath //a[5] and XPath //a[6].
it('Navigate through the links using loops', () => {
Cypress.Cookies.preserveOnce('session_id', 'remember_token')
cy.visit('hubs/26/brain');
cy.get('.notification-dismiss').click();
cy
.xpath("//a[1]")
.then(link => {
cy
.request(link.prop('href'))
.its('status')
.should('eq', 200);
});
cy
.xpath("//a[2]")
.then(link => {
cy
.request(link.prop('href'))
.its('status')
.should('eq', 200);
});
cy
.xpath("//a[3]")
.then(link => {
cy
.request(link.prop('href'))
.its('status')
.should('eq', 200);
});
cy
.xpath("//a[4]")
.then(link => {
cy
.request(link.prop('href'))
.its('status')
.should('eq', 200);
});
cy
.xpath("//a[5]")
.then(link => {
cy
.request(link.prop('href'))
.its('status')
.should('eq', 200);
});
cy
.xpath("//a[6]")
.then(link => {
cy
.request(link.prop('href'))
.its('status')
.should('eq', 200);
});
cy
.xpath("//a[7]")
.then(link => {
cy
.request(link.prop('href'))
.its('status')
.should('eq', 200);
});
cy
.xpath("//a[8]")
.then(link => {
cy
.request(link.prop('href'))
.its('status')
.should('eq', 200);
});
});

sometimes if you can be waiting for a request that has already been completed.
cy.wait() accepts also an array of aliases so you can first collect all aliases and then wait for all of them with a single cy.wait().
const aliases = [];
for (let i = 0; i < requestUrls.length; i++) {
aliases.push(`#request${i}`);
...
}
cy.wait(aliases);
But it is better if you can share the code and details.

Related

Not able to use alias across tests in Cypress

I am trying to create a framework for API tests using cypress and I am facing an issue accessing the data between tests using an alias. Is there something that I am missing?
custom.js
Cypress.Commands.add('getResource', function (uri) {
cy.request({
url: uri,
method: 'GET'
}).then(function (response) {
return cy.wrap(response);
});
});
test.js
exports.__esModule = true;
context('requests', function () {
it('validate get call response', function () {
let re = cy.getResource('https://reqres.in/api/users?page=2','resp')
re.then(function (response) {
cy.wrap(response.body).as('respbody');
cy.wrap(response.status).as('respstatus');
//cy.log(JSON.stringify(response.body));
});
});
it('Tests test', function () {
cy.wait('#respbody').then((body) => {
console.log(JSON.stringify(body));
});
});
});
cypress version - 8.2.0
By design cypress cleans up aliases after each test. So you can do something like this cypress recipe
Your getResource custom command is taking just one parameter, hence we are passing just one papameter.
exports.__esModule = true;
let responseBody;
let responseStatus;
context('requests', () => {
before(() => {
cy.getResource('https://reqres.in/api/users?page=2')
.then(function(response) {
responseBody = response.body
responseStatus = response.status
})
})
beforeEach(() => {
cy.wrap(responseBody).as('responseBody')
cy.wrap(responseStatus).as('responseStatus')
})
it('Get Response status', function() {
cy.wait('#responseStatus').then((responseStatus) => {
console.log(responseStatus)
})
})
it('Get Response Body', function() {
cy.wait('#responseBody').then((responseBody) => {
console.log(JSON.stringify(responseBody))
})
})
})

Cypress, loop till response of api call has expected value

Im making an api call with cypress. This apis returns status of operation happening server side. Sample response {'status':'13'}. This means job completed 13%. I have to wait till I get status as 100 before performing other operations.
...
cy.request(getStatusUrl)
.then(response => {
console.log(response.body.status);
});
...
I have keep polling getStatusUrl till status comes as "100".
How do I get the value of response.body.status out of then{...} to use in a loop?
function pollProgress(url, done) {
cy.request(url)
.then(response => {
const progress = response.body.status;
// Poll every 500ms until progress reaches 100%
setTimeout(() => {
if (progress < 100) {
pollProgress(url, done);
} else {
done({ status: 'OK' });
}
}, 500);
})
.catch(() => {
done({ status: 'ERROR' })
})
}
...
new Promise((resolve, reject) => {
pollProgress(getStatusUrl, ({ status }) => {
if (status == 'OK') ? resolve() : reject();
});
})
.then(() => {
// it's 100% here if there's no error
})

Is the following how jQuery promise chaining is written compared to how ES6 promise chaining is written?

Is the following jQuery code equivalent to how it is done in ES6's way, or should the jQuery way be written differently?
// ES6:
new Promise((resolve, reject) => {
console.log("start");
setTimeout(() => resolve("a"), 2000);
}).then(s => {
console.log(s);
return new Promise((resolve, reject) => {
setTimeout(() => resolve("b"), 2000);
});
}).then(s => {
console.log(s);
return new Promise((resolve, reject) => {
setTimeout(() => resolve("c"), 2000);
});
}).then(s => {
console.log(s);
});
// jQuery:
let d = $.Deferred();
d.then(s => {
console.log(s);
let d = $.Deferred();
setTimeout(() => d.resolve("b"), 2000);
return d.promise();
}).then(s => {
console.log(s);
let d = $.Deferred();
setTimeout(() => d.resolve("c"), 2000);
return d.promise();
}).then(s => {
console.log(s);
})
console.log("start");
setTimeout(() => d.resolve("a"), 2000);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
It seems:
Not everything can be written in one statement in jQuery. The executor has to be moved out as separate statements in jQuery.
For jQuery, not only promise needs to be involved. The deferred needs to be used, because otherwise there is no way to resolve the promise.
In jQuery, the line return d.promise(); can just be return d;, but is it good to return the deferred? The code that receives the deferred can inadvertently resolve the promise, but if it is chained promises, can any code actually receive the deferred and inadvertently resolve the promise?
Per #Tomalak and #jfriend00's comment, it is found that jQuery's promises can be written this way, similar to ES6 promises:
// jQuery:
$.Deferred(d => {
console.log("start");
setTimeout(() => d.resolve("a"), 2000);
}).then(s => {
console.log(s);
return $.Deferred(d => {
setTimeout(() => d.resolve("b"), 2000);
});
}).then(s => {
console.log(s);
return $.Deferred(d => {
setTimeout(() => d.resolve("c"), 2000);
});
}).then(s => {
console.log(s);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Instead of function(resolve, reject), it is function(deferred).
The jQuery.Deferred method can be passed an optional function, which is called just before the method returns and is passed the new deferred object as both the this object and as the first argument to the function.
The passed in deferred is the same as this only if it is a traditional function but not an arrow function. But I think it will be better to use the passed in deferred d instead of using this.

Dialogflow v2 Actions on Google response timeout

Hi I have a timeout problem to get a json response; I am using google places API to look for the closest location.
Could anyone help me with this? Thanks.
const PlaceSearch = require("./node_modules/googleplaces/lib/NearBySearch.js");
const PlaceDetailsRequest = require("./node_modules/googleplaces/lib/PlaceDetailsRequest.js");
app.intent('Ask Location', conv => {conv.ask(new Permission({context: 'To start',permissions: 'DEVICE_PRECISE_LOCATION',}));});
app.intent('geolocation.intent', (conv,params,granted) =>{
if(granted){
var coordinates = conv.device.location.coordinates;
var location = [coordinates.latitude, coordinates.longitude];
var searchParameters = {
location: location,
name:'Store Name',
radius:10000
};
var config = {
apiKey:'#####',
outputFormat:'json'
};
var placeSearch = new PlaceSearch(config.apiKey, config.outputFormat);
var placeDetailsRequest = new PlaceDetailsRequest(config.apiKey, config.outputFormat);
placeSearch(searchParameters, function (error, search_response) {
if(search_response.status === 'OK'){
placeDetailsRequest({reference: search_response.results[0].reference}, function (error, details_response) {
conv.ask(`Your closest store is at ${details_response.result.formatted_address}.`);
});
}
});
}
});
I solved the issue using a request to Google API via URL; and using a promise.
const request = require("request");
app.input("geolocation.intent", conv => {
return new Promise((resolve, reject) => {
...
request(options, (error, response, body) => {
...
if (error) {
...
reject(...);
} else {
...
resolve(...);
}
}).then(result => {
const address = result.address;
conv.ask('Your closest store is...');
}).catch(error => {
conv.close('Error in Promise');
});
});
What I learned is that in Dialogflow API v2 you need to use promises when you make a request.

how to avoid repeating expectations in multiple test when using mocha/chai

I have 20 tests with the same check/expections and I want to reduce the repeated function in the end method call. Any suggestions to refactor?
describe('my test 1', function() {
it('response with email id reference expected', function(done) {
request
.post(apiPath)
.send(input)
.end(function(err, res) {
expect(res.statusCode).equals(200);
expect(res.body.refId.length == 36);
expect(res.body.this1.length = 1);
expect(res.body.that2.length = 2);
expect(res.body.that3.length = 3);
done();
});
});
});
I managed it like this below. If there is better way then please answer.
let positiveAssertions = function(response) {
expect(response.statusCode).equals(200);
expect(response.body.refId.length == 36);
expect(response.body.this1.length = 1);
expect(response.body.that2.length = 2);
expect(response.body.that3.length = 3);
};
describe('my test 1', function() {
it('response with email id reference expected', function(done) {
request
.post(messagingApiPath)
.send(input)
.expect((response) => positiveAssertions(response))
.end(done);
});
});

Resources