Cypress command timeout of '10000ms' exceeded - javascript

Getting started with Cypress, I'm noticing my test fails about passing:
describe('Sessions Page', () => {
it('Loads', () => {
// Set up alias
cy.server()
.route('POST', '/graphql')
.as('graphql');
// Visit site
cy.visit('/', { timeout: 30000 })
.wait('#graphql')
.its('Status')
.should('be', 200);
});
});
When I run this, it passes, then after a few seconds it fails.
I see this output:
Another thing I found strange is that the test says Passed immediately but it's still waiting for the route to resolve:

Related

Child process not killed - Node js ( inside Electron js app, windows)

I am trying to stop this command after 4 seconds, but it doesn't stop the child-process
(Running in an electron-js app, windows )
child = child_process.spawn("ping google.com -t", {
encoding: 'utf8',
shell: true
});
child.stdout.on('data', (data) => {
//Here is the output
data=data.toString();
console.log(data)
});
setTimeout(function() {
console.log('Killing Your child', child.pid);
child.kill()
}, 4 * 1000);
the timeout runs after 4 seconds, it logs the message but never stops the process
I tried using tags inside the kill() like "SIGINT" or "SIGKILL"
I tried running without the timeout too...
By looking at the official documentation for child process I have slightly modified your provided example to a bare minimum of what still seems to work for me. Please note that the ping -t flag requires an argument which you didn't provide.
The following worked for me (the program exits after 4 pings) on Node LTS (16.15.1) and the latest version (18.4.0):
const { spawn } = require('child_process');
const child = spawn("ping", ['www.google.com'], {});
child.stdout.on('data', (data) => { console.log(data.toString()); });
setTimeout(() => {
console.log('Killing Your child', child.pid);
child.kill();
}, 4000);
shell: true doesn't work with .kill()
as you can see in the answer from this post:
Try to kill a spawn process with shell true and detached true nodejs
I needed to replace:
child.kill()
with
child_process.spawn("taskkill", ["/pid", child.pid, '/f', '/t']);

How pass a login form with CYPRESS?

