Cypress test stops to execute in the middle of code - cypress

Here is my code:
context('Actions', () => {
beforeEach(() => {
cy.visit('http://www.staging.365dropship.com')
cy.contains('Login').click()
cy.wait(10000)
.get('#fancybox-frame').then(($iframe) => {
const $body = $iframe.contents().find('body')
cy.wrap($body).find('#login-username').type('testtust100#gmail.com')
cy.wrap($body).find('#login-password').type('1234567')
cy.wrap($body).find('button').click()
})
})
it('continue', () => {
cy.wait(10000)
cy.url().should('include', '/owner/index')
cy.get('a.icon-sale').click()
cy.wait(10000)
})
})
On the first wait after login test stops execution with no reason and no errors in logs... Can somebody help me where I make a mistake?
that is the last screen I caught before test stops, the wait is not complete
after I got this

The mentioned test works fine at my place. I guess the credentials are known invalid, but it fails at the point where I expected it to fail:

Related

Blank page after running Cypress tests

Whenever I run a new cypress test, the page that is supposed to show the UI is blank. Even when I click on each part of each test it remains blank. Please see image below.
image
Cypress package version: 10.4.0
Node v16.16.0
Code:
describe("home page", () => {
beforeEach(() => {
cy.visit("http://localhost:3000")
})
context("Hero section", () => {
it("the h1 contains the correct text", () => {
cy.getByData("hero-heading").contains(
"Testing Next.js Applications with Cypress"
)
})
it("the features on the homepage are correct", () => {
cy.get("dt").eq(0).contains("4 Courses")
cy.get("dt").eq(1).contains("25+ Lessons")
cy.get("dt").eq(2).contains("Free and Open Source")
})
})
context("Courses section", () => {
it("CourseL Testing Your First Next.js Application", () => {
cy.getByData('course-0')
.find('a')
.eq(3)
.contains('Get started')
})
})
})
/// <reference types="cypress" />
Cypress.Commands.add('getByData', (selector) => {
return cy.get(`[data-test=${selector}]`);
});
I faced the same issue in Cypress version 12.0.0 and I solved it by adding this configuration to cypress.config.js
testIsolation: false,
Try adding 's' to http; this might solve that else here is similar issue reported which might give you clue to your problem https://github.com/cypress-io/cypress/issues/4235
You might have put the it() describe() statements in the wrong place. Try creating the most simple test file possible or better still use an example test that cypress provides strip it down and continue to test it until it is barebones.
I have a "solution" in my tests - it seems that the it steps lose the URL.
Remove all the it steps:
describe('Register Native', () => {
// it("Verify1", () => {
: a
// })
// it("Verify2", () => {
: b
// })
})
Now I have a structure like this (only one it step):
describe('Registrer Native', () => {
it('Whole test- Without IT parts', () => {
: a
: b
: c
})
})
It is not an optimal solution as I now have a long test without intermediary it sections.

Cypress assertion fails but test is marked passed (green checkbox) in the Cypress UI. Is this expected?

It looks like Cypress tests are marked with a green checkbox even if an assertion fails. Has anyone encountered this?
I tried adding Cypress.on("fail", (err, runnable) => { return false; }); to the index.js file in cypress/integration/support folder and this didn't help.
Here is a simple test showing the problem. If you run the test you should see a green checkbox in the Cypress runner but if you expand the test to look at each step you will see the failed assertion in red:
describe('fail intentionally', () => {
it('should fail when some random element that does not exist on page is asserted', () => {
cy.visit('https://www.google.com');
cy.get('[name=btnK]').should('be.visible');
cy.get('[name=totallyfake12345').should('be.visible') //expected to not be on the page
});
});
image showing Cypress UI view after running above test
For me, the line Cypress.on("fail", (err, runnable) => { return false; }) actually causes the problem.
If I comment it out, the test fails as expected
Just shows why it's dangerous to apply this event modifier.
If there is an application error to avoid, it's better to apply it once only
Cypress.once("fail", (err, runnable) => { return false; })

Cypress: How to pass if its() function DOES timeout

I have a test where I want to know that a window property is NOT set after an arbitrary timeout period.
So, in pseudo-code:
cy.window().its('msg_1', {
timeout: 3000
}).should.timeoutIn3000
In other words, the test passes if the 3000ms timeout is reached. If the window property msg_1 turns up before 3000ms, the test should fail.
Is that possible? I am probably missing the obvious here.
Thanks
The strategy might be test, wait, test again.
it('does not see the message', () => {
cy.visit('http://example.com').then(win => {
setTimeout(() => {
win.msg_1 = 'hi'
}, 1000)
})
cy.window().then(win => expect(win.msg_1).to.eq(undefined)) // passes
cy.wait(3000)
cy.window().then(win => expect(win.msg_1).to.eq(undefined)) // fails
})
Ok, following #EQQ's helpful reply I found the following works:
// This will pass if it is not there
cy.window().then(win => expect(win.msg_1).to.eq(undefined))
// Wait for the timeout and test again
cy.window().wait(3000).then(win => {
expect(win.msg_1).to.eq(undefined)
})
and as a custom command:
/**
* Use to test that a window property does NOT turn up
* within the specified time period
*/
Cypress.Commands.add("notIts", (prop, timeout) => {
cy.window().then(win => expect(win[prop]).to.eq(undefined))
cy.window().wait(timeout).then(win => {
expect(win[prop]).to.eq(undefined)
})
});
used like:
cy.notIts('msg_1', 3000)
Maybe "notIts" is not a good name for it but anyway, this works for me.
Thanks!
Murray

