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.
Related
I am trying to E2E test an auth flow with Cypress that includes a third party method called BankID. BankId is integrated through three nested iframes that I can successfully access. However, when I type into the input field via cy.type('12345678912'), BankId does not register this as trusted events and never unlocks the submit button with the arrow.
According to this issue here, Cypress does not intend to support native browser events and suggests to use the package cypress-real-events. When using this via cy.realType('12345678912'), it actually succeeds in unlocking the submit button. However i can never successfully click the submit button, neither with .click() or even the package method .realClick().
The error is: "Failed to execute 'getComputedStyle' on 'Window': parameter 1 is not of type 'Element'."
I uploaded a sample repository with an minimal testing version here.
Any feedback or hints would be greatly appreciated :)
Here is the relevant code:
/// <reference types="cypress" />
import { skipOn } from '#cypress/skip-test'
describe('Recipe: blogs__iframes', () => {
skipOn('firefox', () => {
it('do it more generically', () => {
const getIframeBody = (identifier) => {
return cy
.get(identifier)
.its('0.contentDocument.body')
.should('not.be.empty')
.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"]').as('iframeA')
cy.get('#iframeA').within(() => {
getIframeBody('iframe[src="https://tools.bankid.no/bankid-test/auth"]').as('iframeB')
cy.get('#iframeB').within(() => {
getIframeBody('iframe[src^="https://csfe.bankid.no/CentralServerFEJS"]').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'."
cy.get('#iframeC').find('button[type="submit"]').should('be.visible').first().realClick()
})
})
})
})
})
I also posted this problem on https://github.com/dmtrKovalenko/cypress-real-events/issues/226 and got an answer there:
Using .realClick({ scrollBehavior: false }); solved the issue.
The problem is if the webapp is not scrolling as expected, therefore leading to Cypress not finding the element. In my case, i made the iframe wider to avoid needing to scroll and the issue was still there, but the workaround solved it anyway.
I'm currently using TestCafe for some e2e tests. I've run into the following error
1) - Error in Role initializer -
A JavaScript error occurred on "http://localhost:3000/".
Repeat test actions in the browser and check the console for errors.
If you see this error, it means that the tested website caused it. You can fix it or disable tracking JavaScript errors in TestCafe. To do the latter, enable the "--skip-js-errors" option.
If this error does not occur, please write a new issue at:
"https://github.com/DevExpress/testcafe/issues/new?template=bug-report.md".
JavaScript error details:
ResizeObserver loop limit exceeded
No stack trace available
A bit of research suggests that the ResizeObserver loop limit exceeded issue is a benign error.
However, it causes my test to fail. Is there any way I can ignore this specific error without using the --skip-js-errors flag, as I would prefer to not ignore all JavaScript errors because of this one issue
As far as I understand, this error occurs when ResizeObserver cannot deliver all observations within a single animation frame. A person who is the author of the ResizeObserver specification assures that it can be safely ignored: ResizeObserver loop limit exceeded
Chrome and Firefox don't display it by default. You can only catch it when you set an explicit onerror handler:
window.onerror = e => console.log(e);
You can see that this error is reproduced on the Google Sign In page without TestCafe. I added an onerror handler to the page and got ResizeObserver loop completed with undelivered notifications. in Firefox and ResizeObserver loop limit exceeded in Chrome.
As a workaround, you can specify the --skip-js-errors flag when starting TestCafe. I admit that it's not the best approach since you will suppress all Javascript errors on a tested page.
A more reliable way is to add a global window error handler explicitly in your tests via client scripts:
import { Selector, t } from 'testcafe';
// Constants
const gmailEmailInput = Selector("#identifierId");
const gmailNextButton = Selector(".CwaK9");
const gmailPasswordInput = Selector("input[type='password']");
const explicitErrorHandler = () => {
window.addEventListener('error', e => {
if(e.message === 'ResizeObserver loop completed with undelivered notifications.' ||
e.message === 'ResizeObserver loop limit exceeded') {
e.stopImmediatePropagation();
}
})
}
fixture("Gmail login test")
.clientScripts({ content: `(${explicitErrorHandler.toString()})()` });
test("Not trigger JS error when logging in to Gmail", async testController => {
await testController
.navigateTo("https://mail.google.com")
.typeText(gmailEmailInput, "someuser#gmail.com")
.click(gmailNextButton)
.typeText(gmailPasswordInput, "password")
});
I copypasted the workaround from here.
i tried to test this simple code
type Url = string
it('loads examples', () => {
const url: Url = 'https://www.ebay.com/'
cy.visit(url)
cy.get('input[type="text"]').type('book')
cy.get('#gh-btn').click();
})
then I faced this error
how can I solve it
Try adding this in support/index.js:
import './commands'
Cypress.on('uncaught:exception', (err, runnable) => {
// returning false here prevents Cypress from failing the test
return false
})
This should avoid the uncaught:exception in the click() method.
The accepted answer will cause Cypress to ignore all uncaught exceptions in the application. Generally, when these come up it means you found a bug in your app and should fix it.
Binding to the global Cypress object causes the event to stay bound for your entire test run. Usually, this isn't what you want.
If you actually need to ignore the exceptions though, you should be binding the event on the cy object so it's only persisted for the single test it's used in.
it('my test', () => {
cy.once('uncaught:exception', () => false);
// action that causes exception
cy.get('body').click();
});
I got Same Issue like this
Cypress Error
The following error originated from your application code,
not from Cypress. >
Cannot read properties of null (reading 'textContent')
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
No Need to worry about this.
Just paste this code to your index.js file :)
import './commands'
Cypress.on('uncaught:exception', (err, runnable) => {
// returning false here prevents Cypress from
// failing the test
return false
})
Actually, if you click in the Learn more link that comes with the error, you'll get everything you need.
https://docs.cypress.io/guides/references/error-messages#Uncaught-exceptions-from-your-application
Quoting others:
won't this answer ignore all errors thrown by the application?
The accepted answer will cause Cypress to ignore all uncaught exceptions
That is true.
Also, #DJSDev did not work for me when using Cypress v10.0.3.
The aforementioned link provides a working alternative:
it('is doing something very important', (done) => {
// this event will automatically be unbound when this
// test ends because it's attached to 'cy'
cy.on('uncaught:exception', (err, runnable) => {
expect(err.message).to.include('something about the error')
// using mocha's async done callback to finish
// this test so we prove that an uncaught exception
// was thrown
done()
// return false to prevent the error from
// failing this test
return false
})
// assume this causes an error
cy.get('button').click()
})
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)
When I run Cypress with vue-cli-service test:e2e --headless some tests inside a register request callback fail:
whereas normally when run in browser (vue-cli-service test:e2e) they pass:
it('Submit WITHOUT promo code', () => {
cy.server();
cy.route({method: 'POST', url: 'api/register'}).as('register');
cy.get('.thz-items-loading').should('not.be.visible');
cy.get('#btn-submit').should('not.be.disabled');
cy.get('iframe[name^="__privateStripeFrame"]').then(($iframe) => {
const $body = $iframe.contents().find('body');
cy.wrap($body).find('input:eq(1)').click({force: true}).clear();
cy.wrap($body).find('input:eq(1)').type('4000000000009979'); // stolen card
cy.get('#btn-submit').click(); // SUBMIT FORM
cy.wait('#register').then(xhr => {
cy.contains('#card-errors', 'Your card was declined.');
// cy.get('.thz-items-loading').should('not.be.visible'); // FAILS
// cy.get('.thz-items-loading').to.have.style('display', 'none'); // FAILS
cy.get('#btn-submit').should('not.be.disabled'); // FAILS
(...)
});
return null;
});
(...)
Stack trace:
1) Trial registration form Submit WITHOUT promo code:
CypressError: Timed out retrying: expected <button#btn-submit.thz-button.thz-radius-50.thz-btn-border-2.thz-align-center.thz-ff-g-hind-vadodara-600> not to be 'disabled'
at Object.cypressErr (https://localhost:8000/__cypress/runner/cypress_runner.js:82944:11)
at Object.throwErr (https://localhost:8000/__cypress/runner/cypress_runner.js:82909:18)
at Object.throwErrByPath (https://localhost:8000/__cypress/runner/cypress_runner.js:82936:17)
at retry (https://localhost:8000/__cypress/runner/cypress_runner.js:76454:16)
at https://localhost:8000/__cypress/runner/cypress_runner.js:68529:18
at tryCatcher (https://localhost:8000/__cypress/runner/cypress_runner.js:131381:23)
at Promise._settlePromiseFromHandler (https://localhost:8000/__cypress/runner/cypress_runner.js:129399:31)
at Promise._settlePromise (https://localhost:8000/__cypress/runner/cypress_runner.js:129456:18)
at Promise._settlePromise0 (https://localhost:8000/__cypress/runner/cypress_runner.js:129501:10)
at Promise._settlePromises (https://localhost:8000/__cypress/runner/cypress_runner.js:129576:18)
at Async._drainQueue (https://localhost:8000/__cypress/runner/cypress_runner.js:126305:16)
at Async._drainQueues (https://localhost:8000/__cypress/runner/cypress_runner.js:126315:10)
at Async.drainQueues (https://localhost:8000/__cypress/runner/cypress_runner.js:126189:14)
at
Following lines inside cy.wait('#register') callback should pass in headless mode:
cy.get('.thz-items-loading').should('not.be.visible');
cy.get('.thz-items-loading').to.have.style('display', 'none');
cy.get('#btn-submit').should('not.be.disabled');
Looks like the timeout happens because elements #btn-submit and .thz-items-loading are not reachable in #register callback, even though in both cases they exist in DOM, but why? They are reachable before the request just fine.
I'm running Cypress 3.2.0 from a project created with vue-cli on Windows 10. Tested app is not a part of the project, is hosted elsewhere and is a static html page. Headless browser is Electron 59.
It turns out that Electron browser silently fails at executing newer syntax like Promises, that's why code in resolved Promise's then() callback which was supposed to change display property of .thz-items-loading and #btn-submit was never executed and tests expecting that change never passed.
Adding babel's polyfills before main.js of tested APP fixed this issue:
<script src="../../node_modules/#babel/polyfill/dist/polyfill.min.js"></script> <!-- or copy to root dir in build process -->
<script src="./main.js"></script>
This fixed it for me:
"experimentalFetchPolyfill": true