I manage to run CYPRESS without any worries on a site without authentication.
But on an intranet, I can't identify myself. I must to log in before.
Here is my code:
describe('home', () => {
it('home accessible', () => {
cy.visit('/')
})
//We fill the login FORM
it('User Field', () => {
cy.get('input#user')
.type('login')
})
it('User pass', () => {
cy.get('input#pass')
.type('mot de passe')
})
it('check consent', () => {
cy.get('input#permalogin')
.click({ force: true })
})
it('submit', () => {
cy.get('input.btn.btn-primary')
.click()
})
//the form is submit, we can visit a page
it('autre page!!', () => {
cy.visit('/luniversite/page-2',{ timeout: 30000 })
})
//We check the title of the page, we should be on the page 2
it('titre page 2', () => {
cy.title().should('eq', 'page 2: INTRANET)
})
CYPRESS and the CYPRESS video show me that I am blocked on the authentication page.
The test on the title of the page is not correct, I don't access page-2. I stay on the first page for log in.
First thing's first: This appears to be one test, but you are specifying multiple it() functions, which is breaking it up into multiple tests, which is not what you want. You will want to restructure your test like this:
describe("home", () => {
it("home accessible", () => {
cy.visit("/");
//We fill the login FORM
cy.get("input#user").type("login");
cy.get("input#pass").type("mot de passe");
cy.get("input#permalogin").click({ force: true });
cy.get("input.btn.btn-primary").click();
cy.visit("/luniversite/page-2", { timeout: 30000 });
cy.title().should("eq", "page 2: INTRANET");
});
});
With that out of the way, it's hard to know what your application is doing without more details:
1/ When executed manually, is your application authenticating properly with the provided credentials? Do you have console errors? Have you determined that the element locators you're using are actually interacting with the elements in the manner you expect?
2/ Is your test attempting to navigate to /luniversite/page-2 before authentication is complete? If so, you may want to use intercept your authentication call and wait for it to complete:
// get your authentication POST request from network tab of devtools and use that in the cy.intercept call
cy.intercept('POST', '/yourAuthenticationCallUrl').as("#authenticationCall")
// YOUR LOGIN STEPS HERE
cy.wait("#authenticationCall") //waits for the authentication call to complete before moving to the next step
cy.visit("/luniversite/page-2", { timeout: 30000 });

Looking for alternatives to cy.wait() on a flaky test in Cypress

So I have a flaky test case right now in Cypress. When the modal loads, it skips the filling out the name part but fills out everything else. Therefore, causing it to fail the first time, but on the retry, it passes. I tried adding an assertion (see below), but it does not work. I am trying to avoid adding using a wait command, but wanted to see if there are any other alternatives out there to cy.wait().
describe("Coach dealing with forms" () => {
beforeEach(() => {
loginfile.login(users.coach)
});
it("Can fill out form and submit", () => {
cy.get("#modal-button").click()
cy.get("#modal-form").should("exist")
cy.get("#form-name").type("Mike Johnson")
cy.get("#form-age").type("33")
cy.get("#form-email").type("mj09#yahoo.com)
cy.get("#submit-button").click()
}
}
There a number of ways to approach flaky tests. You can try these and check what suits best for your use case:
1.Test Retires easy and effective, just retry the execution automatically it something fails. Can be applied, globally using cypress.json or to a describe block or to a it block as well.
For it block:
// `it` test block with custom configuration
it('allows user to login', {
retries: {
runMode: 2,
openMode: 2
}
}, () => {
// ...
})
For describe block:
// Customizing retry attempts for a suite of tests
describe('User bank accounts', {
retries: {
runMode: 2,
openMode: 2,
}
}, () => {
// The per-suite configuration is applied to each test
// If a test fails, it will be retried
it('allows a user to view their transactions', () => {
// ...
}
it('allows a user to edit their transactions', () => {
// ...
}
})
2.Adding .visible and click() before writing into the name field
it("Can fill out form and submit", () => {
cy.get("#modal-button").click()
cy.get("#modal-form").should("exist")
cy.get("#form-name").should('be.visible') //making sure the name field is visible
cy.get("#form-name").click() //clicking on the name field
cy.get("#form-name").type("Mike Johnson")
cy.get("#form-age").type("33")
cy.get("#form-email").type("mj09#yahoo.com")
cy.get("#submit-button").click()
})
3.Use timeouts instead of waits
cy.get("#form-name", {timeout: 10000}).type("Mike Johnson")
4.Use cy.intercept() to wait for the XHR request to finish execution. Here I am assuming that there is some unfinished XHR request after clicking the modal button that is causing the issue. If that is not the case, you can debug your tests to find out and apply intercept accordingly.
it("Can fill out form and submit", () => {
cy.intercept('http://example.com/settings').as('getSettings') //Intercept the url that is triggered after clicking the modal button
cy.get("#modal-button").click()
cy.wait('#getSettings') //Wait till that request has finished execution
cy.get("#modal-form").should("exist")
cy.get("#form-name").type("Mike Johnson")
cy.get("#form-age").type("33")
cy.get("#form-email").type("mj09#yahoo.com")
cy.get("#submit-button").click()
})
You should add a timeout to the type() command (not to the get() command) and follow it with a should() to confirm the value has been entered.
type() and should() will both retry until they succeed.
it("Can fill out form and submit", () => {
cy.get("#modal-button").click()
cy.get("#modal-form") // .should("exist") - don't need as cy.get() does that already
cy.get("#form-name").type("Mike Johnson", {timeout: 10000}) // wait for actionability
.should('have.value', 'Mike Johnson');
cy.get("#form-age").type("33")
cy.get("#form-email").type("mj09#yahoo.com")
cy.get("#submit-button").click()
})

What is causing this jasmine test failure?

I'm working with my jasmine test suite, and I'm getting a weird error that causes the test to fail. The code works, and I've verified by debugging the tests that the values I expect are the values present, but the test fails. I get this as output:
Failed
at stack (/Users/username/code/source/client/node_modules/jasmine-core/lib/jasmine-core/jasmine.js:2200:17)
at buildExpectationResult (/Users/username/code/source/client/node_modules/jasmine-core/lib/jasmine-core/jasmine.js:2170:14)
at Spec.expectationResultFactory (/Users/username/code/source/client/node_modules/jasmine-core/lib/jasmine-core/jasmine.js:777:18)
at Spec.addExpectationResult (/Users/username/code/source/client/node_modules/jasmine-core/lib/jasmine-core/jasmine.js:450:34)
at Env.fail (/Users/username/code/source/client/node_modules/jasmine-core/lib/jasmine-core/jasmine.js:1192:25)
at next.fail (/Users/username/code/source/client/node_modules/jasmine-core/lib/jasmine-core/jasmine.js:4046:19)
This is what my tests look like
describe('the returned type', () => {
afterEach(store.clearActions);
beforeEach(done => {
mock.onPatch(url).replyOnce(200, { updated_at: moment().toISOString() });
save(4, value)(store.dispatch, store.getState)
.then(() => setTimeout(done, 750));
});
it('should have correct type', () => {
const action = store.getActions()[0];
expect(action.type).toEqual(LAST_SAVED_UPDATE);
});
});

jasmine: Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL

I have an angular service called requestNotificationChannel:
app.factory("requestNotificationChannel", function($rootScope) {
var _DELETE_MESSAGE_ = "_DELETE_MESSAGE_";
function deleteMessage(id, index) {
$rootScope.$broadcast(_DELETE_MESSAGE_, { id: id, index: index });
};
return {
deleteMessage: deleteMessage
};
});
I am trying to unit test this service using jasmine:
"use strict";
describe("Request Notification Channel", function() {
var requestNotificationChannel, rootScope, scope;
beforeEach(function(_requestNotificationChannel_) {
module("messageAppModule");
inject(function($injector, _requestNotificationChannel_) {
rootScope = $injector.get("$rootScope");
scope = rootScope.$new();
requestNotificationChannel = _requestNotificationChannel_;
})
spyOn(rootScope, '$broadcast');
});
it("should broadcast delete message notification", function(done) {
requestNotificationChannel.deleteMessage(1, 4);
expect(rootScope.$broadcast).toHaveBeenCalledWith("_DELETE_MESSAGE_", { id: 1, index: 4 });
done();
});
});
I read about the Asynchronous Support in Jasmine, but as I am rather new to unit testing with javascript couldn't make it work.
I am receiving an error :
Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL
and my test is taking too long to execute (about 5s).
Can somebody help me providing working example of my code with some explanation?
Having an argument in your it function (done in the code below) will cause Jasmine to attempt an async call.
//this block signature will trigger async behavior.
it("should work", function(done){
//...
});
//this block signature will run synchronously
it("should work", function(){
//...
});
It doesn't make a difference what the done argument is named, its existence is all that matters. I ran into this issue from too much copy/pasta.
The Jasmine Asynchronous Support docs note that argument (named done above) is a callback that can be called to let Jasmine know when an asynchronous function is complete. If you never call it, Jasmine will never know your test is done and will eventually timeout.
Even for async tests, there is a timeout that goes off in this cases, You can work around this error by increasing the value for the limit timeout to evaluate an async Jasmine callback
describe('Helper', function () {
var originalTimeout;
beforeEach(function() {
originalTimeout = jasmine.DEFAULT_TIMEOUT_INTERVAL;
jasmine.DEFAULT_TIMEOUT_INTERVAL = 1000000;
});
afterEach(function() {
jasmine.DEFAULT_TIMEOUT_INTERVAL = originalTimeout;
});
it('Template advance', function(doneFn) {
$.ajax({
url: 'public/your-end-point.mock.json',
dataType: 'json',
success: function (data, response) {
// Here your expected using data
expect(1).toBe(1)
doneFn();
},
error: function (data, response) {
// Here your expected using data
expect(1).toBe(1)
doneFn();
}
});
});
});
Source: http://jasmine.github.io/2.0/introduction.html#section-42
This error can also be caused by leaving out inject when initializing a service/factory or whatever. For example, it can be thrown by doing this:
var service;
beforeEach(function(_TestService_) {
service = _TestService_;
});
To fix it just wrap the function with inject to properly retrieve the service:
var service;
beforeEach(inject(function(_TestService_) {
service = _TestService_;
}));
import { fakeAsync, ComponentFixture, TestBed } from '#angular/core/testing';
use fakeAsync
beforeEach(fakeAsync (() => {
//your code
}));
describe('Intilalize', () => {
it('should have a defined component', fakeAsync(() => {
createComponent();
expect(_AddComponent.ngOnInit).toBeDefined();
}));
});
You can use karma-jasmine plugin to set the default time out interval globally.
Add this config in karma.conf.js
module.exports = function(config) {
config.set({
client: {
jasmine: {
timeoutInterval: 10000
}
}
})
}
This error started out of the blue for me, on a test that had always worked. I couldn't find any suggestions that helped until I noticed my Macbook was running sluggishly. I noticed the CPU was pegged by another process, which I killed. The Jasmine async error disappeared and my tests are fine once again.
Don't ask me why, I don't know. But in my circumstance it seemed to be a lack of system resources at fault.
This is more of an observation than an answer, but it may help others who were as frustrated as I was.
I kept getting this error from two tests in my suite. I thought I had simply broken the tests with the refactoring I was doing, so after backing out changes didn't work, I reverted to earlier code, twice (two revisions back) thinking it'd get rid of the error. Doing so changed nothing. I chased my tail all day yesterday, and part of this morning without resolving the issue.
I got frustrated and checked out the code onto a laptop this morning. Ran the entire test suite (about 180 tests), no errors. So the errors were never in the code or tests. Went back to my dev box and rebooted it to clear anything in memory that might have been causing the issue. No change, same errors on the same two tests. So I deleted the directory from my machine, and checked it back out. Voila! No errors.
No idea what caused it, or how to fix it, but deleting the working directory and checking it back out fixed whatever it was.
Hope this helps someone.
You also get this error when expecting something in the beforeAll function!
describe('...', function () {
beforeAll(function () {
...
expect(element(by.css('[id="title"]')).isDisplayed()).toBe(true);
});
it('should successfully ...', function () {
}
}
Don't use done, just leave the function call empty.
It looks like the test is waiting for some callback that never comes. It's likely because the test is not executed with asynchronous behavior.
First, see if just using fakeAsync in your "it" scenario:
it('should do something', fakeAsync(() => {
You can also use flush() to wait for the microTask queue to finish or tick() to wait a specified amount of time.
In my case, this error was caused by improper use of "fixture.detectChanges()" It seems this method is an event listener (async) which will only respond a callback when changes are detected. If no changes are detected it will not invoke the callback, resulting in a timeout error. Hope this helps :)
Works after removing the scope reference and the function arguments:
"use strict";
describe("Request Notification Channel", function() {
var requestNotificationChannel, rootScope;
beforeEach(function() {
module("messageAppModule");
inject(function($injector, _requestNotificationChannel_) {
rootScope = $injector.get("$rootScope");
requestNotificationChannel = _requestNotificationChannel_;
})
spyOn(rootScope, "$broadcast");
});
it("should broadcast delete message notification with provided params", function() {
requestNotificationChannel.deleteMessage(1, 4);
expect(rootScope.$broadcast).toHaveBeenCalledWith("_DELETE_MESSAGE_", { id: 1, index: 4} );
});
});
What I did was: Added/Updated the following code:
framework: 'jasmine',
jasmineNodeOpts:
{
// Jasmine default timeout
defaultTimeoutInterval: 60000,
expectationResultHandler(passed, assertion)
{
// do something
},
}
As noted by #mastablasta, but also to add that if you call the 'done' argument or rather name it completed you just call the callback completed() in your test when it's done.
// this block signature will trigger async behavior.
it("should work", function(done){
// do stuff and then call done...
done();
});
// this block signature will run synchronously
it("should work", function(){
//...
});
jasmine.DEFAULT_TIMEOUT_INTERVAL = 100000;
Keeping this in the block solved my issue.
it('', () => {
jasmine.DEFAULT_TIMEOUT_INTERVAL = 100000;
});
Instead of
beforeEach(() => {..
use
beforeEach(fakeAsync(() => {..
In my case, a timeout was cause because of a failed injection of a service with providedIn: 'root'. It's not clear why injection failed, nor why there was no early error if there is apparently no instance of provider available.
I was able to work around it by manually providing a value:
TestBed.configureTestingModule({
declarations: [
// ...
],
imports: [
// ...
],
providers: [
// ...
{ provide: MyService, useValue: { /* ... */ } },
]
}).compileComponents();
I have caught the same error because I used the setTimeout function in the component. Example:
ngOnInit(): void {
this.changeState();
}
private changeState(): void {
setTimeout(() => this.state = StateEnum.IN_PROGRESS, 10000);
}
When I changed the timeout from 10000ms to 0 or less than 5000ms (DEFAULT_TIMEOUT_INTERVAL), all tests were passed.
In my case, I was not returning the value from the spy method, hence facing error,
mainMethod(args): Observable<something>{
return nestedMethod().pipe();
}
Your Test should like below,
it('your test case', (done: DoneFn) => {
const testData = {}; // Your data
spyOn(service, 'nestedMethod').and.returnValue(of(testData));
const obxValue = service.mainMethod('your args');
obxValue.pipe(first()).subscribe((data) => {
expect(data).not.toBeUndefined();
done();
});
});
If you have an argument (done) in the it function try to remove it as well it's call within the function itself:
it("should broadcast delete message notification", function(/*done -> YOU SHOULD REMOVE IT */) {
requestNotificationChannel.deleteMessage(1, 4);
expect(rootScope.$broadcast).toHaveBeenCalledWith("_DELETE_MESSAGE_", { id: 1, index: 4 });
// done(); -> YOU SHOULD REMOVE IT
});

Categories

Resources