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))
})
})
})
Related
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)
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 have tried to insert the value in db in my mocha test i am getting this error i tried few of the following ways but nothing work out.
var assert=require('chai').assert;
const user=require('../model/user')
i tried both way
describe('insertDataLasone',()=>{
it('should save the value ',(done)=>{
var User = new user({fname:'test'});
User.save().then(done=>{
done()
}).catch(done=>done())
})
})
describe('User', function() {
describe('#save()', function() {
// this.timeout(5000)
it('should save without error', function(done) {
var User5 = new user({fname:'test'});
User5.save(function(done) {
if (err) done(err);
else setTimeout(done,3000);
});
});
});
});
This error occurs when done() is not called in a test. Make sure you are calling done().
var assert = require('chai').assert;
const User = require('../model/user');
describe('insertDataLasone', () => {
it('should save the value ', done => {
var user = new User({ fname: 'test' });
user.save().then(() => {
done();
})
.catch(done); // mocha done accepts Error instance
});
});
or
var assert = require('chai').assert;
const User = require('../model/user');
describe('User', function() {
describe('#save()', function() {
it('should save without error', function(done) {
var user5 = new User({ fname: 'test' });
user5.save(function(err) {
if (err) done(err);
else done();
});
});
});
});
Read https://mochajs.org/#asynchronous-code carefully
I'm using jasmine+karma to run the following code...
and get the following error:
Expected { then : Function, catch : Function, finally : Function } to equal 123.
Can someone help me understand why I don't get a resolved value for my promise. thanks
'use strict';
angular
.module('example', ['ui.router'])
.config(function($stateProvider) {
$stateProvider
.state('stateOne', {
url: '/stateOne',
resolve: {cb: function($q) {
var deferred = $q.defer();
deferred.resolve(123);
return deferred.promise;
}},
controller: function($scope, cb) {console.log(' * in controller', cb);},
templateUrl: 'stateOne.html'
});
})
.run(function($templateCache) {
$templateCache.put('stateOne.html', 'This is the content of the template');
});
describe('main tests', function() {
beforeEach(function() {module('example');});
describe('basic test', function($rootScope) {
it('stateOne', inject(function($rootScope, $state, $injector, $compile) {
var config = $state.get('stateOne');
expect(config.url).toEqual('/stateOne');
$compile('<div ui-view/>')($rootScope);
$rootScope.$digest();
expect($injector.invoke(config.resolve.cb)).toEqual(123);
}));
});
});
Ok, Figured it out with some help (via email) from Nikas, whose blog I found at:
http://nikas.praninskas.com/angular/2014/09/27/unit-testing-ui-router-configuration/.
Here is a succinct example that demonstrates how to test the resolve values in ui.router, where the values involve $http.
angular
.module('example', ['ui.router'])
.factory('Clipboard', function($http) {
return {
get: function(args) {
return $http.get('/db/clipboard');
}
};
})
.config(function($stateProvider) {
$stateProvider
.state('stateOne', {
resolve: {cb: function(Clipboard) {
return Clipboard.get();
}}
});
});
describe('main tests', function() {
beforeEach(function() {module('example');});
it('stateOne', inject(function($state, $injector, $httpBackend) {
$httpBackend.whenGET('/db/clipboard').respond({a:1});
$injector.invoke($state.get('stateOne').resolve['cb'])
.then(function(res) {console.log(' *res ', res.data);})
.catch(function(err) {console.log(' *err ', err);});
$httpBackend.flush();
}));
afterEach(inject(function($httpBackend) {
$httpBackend.verifyNoOutstandingExpectation();
$httpBackend.verifyNoOutstandingRequest();
}));
});