Cypress Iframe Handling - Failure to interact with Button - javascript

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.

Related

How to integrate Quill-comment with React-quill?

I currently have this Code SandBox where I am trying to get React-Quill and Quill-Comment to work together so that I can let users comment on content that has been written.
Quill comment is not a react package and I am a react noob so I don't know if what I am trying to do it even possible. It appears to partially work because the toolbar add comment button registers the click event.
let commentCallback;
function commentAddClick(callback) {
setOpen(true); //show the modal
commentCallback = callback; //Appears to do nothing?
console.log("callback :>> ", callback); //Nothing is ever in the callback
console.log("commentAddClick");
}
However, the callback value doesn't appear to have or do anything. When I click the add comment button in the modal:
const commentSave = () => {
const comment = "This is a comment, forced for testing";
commentCallback(comment);
console.log("comment :>> ", comment);
//let comment = $('#commentInput').val();
commentCallback(comment);
addCommentToList(comment, currentTimestamp);
};
it throws an error that tells me
commentCallback is not a function
I am attempting to following the Vanilla JS example see line 68 here. I assume this problem is related to this warning message that spams on every keypress.
quill:toolbar ignoring attaching to nonexistent format comments-add
<button type="button" class="ql-comments-add"></button>
How do I resolve the warning message, and get the callback to work? Or, secondarily, is there another good commenting library that will work with Quill?
A working example in Vanilla JS can be found here:
https://github.com/nhaouari/quill-comment/tree/master/example/quill-comment-test
I'd like to replicate this in React.
The library you are referring to says that callback function will be null when nothing is selected in the editor. So, you need to select some text in the editor for the callback function to work.

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.

testcafe: Check for something after every click

I am testing a web app that renders some of its errors as HTML and gives no other indication that a problem occurred. After every click, I would like to see if a .error element exists.
I know I could manually add this after every click, but it's going to obfuscate my test and it will be easy to forget some instances. Is there a way to tell testcafe that a certain condition should make the test fail, even if I'm not explicitly checking for it?
I did something like this:
const scriptContent = `
window.addEventListener('click', function () {
if($('.error').length > 0) {
throw new Error($('.error').text());
}
});
`;
fixture`Main test`
.page`../../dist/index.html`.clientScripts(
{ content: scriptContent }
);
This injects a script onto the page I am testing. After every click, it uses jQuery to see if an error class exists. If it does, it throws an error on the page I'm testing. Testcafe reports the message of that error.
I'm hoping there's a better way.

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)

Meteor Accounts.onLogin infinite loop

In the Meteor forums I read that it is suggested to put Meteor.logoutOtherClients inside Accounts.onLogin(). Although this works, there is a problem to it, and that is the Accounts.onLogin() gets called multiple times when there are multiple TABS (not browsers) opened. Is this the expected output?
Here is my code below:
Accounts.onLogin(() => {
console.log('onLogin called')
Meteor.logoutOtherClients((error) => {
if (error) {
console.log(`error: ${error.error}`)
}
})
// Some Meteor Method calls here
alert('Welcome User!')
})
Another problem is that I got method calls in the same Accounts.onLogin() block and it gets called every time.
meteor#1.4.2.6
accounts-base#1.2.17
Question
How should I prevent this infinite calls from happening?
If I can't prevent this, where should I dispatch method calls when user logs in? Because obviously if I put it inside this code block it causes the dispatches to get called infinitely and that alert gets fired infinitely.
You can also see the details reported here: https://github.com/meteor/meteor/issues/8669
This is a confirmed bug #8669. So my workaround is I created a manual token for the user instead of using the default from accounts-base. I also handled the checking manually so basically getting rid of "magic" Meteor offers.

Categories

Resources