i would like to check (in before) if the homepage is online. If it is online, the Test steps (it()) have to be run.
If the homepage is offline, the test case have to terminate, before the it() run.
describe('check Homepage', () => {
before(() => {
cy.visit('/')
cy.get('.welcomeText').then((text) => {
if(text.text() !== 'Welcome to x'){
//terminate Test Case
}
})
})
it('check a', () => {
})
it('check b', () => {
})
it('check c', () => {
})
})
Thank you!
Well, you can just let it fail :)
But the check you want can be done with cy.request()
// NOTE must be function
function checkHomepage() {
const homepageUrl = Cypress.config('baseUrl')
cy.request({
url: homepageUrl,
failOnStatusCode: false
})
.then(response => {
if (response.statusCode !== 200) { // homepage is offline
this.skip() // skip the test
}
})
}
beforeEach(checkHomepage)
You could also take a proactive approach and retry until the homepage is accessable
function checkHomepage() {
const homepageUrl = Cypress.config('baseUrl')
cy.request({
url: homepageUrl,
retryOnStatusCodeFailure: true,
retryOnNetworkFailure: true
})
}
beforeEach(checkHomepage)
Related
I have a Cypress test:
describe('Create a session ', () => {
it('creates a session', () => {
cy.request({
method: 'POST',
url: `${Cypress.env('apiURL')}/api/v1/user/login/`,
form: true,
body: {
email: Cypress.env('email'),
password: Cypress.env('password'),
},
}).then((response) => {
expect(response.status).to.eq(200);
cy.task('setKey', response.body.data.key);
});
});
});
This POST returns some session data needed to create a dummy account:
describe('Create a company ', () => {
it('creates a company', () => {
cy.task('getKey')
.then((data: Key) => {
key = data;
})
.then(() => {
createNonce();
cy.request({
method: 'POST',
url: `${Cypress.env('apiURL')}/api/v1/cli/`,
headers: {
'X-Auth-Timestamp': epochTime(),
'X-Auth-Key': key.key,
'X-Auth-Nonce': nonce,
'X-Auth-Signature': createSignature(),
},
body: {
args: ['seeder', 'create', 'abc1'],
},
}).then((response) => {
expect(response.status).to.eq(200);
// TODO: we need some REST endpoints to return a JSON object instead of a string
data = JSON.parse(response.body.substring(response.body.indexOf('{')));
cy.task('setCompany', data);
});
});
});
});
I'm not sure I need these functions to be tests since they don't test anything, but just do a POST request. Is it possible to maybe move the functionality into a cypress task?
You can add the post request in your commands file:
function postRequest() {
cy.request({
method: 'POST',
url: `${Cypress.env('apiURL')}/api/v1/cli/`,
headers: {
'X-Auth-Timestamp': epochTime(),
'X-Auth-Key': key.key,
'X-Auth-Nonce': nonce,
'X-Auth-Signature': createSignature(),
},
body: {
args: ['seeder', 'create', 'abc1'],
},
})
}
Cypress.Commands.add('postRequest', postRequest)
An assuming all the rest of your code is fine, and you want only to abstract the logic; then in your test you can invoke that command:
describe('Create a company ', () => {
it('creates a company', () => {
cy.task('getKey')
.then((data: Key) => {
key = data;
})
.then(() => {
createNonce();
cy.postRequest().then((response) => {
expect(response.status).to.eq(200);
data = JSON.parse(response.body.substring(response.body.indexOf('{')));
cy.task('setCompany', data);
});
});
});
});
You can move these into before() or beforeEach() so they will be separate from your tests.
describe('Create a company ', () => {
before(() => {
cy.task('getKey')
.then((data: Key) => {
key = data;
})
.then(() => {
createNonce();
cy.request({
method: 'POST',
url: `${Cypress.env('apiURL')}/api/v1/cli/`,
headers: {
'X-Auth-Timestamp': epochTime(),
'X-Auth-Key': key.key,
'X-Auth-Nonce': nonce,
'X-Auth-Signature': createSignature(),
},
body: {
args: ['seeder', 'create', 'abc1'],
},
}).then((response) => {
expect(response.status).to.eq(200);
// TODO: we need some REST endpoints to return a JSON object instead of a string
data = JSON.parse(response.body.substring(response.body.indexOf('{')));
cy.task('setCompany', data);
});
});
})
it('creates a company', () => {
//test code
});
});
I am aiming to skip a spec files once an it() inside it fails. And I would still like to see the error reported so I know where to focus on.
I have two test scripts that is inside the same folder first.cy.js and second.cy.js:
describe('test body', () => {
afterEach(() => {
if (cy.state('test').state == 'failed') {
Cypress.runner.stop()
}
})
it('should pass first test', function() {
expect(true).to.eq(true)
})
it('should pass second test', function() {
expect(true).to.eq(true)
})
it('should fail third test and skip this script', function() {
expect(true).to.eq(false)
})
it('should skip fourth test', function() {
expect(true).to.eq(true)
})
})
My problem is on result reporting, it does not report the failing part:
Is there anything I am missing here?
EDIT: I also need to mention that we have retries set on cypress config:
retries: {
runMode: 2
},
Update: Was able to figure out how I will skip the spec file and still record errors with the help of Alapan das:
describe('skipping with retrying and recording', () => {
let errorCount = 0
afterEach(() => {
if (cy.state('test').state == 'failed') {
errorCount += 1
if (errorCount == 3) {
Cypress.runner.stop()
cy.state('test').state = 'failed'
}
}
})
})
The afterEach() is too early to call Cypress.runner.stop(), but it seems to work with test:after:run.
describe('test body', () => {
Cypress.on('test:after:run', (result) => {
if (result.currentRetry === result.retries && result.state === 'failed') {
Cypress.runner.stop()
}
})
it('should pass first test', function() {
expect(true).to.eq(true)
})
it('should pass second test', function() {
expect(true).to.eq(true)
})
it('should fail third test and skip this script', function() {
expect(true).to.eq(false)
})
it('should skip fourth test', function() {
expect(true).to.eq(true)
})
})
Running two identical tests in a single run
Before adding the Cypress.on('test:after:run')
After adding the Cypress.on('test:after:run')
I ran your test exactly in my local with cypress version 10.0.3, I am getting the failure count. This is without test re-tries.
describe('test body', () => {
afterEach(() => {
if (cy.state('test').state == 'failed') {
Cypress.runner.stop()
}
})
it('should pass first test', function () {
expect(true).to.eq(true)
})
it('should pass second test', function () {
expect(true).to.eq(true)
})
it('should fail third test and skip this script', function () {
expect(true).to.eq(false)
})
it('should skip fourth test', function () {
expect(true).to.eq(true)
})
})
Terminal Screenshot:
In case of test retries, one way would be to manually set the test state to failed like this:
afterEach(() => {
if (cy.state('test').state == 'failed') {
Cypress.runner.stop()
cy.state('test').state = 'failed'
}
})
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'm trying to wait for a specific graphql request to finish before I check for an element on the page but it doesn't seem to wait the way I have it set up
describe('CopyrightModule', () => {
it('edit, cancel, edit, save', () => {
cy.intercept(
{
method: 'POST',
url: '/graphql',
},
req => {
console.log(req.body.id);
console.log(req);
if (req.body.id === 'TakedownUserRendererQuery') {
req.alias = 'TakedownUserRendererQuery';
}
},
);
cy.visit('/');
cy.get(selectors.DMCA_LINK).click({ force: true });
cy.contains('My Requests').click();
cy.get(selectors.REQUEST_ROW)
.first()
.click();
cy.wait('#TakedownUserRendererQuery');
cy.get(selectors.COPYRIGHT_EDIT).click();
cy.contains('Cancel').click();
cy.get(selectors.COPYRIGHT_EDIT).click();
cy.contains('div', 'Owner Website URLs')
.find('input')
.first()
.type('8000-1612023');
});
});