Cypress Code:
describe("/gradebook/", () => {
before(() => {
cy.login("username", "password");
cy.intercept("GET", "/api/**").as("getApi");
cy.visit("/home/");
cy.wait("#getApi");
cy.log("111");
});
after(() => {
cy.intercept("GET", "/api/**").as("getApi2");
cy.wait("#getApi2");
cy.log("333");
cy.logout();
});
it("Loads Page Title: Gradebook", () => {
cy.log("222");
});
});
The Problem:
Sometimes it throws an error undefined: undefined but it seems random.
Output Image (when it fails):
Only thing I can think of is that it's somehow logging out before the /api/gradebook/scores/ request finishes, which is why it 400s, but don't know how to fix that. It is intercepting the request, so it shouldn't be continuing to the logout until that's finished.
*Note: I found this Is there a way to check if there are any pending fetch requests? but it doesn't have any answers.
Related
It's my first post on the stackoverflow so I apologize in advance if I am doing something wrong.
I'm new to Cypress E2E test. Im trying to write a test for react WebApplication.
Unfortunately I am stuck on the element when the application on mobile views e.g. viewPort 360 opens in full screen. The application is doing that when I interact with the first element (login page). After filling the login field spec then stops with the message "(uncaught exception) TypeError: Fullscreen request denied".
Is there any way to work around this? On higher resolutions where full screen is not opened spec passes without problem.
Screen with the error from Cypress
I was searching if there is a parameter in Cypress settings to disable the blocker for full screen , unfortunately I did not find anything.
The same problem occurs on Chrome and Firefox.
The spec code is very simple
I use the class from POM
class Homepage_PO {
Visit_Homepage(){
cy.visit(Cypress.env('integrax_homepage'),{timeout:60000})
}
Login(login, password){
cy.get('input[name="login"]').type(login)
cy.get('input[name="password"]').type(password)
cy.get('#loginBtn').click()
}
}
export default Homepage_PO;
and the spec code
import Homepage_PO from "../../support/pageObjects/integraX/Homepage_PO";
/// <reference types = 'cypress'/>
describe('Log in into IntegraX', () => {
const homepage_PO = new Homepage_PO()
beforeEach(() => {
homepage_PO.Visit_Homepage();
});
it.only('log in as Integra administrator', () => {
homepage_PO.Login(Cypress.env('integra_admin_login'), Cypress.env('integra_admin_password'));
});
it('log in as Car Service', () => {
});
});
You might be able to disable fullscreen by replacing the method on the element or documentElement.
See How TO - Fullscreen.
If the call is at element level
const stub = cy.stub();
cy.get('input[name="password"]')
.then($el => $el[0].requestFullscreen = stub)
.type(password)
.then(() => expect(stub).to.be.called)
or if the call is at document level
const stub = cy.stub();
cy.document().then(doc => {
doc.documentElement.requestFullscreen = stub
})
cy.get('input[name="password"]')
.type(password)
.then(() => expect(stub).to.be.called)
In case this method cannot be stubbed, you can catch the uncaught exception error and just let the test carry on
Cypress.once('uncaught:exception', () =>
return false
})
cy.get('input[name="password"]')
.type(password) // error suppressed by above handler
Thank you for your help.
This solution worked in my case (the call is at document level)
const stub = cy.stub();
cy.document().then(doc => {
doc.documentElement.requestFullscreen = stub
})
cy.get('input[name="password"]')
.type(password)
.then(() => expect(stub).to.be.called)
This solution also werked but I'll need to add it to each field. The same problem occured when I was clicking "Login" btton. So abowe solution is much better.
Cypress.once('uncaught:exception', () =>
return false
})
cy.get('input[name="password"]')
.type(password) // error suppressed by above handler
When I run my Cypress tests I randomly get HTTP 405 Method not allowed code when I submit the form, but the HTTP method is a correct one - POST. If I open the Developer Tools to see the outgoing request the HTTP 405 is never returned, in other words the error only happens when Developer Tools are closed. No combination of cy.pause(), cy.wait() alleviates the problem.
Question: Can you configure Cypress so it logs all the outgoing requests and responses to a file so I don't have to open DevTools?
Should be possible with cy.intercept() functional handler.
General info here Using the routeHandler function
cy.intercept(url, (req) => {
cy.writeFile('my-log', req, { flag: 'a' }) // append
req.continue((res) => {
cy.writeFile('my-log', res, { flag: 'a' }) // append
})
})
Utilizing an interceptor solely for logging purposes is not very efficient.
You can generate a HAR file that includes detailed information about the network activity during the execution of your Cypress tests.
Especially for this purpose, you can use the cypress-har-generator.
describe('my tests', () => {
before(() => {
// start recording
cy.recordHar();
});
after(() => {
// save the HAR file
cy.saveHar({ waitForIdle: true });
});
it('does something', () => {
cy.visit('https://example.com');
// ...
});
});
I have a question about cypress testing.
I'm doing the following:
cy.route() to an url with alias
then cy.wait(#alias)
I know that the default action that cypress does it to fail the test if the there wasn't any request made to that url.
My problem is that I have multiple requests and one of them may not reach the request url. But I don't want that to fail my test, just to skip over it. How can I do this?
Basically, I'm asking how do you make your tests NOT to fail when you get this:
CypressError: Timed out retrying: cy.wait() timed out waiting 30000ms for the 221st response to the route: 'productRequest'. No response ever occurred.
If your usecase is to wait for requests and then continue with more commands, this solution might help you:
describe("route", () => {
it("hiting route", () => {
let req1 = false;
let req2 = false;
cy.server()
cy.route({
methdod: "GET",
onRequest: () => {
req1 = true;
},
url: "/will/eventually/called"
});
cy.route({
methdod: "GET",
onRequest: () => {
req2 = true;
},
url: "/will/eventually/called2"
});
setTimeout(() => {
req2 = true
}, 2000)
cy.visit("https://biehler-josef.de")
cy.get("body").should(() => {
if (req1) {
expect(req1).to.eq(true);
}
if (req2) {
expect(req2).to.eq(true);
}
if (!req1 && !req2) {
expect(false).to.eq(true)
}
});
cy.get("body").should("exist");
});
})
You define the routes and pass a onRequest function that sets a variable. This can be done with multiple routes. Then you use should with callback function. Within that you can check both variables and force to fail only if no request occurred. The setTimeoutin this example demonstrates a request that takes 2 seconds to finish.
If you want to check if a request is not hit, it is much easier. But this solution is not usable if you want to execute additional commands after the cy.wait(#alias):
describe("route", () => {
it("hiting route", (done) => {
cy.server()
cy.route("GET", "will/never/be/hit").as("requestalias");
cy.visit("https://biehler-josef.de")
cy.on("fail", (error) => {
if (error.name === "CypressError"
&& error.message.match(/.*Timed out retrying: cy.wait().*requestalias.*/)) {
// calling done forces cypress to turn test to green
done()
}
});
cy.wait("#requestalias")
});
})
With cy.on("fail") you can listen to the event that is thrown when a test fails. Caling done() within this will force the test to be green. But you can not continue with subsequent commands in your test. So the wait() must be the last command in your test
As far as I can tell, using promises or callbacks in After hook prevents Command Queue from executing when using promises / callbacks. I'm trying to figure out why, any help or suggestions are appreciated. Closest issue I could find on github is: https://github.com/nightwatchjs/nightwatch/issues/341
which states: finding that trying to make browser calls in the after hook is too late; it appears that the session is closed before after is run. (exactly my problem). But there is no solution provided. I need to run cleanup steps after my scenarios run, and those cleanup steps need to be able to interact with browser.
https://github.com/nightwatchjs/nightwatch/wiki/Understanding-the-Command-Queue
In the snippet below, bar is never outputted. Just foo.
const { After } = require('cucumber');
const { client } = require('nightwatch-cucumber');
After(() => new Promise((resolve) => {
console.log('foo')
client.perform(() => {
console.log('bar')
});
}));
I also tried using callback approach
After((browser, done) => {
console.log('foo');
client.perform(() => {
console.log('bar');
done();
});
});
But similar to 1st example, bar is never outputted, just foo
You can instead use something like:
const moreWork = async () => {
console.log('bar');
await new Promise((resolve) => {
setTimeout(resolve, 10000);
})
}
After(() => client.perform(async () => {
console.log('foo');
moreWork();
}));
But the asynchronous nature of moreWork means that the client terminates before my work is finished, so this isn't really workin for me. You can't use an await in the perform since they are in different execution contexts.
Basically the only way to get client commands to execute in after hook is my third example, but it prevents me from using async.
The 1st and 2nd examples would be great if the command queue didn't freeze and prevent execution.
edit: I'm finding more issues on github that state the browser is not available in before / after hooks: https://github.com/nightwatchjs/nightwatch/issues/575
What are you supposed to do if you want to clean up using the browser after all features have run?
Try the following
After(async () => {
await client.perform(() => {
...
});
await moreWork();
})
I want to do precompiles my server-side webpack bundles before all tests. So I decide to add file 'helper.js' and put it in mocha.opt to do it.
in helper.js:
global.assert = require('assert');
before((done) => {
startWireMockApi().then(({service, port}) => {
startFrontenEndService(port)
.then(frontEndService => {
done();
})
.catch(error => done(error));
});
});
after(() => {
console.log("after all........", global.server);
});
but I don't know why I still get the error for before all hook: "Error: Timeout of 2000ms exceeded. For async tests and hooks, ensure "done()" is called; if returning a Promise, ensure it resolves."
Can anyone help me to look at this? or do we have any other solution to do this?
Thanks very much!
I solve this problem by setting timeout to 30000(more than 2000).