I am trying to stub out a route using cypress 5.2. I have a simple function to do that:
function mockAlertsResponses(){
cy.route({
method: "GET",
url: "/api/polling/alerts/statistics*",
response: {
total: 2,
...
}
});
}
In one set of tests, this works just fine:
describe("admin and read only permissions", () => {
it ("all action bar items are enabled with admin permissions", () => {
cy.login("user", "password");
mockAlertsResponses();
// Click alert to enable all buttons
cy.get("#1-checkbox").click()
cy.get("#mark-alert-button").should("be.enabled");
cy.get("#delete-alert-button").should("be.enabled");
});
// ... a few more similar tests
});
However, in another set of tests, I use the same function:
it("Logs in and out", () => {
cy.login("username", "password");
mockAlertsResponses()
cy.get("#vine-appbar").should("be.visible");
cy.get("#info-button").click();
cy.get("#info-menu-logout").click();
cy.get("#login-button");
cy.get("#vine-appbar").should("not.be.visible");
});
In this second set of tests, the routes are not stubbing properly, leading to errors and test failures. Here, you can see the route is not stubbed, but rather throws a 500 error:
I'm not sure what could be interfering here. I'm a bit new to cypress and I'm not even sure where to begin debugging this. Might the cy.server calls be interfering? Please let me know what more information we'd need to figure out why one set of stubs works and another doesn't.
If you're wondering, the login function has a call to cy.server and has its own cy.route as well:
Cypress.Commands.add("login", (username, password, admin = true) => {
const response = admin ? <jwt1> : <jwt2>
cy.server();
cy.route({
method: "POST",
url: "/api/login",
response
});
cy.visit("/logout");
cy.visit("/");
cy.wait(100);
cy.get("#login-error").should("not.be.visible");
cy.get("#login-username").type(username);
cy.get("#login-password").type(password);
cy.get("#login-button").click();
});
Related
I have the following code:
export function backofficeAuthenticate(username, password) {
cy.session(['Login'], () => {
cy.request({
log: false,
method: 'POST',
url: getBackUrl('/login.htm'),
qs: {
redir: getBackUrl('/back'),
},
followRedirect: false,
body: {
'Login_login-email': username,
'Login_login-password': password,
'action[Login_login:login]': 'login',
},
});
});}
And I am calling a function to login like that:
export function loginWithAdmin() {
backofficeAuthenticate(Cypress.env('WEB_LOGIN_USERNAME'), Cypress.env('WEB_LOGIN_PASSWORD'));
}
My code in the test is:
import { loginWithAdmin, httpAuthentication } from '../../cypress/support/bestreviews.js';
describe('Dashboard types quick smoke', () => {
const endpoints = [
'/dashboard',
'/dashboard/articles',
'/dashboard/archive',
'/dashboard/syndicated',
'/dashboard/tribunearticles',
'/dashboard/giftguides',
'/dashboard/blogposts',
];
endpoints.forEach((endpoint) => {
it(endpoint, () => {
cy.visitBackOffice(endpoint);
httpAuthentication();
loginWithAdmin();
cy.checkErrorFree();
cy.get('.dashboard-entries').should('exist');
cy.get('[data-content="topic-info"]').should('exist');
});
});
});
After I execute the code, I always got an error:
(uncaught exception) TypeError: Cannot read properties of null
(reading 'style') TypeError The following error originated from your
application code, not from Cypress.
Cannot read properties of null (reading 'style')
When Cypress detects uncaught errors originating from your application
it will automatically fail the current test.
This behavior is configurable, and you can choose to turn this off by
listening to the uncaught:exception event.Learn more
Does anyone know what I am missing? I think the problem is with cypress session, but not sure how to proceed...
To make sure that cypress catches exceptions generated from your application you can add this in cypress/support/e2e.js
Cypress.on('uncaught:exception', (err, runnable) => {
// returning false here prevents Cypress from
// failing the test
return false
})
Note: One thing to note is that if you add this, cypress will not catch exceptions generated from your application, which is not a good practice, because you want your tests to catch exceptions.
I've finished writing my first Cypress test. Everything is good except I'm struggling to post the result data to a website. Because I want to send the result data and also if any errors occurs the result screenshot to our coworker telegram group.
For the last two days I've tried everything and couldn't find any solution.
I've tried those in my test script (cypress/integration/test.js);
Cypress.on('test:after:run', (test, runnable) => {
console.log('test,runnable', test, runnable)
const details = {
projectKey: Cypress.env('zephyr-project-key'),
testName: test.invocationDetails.relativeFile,
status: test.status,
error: runnable.err.message,
retries: runnable.retries.length,
duration: test.wallClockDuration,
startTime: test.wallClockStartedAt
}
cy.request('POST', 'http://mywebsite.com/notify.php', { body: details })
fetch('http://mywebsite.com/notify.php')
})
Also this didn't work (cypress/plugins/index.js);
module.exports = (on, config) => {
// `on` is used to hook into various events Cypress emits
// `config` is the resolved Cypress config
on('after:run', (results) => {
if (results) {
// results will be undefined in interactive mode
console.log(results.totalPassed, 'out of', results.totalTests, 'passed')
fetch('http://mywebsite.com/notify.php');
}
})
}
Edit: This is day 3 and I still couldn't solve this. What I've seen from Cypress help page is that cy.task() calls do not fire in 'test:after:run' event block;
https://github.com/cypress-io/cypress/issues/4823
I've seen some telegram groups who can do what I'm trying to do. All I need is to be able to get the results and post it to my website.
The third parameter to cy.request() is body, you don't have to wrap it.
Cypress.on('test:after:run', (test, runnable) => {
const details = {
projectKey: Cypress.env('zephyr-project-key'),
testName: test.invocationDetails.relativeFile,
status: test.status,
error: runnable.err?.message, // need err?.message if there is no error
retries: runnable.retries.length,
duration: test.wallClockDuration,
startTime: test.wallClockStartedAt
}
cy.request('POST', 'http://mywebsite.com/notify.php', details) // don't wrap details
.then(res => expect(res.status).to.eq(201)) // confirm result
})
I have a web application and logged into that. On the Menu > Submenu I have a 'Customers' link. When I click on the customers link there is some delay in loading the page
Can we add a cy.route() for that ? The below route is not working. For the time being I am using cy.wait() an need to avoid that.
I am getting an error >> Timed out retrying: cy.wait() timed out waiting 5000ms for the 1st request to the route: getCustomers. No request ever occurred.
context('Route testing', () => {
before(() => {
cy.loginToWebApplication();
});
it('Test route', () => {
cy.server();
cy.route({
method: 'GET',
url: 'https://testsite-url/company/customers.php',
}).as('getCustomers');
cy.get('#submenu_People ul li a')
.contains('Customers')
.click({force: true});
cy.get('input[name="searchText"]').type('Some Customer');
cy.wait('#getCustomers');
});
});
Another example, one on click on the Search button, some delay in navigating and displaying the invoice data: In both cases routes are not working, could someone please give some idea.
it('Test route', () => {
cy.server();
cy.route({
method: 'GET',
url:
'**invoices.php?&ajaxCall=true&selectedMainItem=invoices&invoiceItem=unpaid**',
}).as('invoicesSearch');
cy.get('#Invoices ul li a').contains('Current Invoices').click({force: true});
cy.get('#resultsTable tbody tr').each(($tr, index) => {
const invoiceID = Cypress.$($tr).find('td').eq(1).text();
if (invoiceID == 1280) {
cy.get('#searchText').type(invoiceID);
}
});
cy.get('.searchContainer button[type="button"]')
.contains('Search')
.click({force: true});
cy.wait('#invoicesSearch');
cy.get('#invoicesSearch h2').contains('Current Invoices (1)');
});
There are numerous examples in the Cypress Real World App, a payment application to demonstrate real-world usage of Cypress testing methods, patterns, and workflows of watching routes and waiting for results before proceeding with the test, which is a best practice.
Refer to our transaction feeds spec and it's beforeEach block where we recommend placing cy.server and cy.route statements.
I have been struggling on how i can mock a function so that i can return a fake value from that function.
I have a simple script that can make a api call, however this api call has two parameters. One parameter is provided through the parameter of the parent function, the other one is provided by making a call to another function. The return value from this function is what i need to mock.
The full code is quite complex, that's why i made a small sample of what i mean. Firstable i have the function makeTheCall. Within that function i call a function called setParameters.
const setParams = require('setParams.js');
module.exports.makeTheCall = (event) => {
const params = setParams('GET', '/todos/1');
const postData = {
name: event.name,
location: event.location
}
console.log(params); //dynamic params 'method' and 'callpath' are both undefined here (should be 'GET' and '/todos/1')
return doARequest(params, postData).then((result) => {
return result;
}).catch((error) => {
return error;
})
}
The setParams function is not so difficult. It just returns an object that contains some static and some dynamic values.
module.exports.setParams = (method, callPath) => {
return {
host: 'jsonplaceholder.typicode.com',
port: 433,
method: method,
path: callPath
}
}
Now, here is where the interesting part comes into play. When write a simple test the call cannot go through. This is, of course, because it cannot resolve the dynamic values method and callPath.
const makeTheCall = require('makeTheCall.js');
it('runs a happy flow scenario', () => {
const event = {
name: 'John Doe',
location: 'Somewhere'
}
return makeTheCall(event)
.then(response => {
//Do some usefull testing here
});
});
My question is how i can mock the return value of the setParams method so that it will return something like:
{
host: 'jsonplaceholder.typicode.com',
port: 433,
method: 'GET',
path: '/todos/1'
}
This way i can invoke my API call in my test without it causing an error. I have been looking into mocking using sinon, particularly into sinon stubs, like:
const params = setParams('GET', '/todos/1');
sinon.stub(params).returns({
host: 'jsonplaceholder.typicode.com',
port: 433,
method: 'GET',
path: '/todos/1'
});
However i think i overlook something because this does not work. The documentation is nice but after a couple of hours struggling and trying things i start to feel kinda lost.
Who knows / can point me in the right direction on how to mock the return value of the setParams function? An example will be highly appreciated.
You're not calling sinon.stub quite right. stub() needs an object and a function that is a property of that object. If you import with:
const setParams = require('setParams.js');
Then setParams will be the modules.export object and setParams will be a property, so you can stub it with something like:
let fakeParam = {
host: 'jsonplaceholder.typicode.com',
port: 433,
method: 'GET',
path: '/todos/1'
}
let paramStub = sinon.stub(params, 'setParams').returns(fakeParam)
In the broader picture it's not really clear what you are trying to test. With unit tests you generally try to reduce everything down to one small thing you want to assert. So in this case maybe you want to assert that when you call makeTheCall doARequest is called with the params returned from setParams. In that case you might also stub doARequest. Then you can assert with sinon.calledWith(doARequestStubb, fakeParam). You can have doARequestStubb resolve with a promise to the code doesn't break.
I work on a domain management software through the OVH's API.
I use nodejs and node-webkit and I downloaded the official Node.js wrapper for OVH.
Then, I followed the documentation here: https://www.npmjs.com/package/ovh and here: https://eu.api.ovh.com/g934.first_step_with_api, and I came with the following code:
// set the ovh object with the right configuration
var ovh = require('ovh')({
endpoint: 'ovh-eu',
appKey: 'APP_KEY', // replace it with my key
appSecret: 'APP_SECRET' // replace it with my key
});
ovh.request('POST', '/auth/credential', {
// set access rules
'accessRules': [
{'method': 'GET', 'path': '/*'},
{'method': 'POST', 'path': '/*'},
{'method': 'PUT', 'path': '/*'},
{'method': 'DELETE', 'path': '/*'},
]
}, function (error, credential) {
// print the error if the request failed, else, print the response
console.log(error || credential);
// set the consumerKey in the ovh object
ovh.consumerKey = credential.consumerKey;
// connect on the credential.validationUrl to validate the consumerKey
console.log(credential.validationUrl);
testMe();
});
function testMe() {
/*
This fonction test a request every second
to check if the user connected himself
*/
ovh.requestPromised('GET', '/me')
.then (function (me) {
// if the user is connected, tell him welcome
console.log('Welcome ' + me.firstname);
}
)
.catch (function (err) {
console.log(err);
// while the user is not connected, retry the request
setTimeout(testMe, 1000);
}
);
}
Well, when I execute this, everything is fine until I try to connect through the url, the testMe function keeps telling me an error and I don't get the welcome message.
In order to fix my problem, I tried to use different way to write my code and even checked in OVH's module sources if the signature was right before and after hashing, but it all seems to be good...
If someone already had this issue or if anybody see a error in my code, I would really appreciate your help. Thanks
you've got a syntax error :
then (function (response) {
// if the user is connected, tell him welcome
console.log('Welcome ' + me.firstname);
})
try this instead (renamed the parameter):
then (function (me) {
// if the user is connected, tell him welcome
console.log('Welcome ' + me.firstname);
})
Anyway, it it doesn't work properly please tell us the error you are getting.