How to run next Cypress cy commands while other is still processing? - javascript

I am maintaining a react project that uses Cypress. Cypress by default is asynchronous. How to perform next cy commands while the above cy command is still processing?
Example:
cy.get('showDialog').click() // Instantly closes due to some react states
cy.get('showDialogCloseButton').click() // still loading looking for showDialogCloseButton which eventually fails
// need to execute this again to show dialog and complete above cy command:
cy.get('showDialog').click()
However, the last command can't be executed since it needs the above command to be finished (which resulted to failure)

Using cy.wait() after the cy.get('showDialogCloseButton').click()
ex:
cy.get('showDialogCloseButton').click();
cy.wait(1000);
With this 3rd command will execute after 1s, always
but will make your test suite unnecessarily slow.
So then you can try by increase the timeout(s)
cy.get('showDialog',{timeout: 30000}).click({timeout: 30000});
This command will only fail after 30 seconds of not being able to find the object, or, when it finds it, 30 seconds of not being able to click it.
You can try your own timeout
So you can easily do that with validate also,
cy.get('showDialog', { timeout: 30000 }).should('be.visible').then(() => {
cy.get('showDialog').click();
})

Related

Cypress error when testing nested iframes in headless mode - race condition

I am testing a web app and the test runs reliably in headed mode (cypress open) but has errors in headless mode (cypress run), so it's likely a race condition that I cannot resolve. The error message is:
[36819:0223/163815.745047:ERROR:system_services.cc(34)] SetApplicationIsDaemon: Error Domain=NSOSStatusErrorDomain Code=-50 "paramErr: error in user parameter list" (-50)
This error is mentioned again when Cypress creates a video of the incident:
- Started processing: Compressing to 32 CRF
2022-02-23 17:00:19.700 Cypress Helper[37571:416134] In -[NSApplication(NSQuietSafeQuit) _updateCanQuitQuietlyAndSafely], _LSSetApplicationInformationItem(NSCanQuitQuietlyAndSafely) returned error -50
- Finished processing: /Users/malte.wirz/Documents/iframes-cypress-issue/cypress/videos/iframe-github.js.mp4 (3 seconds)
I created a demo repository here. To reproduce, clone it, run yarn to install, and yarn cypress:run. The test does pass, but with the error mentioned above.
I assume that the error stems from accessing the nested iframes and I tested 5 different approaches so far, but to no avail. I especially made sure that the function getIframeBody waits until each iframe and the requested element is ready. The error also creates a video, but you can only see the successful run, the error message is not visible there.
Any help on how to debug this further is much appreciated.
describe('Testing Iframe within Iframes', () => {
it('Visits the iframe website and accesses the iframe within the iframe', () => {
const getIframeBody = (iframeSelector, elementSelectorInIframe) => {
return cy
.get(iframeSelector)
.its('0.contentDocument.body', {timeout: 30000})
.should((body) => {
expect(Cypress.$(body).has(elementSelectorInIframe).length).gt(0)
})
.then(cy.wrap)
}
// Visiting the page index.html and getting iframe A
cy.visit('index.html').contains('XHR in iframe')
getIframeBody('iframe[data-cy="bankid"]', 'iframe[src="https://tools.bankid.no/bankid-test/auth"]').as('iframeA')
cy.get('#iframeA').within(() => {
getIframeBody('iframe[src="https://tools.bankid.no/bankid-test/auth"]', 'iframe[src^="https://csfe.bankid.no/CentralServerFEJS"]').as('iframeB')
cy.get('#iframeB').within(() => {
getIframeBody('iframe[src^="https://csfe.bankid.no/CentralServerFEJS"]', 'input[type="tel"]').as('iframeC')
// Now we are in the right place and it finds the correct input element.
// However, normal cypress command .type() fails and we have to use library cypress-real-events,
// which provides an event firing system that works literally like in puppeteer
cy.get('#iframeC').find('input[type="tel"]').should('be.visible').realType('12345678912')
// But for the button below, this library now doesn't help anymore:
// "Failed to execute 'getComputedStyle' on 'Window': parameter 1 is not of type 'Element'."
// This was solved by using {scrollBehavior:false}.
cy.get('#iframeC').find('button[type="submit"]').should('be.visible').first().realClick({scrollBehavior:false})
})
})
})
})
I got some feedback that the above "ERROR:system_services.cc(34)" is not critical and does not cause flaky or unsuccessful tests, therefore there are no action points.

Non of the webdriverio methods work to wait until an element is shown using Appium & WebDriverIO (JavaScript)

