export function createDashboardGroup(dashboardGroupName: string): string {
let preferredOrgId = '';
var ID = '' // it will be string;
cy.request({
method: 'GET',
url: getRequestUrl('/v2/user/_/preferences'),
})
.then((res) => {
preferredOrgId = res.body.sf_preferredOrg;
cy.request({
method: 'POST',
url: getRequestUrl(`/v2/dashboardgroup?organizationId=${preferredOrgId}`),
body: {
name: dashboardGroupName,
},
})
.then((dashboardRes) => {
ID = dashboardRes.body.id;
})
});
return ID;
}
Once I try to get the value of ID it returns an empty value. I was searching around, and could not find a solution. How I can get the value of the response and assign it to the global ID var and return it?
Please set it in an alias
.then((dashboardRes) => {
cy.wrap(dashboardRes.body.id).as('id')
})
Access it later via
cy.get('#id').then(id => {
})
Read this page to get background Variables and Aliases
You could store the variable as a global Cypress variable. In your last .then() block...
.then((dashboardRes) => {
Cypress.env('dashboardRes', dashboardRes)
})
.then(() => {
// test what you need with `Cypress.env('dashboardRes')`;
});
You could then reference it in your test by calling Cypress.env('dashboardRes');
What I did was not necessarily a global variable, but going off of this https://glebbahmutov.com/blog/cypress-tips-and-tricks/#wait-for-data
I created an object, then on the response, set a variable to the object. Then in the test, wrap the object, do .then() and then you have access to it.
Not saying this is the best way at all but it worked for my use case and may be helpful to someone
// commands.js
let data = {}
Cypress.Commands.overwrite('visit', (originalFn, url, options) => {
cy.intercept(/endpoint', (req) => {
req.continue((res) => {
data.info = res.body.info
})
})
})
export { data }
/// ----- in test file ------ ////
import { data } from '../support/commands'
it('test', () => {
cy.wrap(data).then((data) => {
console.log(data.info) // here you have access to it
})
})
Related
Is that possible in Cypress to invoke the Chainer to obtain the results of a get request?
let chainer = cy.request(
{
url: "http://localhost:8080/v1/submit",
method: "GET",
timeout: timeouts.request,
failOnStatusCode: failOnStatusCode
})
let response = chainer.invoke() /// <---- THIS DOESN"T EXISTS
console.log(response) // I would like to use response here
You can't do it (not in the same code block).
You are thinking of the async/await pattern, but Cypress does not support it.
You can use a beforeEach() block to set a closure variable or an alias.
describe('request a variable', () => {
let response;
before(() => {
cy.request(...).then(res => response = res)
})
it('uses response', () => {
console.log(response)
})
})
or use an alias to put the response on this
describe('request a variable', () => {
before(function() {
cy.request(...).as('response')
})
it('uses response', function() {
console.log(this.response)
})
})
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))
})
})
})
I was searching for my answer in SO, but could not find any suitable one. So here i go with my questions...
In my redux action creator i am fetching API call from isomorphic-unfetch but I am getting the message Error: Actions must be plain objects. Use custom middleware for async actions each time.Though i defined dispatch in my action...
My action code is
const exchangeBuy = ({btc, usdt, id}, url) => {
return (dispatch) => {
fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify( { btc, usdt, id } )
}).then(
r => r.json()
).then(
r => dispatch({
type: 'EXCHANGE_BUY',
payload: r //here r return an object from mongoDB
})
)
}
}
Also the code that invokes this is
submitExchange(e){
e.preventDefault()
const btc = e.target.btcamount.value
const usdt = e.target.usdprice.value
this.props.exchangeBuy( //Here it is
{
btc: btc,
usdt: usdt,
id: this.props.users.id
},
this.props.apiurl )
}
When I connect axion in get method I get a response from my api and I want to print info on the website.
I tried to change this line:
.then(response => (this.username= response.data.username)) or this
.then(response => (this.username= response.data[0].username)) or this
.then(response => (this.username= response.data.username[0]))
Script
<script>
import axios from 'axios';
export default {
name: "acount",
el: '#app',
data() {
return {
username: null,
pseudo: null,
email: null,
date: null,
};
},
mounted () {
axios
.get('http://127.0.0.1:8080/api/user/65', {
headers: {
token: ''
}
})
.then(response => (this.username= response.data[0].username[0]))
.then(response => (this.pseudo = response.data.pseudo))
.then(response => (this.email = response.data.email))
.then(response => (this.date = response.data.create_at))
}
}
</script>
To chain promises, each function within then() needs to return a value. other than that we could only help, if we would know how the actual response looks like.
new Promise(function(resolve, reject) {
setTimeout(() => resolve(1), 1000); // (*)
}).then(function(result) { // (**)
alert(result); // 1
return result * 2;
}).then(function(result) { // (***)
alert(result); // 2
return result * 2;
}).then(function(result) {
alert(result); // 4
return result * 2;
});
This arrow function uses implicitly returned value:
.then(response => (this.username= response.data[0].username[0]))
This results in having response parameter in next then equal to this.username. To avoid such mistakes, ESLint no-return-assign rule can be used.
Instead, it should be:
.then(response => {
this.username= response.data[0].username[0];
return response;
})
Multiple then are unnecessary because there are no multiple promises to chain. They could be rewritten to single then:
axios.get(...)
.then(response => {
this.username= response.data[0].username[0]);
...
});
I am trying to achieve the following functionality
Before Block : Call the Cy.visit("/login") and call a Function which will trigger a REST API and process the REST API response and set the local storage.
Only after the local storage is set click on "My Account" Link
Here is the source Code I am trying.
import * as subscriberHelpers from '../../../helpers/subscriberHelpers';
import * as localStorage from '../../../helpers/localStorage';
describe('testCode', () => {
before((done) => {
cy.visit('/login', {
timeout: 10000,
onLoad: () => {
localStorage.write("CD-Environment", Cypress.env('defaultEnvironment'));
localStorage.write("CD-Language", "en-US");
localStorage.write("CD-SystemId", "85788485-e411-48a9-b478-610c1285dc1a");
}
})
subscriberHelpers.createSubscriber().then(()=>{
done();
})
})
it('sClick on my account link', () => {
cy.get('.c-header-listItem > .c-link').contains("My Account").click();
})
})
Here is the code to createSubscriber function
export function createSubscriber() {
let URL = `SOME URL`;
let body = {
Some Body
}
return new Promise((resolve, reject) => {
request.subscriberServiceRequest(URL, body).then((response) => {
if (response.status === 200 && ("SessionId" in response.body)) {
localStorage.write("CD-SessionId", response.body.SessionId);
localStorage.write("CD-SubscriberId", response.body.Subscriber.Id);
resolve();
}
else if (response.status === 200 && ("Fault" in response.body)) {
reject(response.body.Fault.Message);
}
})
})
}
Here is the code to subscriber Service request function
export function subscriberServiceRequest(url, body, headers = null) {
let defaultHeaders = { "CD-SystemId": "85788485-e411-48a9-b478-610c1285dc1a" }
if (headers != null) {
defaultHeaders = addHeaders(defaultHeaders, headers);
}
return new Cypress.Promise((resolve, reject) => {
cy.request({
url: url,
method: 'POST',
body: body,
headers: defaultHeaders
}).then((response) => {
resolve(response);
});
})
}
When I try Executing the code I am getting following error in cypress
But the element existing in the UI
Questions:
Why I am getting the error
How to call more than one async functions
in before block
How to tell cypress to wait till the functions on
before block get processed meaning not only wait till receiving the
response but wait till the response got processed in the THEN block
To answer your first question:
Why I am getting the error
.contains() specifically searches for elements within but not including the tag it is called on. In other words, someElement.contains("My Account") will not match someElement.
What you should have instead is this:
cy.get('.c-header-listItem').contains("My Account").click();
Or simply:
cy.contains("My Account").click();