How to wait for the api call to finish and then check if element present using cypress?

i am new to cypress and i am trying to check if the element exists on a page once the api call is finished.
i do a http post to url 'things/thing1' and once this api finishes i want to check if span element is present on page.
i have tried something like below.
const setUp = () => {
cy.apiPatchSomethings(something1)
.then(() => {
cy.reload();
});
}
describe('Suite name', () => {
before(() => {
setUp();
});
it('test case', () => {
cy.contains('span');
}
});
the above code doesnt work. even before span element is seen on page it checks for span element.
if i use cy.wait(10000) like below it works
it('test case', () => {
cy.wait(10000);
cy.contains('span');
});
but i dont want to use cy.wait. is there some other way to solve this. could someone help me with this. thanks.
Cypress command cy.contains() when called with a single argument is looking for content,
Syntax
cy.contains(content)
cy.contains(content, options)
cy.contains(selector, content)
cy.contains(selector, content, options)
but I'm guessing you are looking for a span element, so use
cy.get('span')
or
cy.contains('span', 'my-content-in-span')
Assuming that's not the problem, just some arbitrary sample code...
Your can modify the setup function to return a promise, in order to wait for the reload.
const setUp = () => {
return cy.apiPatchSomethings(something1) // need a return here
.then(() => {
return new Cypress.Promise(resolve => { // inner return also
cy.reload()
resolve(true) // resolve will signal reload is finished
})
});
}
Because setup() is invoked inside before() Cypress will wait for the promise to resolve before proceeding.
Please don't add extra waits or timeouts, which is too often suggested. This will only lead to flaky tests.
Note if you don't mind ditching the setup() function, it becomes a lot simpler
describe('Suite name', () => {
before(() => {
cy.apiPatchSomethings(something1)
.then(() => cy.reload() ); // all commands here will be completed
// before the tests start
});
it('test case', () => {
cy.contains('span', 'my-content-in-span');
}
});
1.You can wait for span to be visible. The default timeout that cypress provides is 4 seconds.
cy.contains('span').should('be.visible')
2.If you want to give a custom timeout(eg. 10 sec) specific to this command, you can use:
cy.contains('span', { timeout: 10000 }).should('be.visible')
3.If you want to increase the timeout globally you mention this in your cypress.json file:
"defaultCommandTimeout": 10000
and, then just use:
cy.contains('span').should('be.visible')
Now, all your commands will have a default timeout for 10 seconds.

Cypress: changing the code while running crashes my tests (request aborted)

I'm testing an Angular App with Cypress.
I'm running my test with the Cypress dashboard, that I open using this command:
$(npm bin)/cypress open
I'm calling an API with my test: it works.
But when I change my code, Cypress will rerun the code which will cause my first (and only my first test) to fail. The request calling the API is aborted.
The only way to make it work again is to manually end the process, then start it again.
Has anyone got an idea what is causing this strange behaviour?
Here is my test code:
beforeEach(() => {
cy.visit('/');
cy.server();
cy.route('POST', `myUrl`).as('apiCall');
});
it('should find a doctor when user searches doctor with firstName', () => {
cy.get('#myInput').type('foo');
cy.get('#submitButton]').click();
cy.wait('#apiCall').then((xhr) => {
expect(xhr.status).to.eq(200);
});
});
You can prepare XHR stub like this:
describe('', () => {
let requests = {}; // for store sent request
beforeEach(() => {
cy.server({ delay: 500 }); // cypress will answer for mocked xhr after 0.5s
cy.route({
url: '<URL>',
method: 'POST',
response: 'fixture:response',
onRequest: ({ request }) => {
Object.assign(requests, { someRequest: request.body }); // it has to be mutated
},
});
});
And then in test:
it('', () => {
cy
.doSomeSteps()
.assertEqual(requests, 'someRequest', { data: 42 })
});
There is 2 advantages of this solution: first 0.5s delay make test more realistic because real backend doesn't answer immediately. Second is you can verify if application will send proper payload after doSomeActions() step.
assertEqual is just util to make assertion more readable
Cypress.Commands.add('assertEqual', (obj, key, value) =>
cy
.wrap(obj)
.its(key)
.should('deep.equal', value)
);

Resources