I am trying to write a test case use in JavaScript with webdriverio (using appium server) for a native android app.
My test case requires me to log in the app, and after logging (which takes 3-4 seconds) I should click a button (element). I tried all of the WebDriverIO APIs like waitForDisplayed, isDisplayed(), non of them work, most the time the error message is that :
TypeError: client.element(...).waitForDisplayed is not a function
at Context.<anonymous> (test-auto-obi-copy.js:142:14)
at processImmediate (internal/timers.js:439:21)
at process.topLevelDomainCallback (domain.js:130:23)
Here is the WebDriverIO Documentation for waitForDisplayed https://webdriver.io/docs/api/element/waitForClickable.html
My code looks like this:
it("should press the profile button", function () {
return client
.element('android=new UiSelector().resourceId("com.example.dev:id/nav_graph_profile")')
.waitForDisplayed(undefined, true)
.click('android=new UiSelector().resourceId("com.example.dev:id/nav_graph_profile")')
.then( function() {
//whatever
})
})
The login test completes succesfully, but after the LOG-IN button is pressed I want to make my test suite "sleep" until the next page loads, to achieve this I was trying to wait until this particular Profile button (element) becomes available, but it seems impossible to wait for it.
Can anyone suggest me what to do in this case, how can I wait?
WebDriverIO changed the names of some of their functions when moving from v4 -> v5 .waitForDisplayed() was one of them, as seen in the changelogs.
WebdriverIO v4 -> .waitForVisible()
WebdriverIO v5 -> .waitForDisplayed()
There's a fair few functions that changed names slightly, so it's worth a look - Additionally, the Docs for v4 still exist though are a little harder to search - Here is the entry for .waitForVisible()
Also, by passing undefined as the first parameter, your delay will only wait for the default 500ms. You'll probably want something like this instead
.waitForDisplayed(5000, true)

Determine an empty event loop

Is there a way to determine if there is an empty event loop?
For example,
// Example 1
setInterval(() => console.log("hi"), 1000);
// event loop is not empty
// Example 2
console.log("hi");
// event loop is now empty
Based on your comment:
I want to exit a process once the event loop is empty
Node.js got you covered. Node process will exit automatically when the event-loop is empty.
If you opened this question because your tests (using Jest) were hanged for some reason, it means that the event loop was not empty at the end of all the afterEach and afterAll hooks, so if you are running a single test-file, Jest will usally hang. If you are running multiple tests files, jest will print an error which indicated that Jest forced to (not-gracefully) close the node-process of one of the test-files.
To fix that, make sure you don't forget to await to any promise, close all conections and clear all timeouts.

Webdriver.waitUntil doesn't work as expected

I'm using wedriverio 4.5:
./node_modules/.bin/wdio -v
v4.5.2
I need to wait until some element exists and if it doesn't exist handle this situation.
for example:
let element = browser.element('.unexisting');
browser.waitUntil(
function () {
return element.isExisting();
},
1000,
'Element is not found.'
);
But if element doesn't exist on the page, webdriver marks my test as failed and shows message: 'Timeout of 10000ms exceeded. Try to reduce the run time or increase your timeout for test specs (http://webdriver.io/guide/testrunner/timeouts.html); if returning a Promise, ensure it resolves.'
How can I handle this situation?
I tried try-catch block, but anyway I see same message about timeout and failed test.
I tried element.waitForExist() but behavior is the same
I tried to use error handler (but it doesn't help)
browser.on('error', function(e) {
console.log ('handle browser error');
})
Why don't I see my message 'Element is not found.'?
Thanks!
Make sure your waitForXXX command doesn't take longer than your spec timeout. If it does increase your spec timeout, in your case mochaOpts.timeout. See more here http://webdriver.io/guide/testrunner/timeouts.html#Framework-related-timeouts

Selenium/Chromedriver: Can't find element in iframe

I'm using Selenium/Chromedriver via Protractor. I'm switching to an iframe, waiting for the contents to load, and then planning to manipulate elements inside it. But it's never recognizing that the contents have loaded.
browser.driver.switchTo().frame("myView");
browser.driver.wait(function() {
return browser.driver.isElementPresent(by.id("myDiv"))
.then(function (isPresent) {
return isPresent;
});
}, 20000, "Taking too long to load!");
myDiv is definitely present within 20 seconds, but wait() times out.
I've tried switching to using browser.driver.findElement(), but got the same result.
I've made sure I'm updated to Chromedriver 2.21 (which fixed an earlier error).
Any ideas what else I could be doing wrong?
ETA per comment: This is all I'm getting for an error log...
Message:
Error: Taking too long to load!
Wait timed out after 20069ms
Stacktrace:
Error: Taking too long to load!
Wait timed out after 20069ms
==== async task ====
Taking too long to load!
at /Users/me/Documents/My-Test/specs/myWorkflow.js:82:20
==== async task ====
at [object Object].<anonymous> (/Users/me/Documents/My-Test/specs/myWorkflow.js:79:14)
==== async task ====
Asynchronous test function: it()
Error
at [object Object].<anonymous> (/Users/me/Documents/My-Test/specs/myWorkflow.js:7:5)
at Object.<anonymous> (/Users/me/Documents/My-Test/specs/myWorkflow.js:5:1)
I've gotten around similar issues by adding a sleep statement, instead of using a wait loop. In c# I would use thread.sleep(20000); for a 20 second wait. Most of mine are in the 1 to 5 second range.
To clarify: I'm suggesting removing the loop that is he is using to check for the element and instead using a simple sleep type command then interacting with the element.
In Selenium using C# I have used the following statement to provide a fixed wait time while an element loads before clicking the element. This element happens to be a link, but it can be any element
//sleep time so UX can load
Thread.Sleep(3000);
//open the new form
By newButton = By.XPath("/dummy/xpath");
IWebElement button = driver.FindElement(newButton);
button.Click();

Categories

Resources