Can't click on an element that is overlapped by another element using (sypress framework) - cypress

I want to click on the element
cy.visit('https://test.com:1111/')
cy.get('button').click()
cy.contains('Configuration').click()
cy.get('ant-tabs-tab').contains('Blocks').click()
but this element is overlapped by another element with CypressError:
Timed out retrying: cy.click() failed because this element:
<div role="tab" aria-disabled="false" aria-selected="false" class=" ant-tabs-tab"> Blocks </div>
is being covered by another element:
<ul class="ant-menu menu ant-menu-dark ant-menu-root ant-menu-horizontal" role="menu" style="line-height: 64px;">...</ul>
Fix this problem, or use {force: true} to disable error checking.

You can use {force: true} with click() to disable error checks:
cy.visit('https://test.com:1111/')
cy.get('button').click({force: true})
cy.contains('Configuration').click({force: true})
cy.get('ant-tabs-tab').contains('Blocks').click({force: true})

Related

Playwright: Click button does not work reliably (flaky)

1. Initial post
I know that Playwright has auto-waiting.
I have a test where sometimes click works, sometimes does not. Below is the code.
import { test, expect } from '#playwright/test';
test('test', async ({ page }) => {
await page.goto('https://website.com');
await page.getByRole('link', { name: 'Log in' }).click();
await expect(page).toHaveURL('https://website.com/login/');
});
Error:
expect(received).toHaveURL(expected)
Expected string: "https://website.com/login/"
Received string: "https://website.com"
Here is a piece of HTML with a login button
<span data-v-154d6ddf="" class="absolute-top-right">
<div class="row justify-end q-gutter-x-sm q-pt-lg q-px-sm">
<div class="col-auto">
<a tabindex="0" type="button" href="/login/potential" role="link" class="q-btn q-btn-item non-selectable no-outline q-btn--flat q-btn--rectangle text-white q-btn--actionable q-focusable q-hoverable q-btn--no-uppercase q-btn--wrap">
<span class="q-focus-helper" tabindex="-1"></span>
<span class="q-btn__wrapper col row q-anchor--skip">
<span class="q-btn__content text-center col items-center q-anchor--skip justify-center row">
<span>Log in</span>
</span>
</span>
</a>
</div>
<div class="col-auto">
<a tabindex="0" type="button" href="/signup" role="link" class="q-btn q-btn-item non-selectable no-outline q-btn--standard q-btn--rectangle bg-primary text-white q-btn--actionable q-focusable q-hoverable q-btn--no-uppercase q-btn--wrap">
<span class="q-focus-helper"></span>
<span class="q-btn__wrapper col row q-anchor--skip">
<span class="q-btn__content text-center col items-center q-anchor--skip justify-center row">
<span>Sign up</span>
</span>
</span>
</a>
</div>
<div class="col-auto">
<label for="f_2334a082-8df9-41a7-9ca0-403e5ce7c237" class="q-field q-validation-component row no-wrap items-start q-select q-field--auto-height q-select--without-input q-select--without-chips q-field--outlined q-field--float q-field--labeled" style="min-width:120px;max-height:20px">
<div class="q-field__inner relative-position col self-stretch column justify-center">
<div tabindex="-1" class="q-field__control relative-position row no-wrap">
<div class="q-field__control-container col relative-position row no-wrap q-anchor--skip">
<div id="translate" class="q-field__native row items-center">
<span>English</span>
<div id="f_2334a082-8df9-41a7-9ca0-403e5ce7c237" tabindex="0" class="no-outline"></div>
</div>
<div class="q-field__label no-pointer-events absolute ellipsis">Translate</div>
</div>
<div class="q-field__append q-field__marginal row no-wrap items-center q-anchor--skip">
<i aria-hidden="true" role="presentation" class="q-select__dropdown-icon fal fa-caret-down q-icon notranslate"></i>
</div>
</div>
</div>
</label>
</div>
</div>
</span>
2. Update
I tried this variation (see below), and it seems like it fails less frequently, but still does not work 100%.
I also tried .click({force: true}). Fails on 3rd run.
I am new to test automation. Just started learning Playwright.
I will appreciate any comments/suggestions.
thank you.
import { test, expect } from '#playwright/test';
test('test', async ({ page }) => {
await page.goto('https://website.com');
const loginBtn = page.getByRole('link', { name: 'Log in' });
expect(await loginBtn.evaluate(node => node.isConnected)).toBe(true) ;
await page.getByRole('link', { name: 'Log in' }).click();
await expect(page).toHaveURL('https://website.com/login/');
});
3. Update
"You should wait after clicking the button before verifying the url." This ws suggestion from #jaky-ruby
I tried this code
test('test2', async ({ page }) => {
await page.goto('https://website.com/');
// Note that Promise.all prevents a race condition
// between clicking and expecting navigation result.
const [response] = await Promise.all([
page.getByRole('link', { name: 'Log in' }).click(),
page.waitForNavigation({ url: 'https://website.com/login' }),
]);
await expect(page).toHaveURL('https://website/login');
...
});
4. Update
I created similar test in Cypress.
Here is the code
describe("Login", () => {
beforeEach(() => {
cy.visit(baseUrl);
});
it.only("Login page should open", () => {
//does not help: cy.wait(3000);
cy.get('a[href*="login"]').click();
//does not help: cy.get(':nth-child(1) > .q-btn > .q-btn__wrapper > .q-btn__content > span').click();
//does not help: cy.get('#q-app > div > span > div > div:nth-child(1) > a > span.q-btn__wrapper.col.row.q-anchor--skip > span').click();
cy.url().should("eq", authUrl.replace("env", env) + "/login/potential");
});
});
As you can see i tried different variations of locators. The interesting part is that Cypress showed this error. Not sure this is the same problem that occurs in Playwright test.
CypressError
Timed out retrying after 4050ms: cy.click() failed because this element: ...is being covered by another element:
I tried to find that element in the DOM but it is not there.
5. Update
Another thing that I do not understand is that when I select "click" step in Cypress and use picker to select my button it shows me selector cy.get('[data-layer="Content"]'). Again, when I try to search it in the DOM it is not there.
6. Update
I checked each step in Playwright using Trace Viewer.
Interesting. The log shows that Playwright waited for element to be visible and stable. However, on the attached page both Login and Sign up buttons are not visible and still loading (turns out you can inspect it. It's not just a static screenshot). I think, possibly, Playwright's auto-wait is not good enough in this example. Possibly, element is not actually stable and still loading but Playwright performs click which does not work.
Now question, "can I do some additional wait to unsure that element has loaded and stable? "
Okay, looks like I found ~~solution~~ a way to make my test less flaky.
Test still fails sometimes. I think, additional 2 waits which I added just give more time for element to load, so in most cases, probably, that is enough for button to reach stable state. That's why clicking works. Note, on the screenshot below that 'networkidle' is 1.4s
Here is the final code
import { test, expect } from '#playwright/test';
test('test', async ({ page }) => {
await page.goto('https://website.com');
await page.waitForLoadState('networkidle'); // <- until there are no network connections for at least 500 ms.
await page.getByRole('link', { name: 'Log in' }).waitFor(); // <- wait for element
await page.getByRole('link', { name: 'Log in' }).click();
await expect(page).toHaveURL('https://website.com/login/');
});
Sharing here some interesting links I found along the way
Avoiding hard waits in Playwright and Puppeteer - DEV Community 👩‍💻👨‍💻
waitForLoadState waitUntil domcontentloaded doesn't wait · Issue #662 · microsoft/playwright · GitHub

error element not visible because its ancestor has position: fixed CSS property and it is overflowed by other element

i am trying to click on the icon trash
<div class="form-body">
<div class="infos">
<div class="recap">
<div class="form-actions ">
<a class="btn btn-light btn-icon btn-icon-light" title="download" href=""
target="_blank" rel="noreferrer noopener" download="my_file">
<i class="icon-download"></i>
</a>
<button type="button" class="btn btn-light btn-icon btn-icon-light" title="delete">
<i class="icon-trash">
i have tried
cy.get('i.icon-trash').click()
cy.get(.form-actions .icon-trash').click()
Whatever i am trying i am getting the error:
The element <i.icon-trash> is not visible because its ancestor has position: fixed CSS property and it is overflowed by other elements. How about scrolling to the element with cy.scrollIntoView()?
Fix this problem, or use {force: true} to disable error checking.
scrollIntoView() also is not working.
Does anyone know why this error is happening please?
Thank you
screenshot of the html part above
The button parent of the icon has the click handler, try clicking that
cy.get('i.icon-trash')
.parent()
.scrollIntoView()
.should('be.visible') // for good measure, may not require
.click()
but I suspect the problem still persists.
Also try realClick()
cy.get('i.icon-trash')
.parent()
.scrollIntoView()
.should('be.visible')
.realClick({ position: "topLeft" }) // try various click positions
You can also try setting a larger viewport at the top of the test.
Other than that try working the CSS - but this is a bit of a hack.
Arguably it's ok because you are testing the click logic not the visibility of the icon (also true for .click({force:true})).
Identify the element with position: fixed for example if it's div.form-actions
cy.get('div.form-actions')
.then($formActions => {
$formActions.css({ position: 'relative' })
})

Cypress - cy.click() does not click on the value in the select2 drop down

I have a dropdown which has select2 class. On clicking the arrow in drop down, I get below code activated in DOM which has the values Reason1 and Reason2 in the dropdown. I want to iterate on the available values and select the desired option.
Using each function, I am able to itearte on the array and get the available values, but I am unable to perform cy.click() on the same to get the value selected. I am not getting any error and code is running fine but the click in not happening (neither on div , li nor span tag)
`<ul class="select2-results">
<li class="select2-results-dept-0 select2-result select2-result-selectable">
<div class="select2-result-label">
<span class="select2-match"></span>
Reason1
</div>
</li>
<li class="select2-results-dept-0 select2-result select2-result-selectable">
<div class="select2-result-label">
<span class="select2-match"></span>
Reason2
</div>
</li>
</ul>`
Given below is my code
cy.get('#select2-drop > .select2-results').find('li').each(($el,index,$list) => {
let option = $el.find('div').text()
if(option=='Reason2')
{
$el.find('div').click()
}
})
If I add $el.find('div').css('background-color','yellow') in the if condition, elements background color is getting changed to yellow but click is not happening.
Can anyone please help on this.
Thanks!
you can use these command if you want to select the second one
cy.get('#select2-drop > .select2-results')
.type("{downarrow}")
.type("{downarrow}")
.type("{enter}")

click on element hidden due to md-backdrop class

Unable to click on the "stage1".
CypressError: Timed out retrying: cy.click() failed because this element:
<img class="add-achievement" src="images/gamification/add-entry-icon.e4f22ffd.png"
alt="add stage achievement" ng-click="addStage(achievement.stage)" role="button"
tabindex="0">
is being covered by another element:
<md-backdrop class="md-select-backdrop md-click-catcher ng-scope" style="position: fixed;">
</md-backdrop>
Fix this problem, or use {force: true} to disable error checking.
https://on.cypress.io/element-cannot-be-interacted-with
Code:
cy.get('#stage').click({force: true})
cy.get('#select_container_218 > md-select-menu > md-content')
.invoke('show')
.should('not.be.visible')
cy.contains('stage1')
.invoke('show')
.click({force: true})

Dropzone opens file chooser twice

I have set up dropzone with a clickable element. Clicking the button causes dropzone to open the file chooser twice, instead of just once, the second coming immediately after the first file has been chosen.
The init code is:
Dropzone.autoDiscover = false;
$(document).ready(function(){
// Remove the template from the document.
var previewNode = document.querySelector("#template");
previewNode.id = "";
var previewTemplate = previewNode.parentNode.innerHTML;
previewNode.parentNode.removeChild(previewNode);
$("div#photo").dropzone({
url: "/blackhole/",
thumbnailWidth: 240,
thumbnailHeight: 240,
parallelUploads: 1,
maxFiles:1,
maxFilesize: 5,
uploadMultiple: false,
previewTemplate: previewTemplate,
autoProcessQueue: true,
previewsContainer: "#photoPreview",
clickable: ".fileinput-button",
init: function() {
this.on("maxfilesexceeded", function(file) {
this.removeAllFiles();
this.addFile(file);
});
}
});
And the page elements are:
<div class="table table-striped" class="files">
<div id="photo">
<div id="actions" class="row">
<div class="col-lg-7">
<button type="button" class="btn btn-success fileinput-button">
<i class="glyphicon glyphicon-plus"></i>
<span>Choose file...</span>
</button>
</div>
</div>
</div>
<div class="files dropzone-previews" id="photoPreview">
<div id="template" class="file-row">
<div>
<span class="preview"><img data-dz-thumbnail /></span>
</div>
<div>
<p class="name" data-dz-name></p>
<strong class="error text-danger" data-dz-errormessage></strong>
</div>
<div>
<p class="size" data-dz-size></p>
<div class="progress progress-striped active" role="progressbar" aria-valuemin="0" aria-valuemax="100" aria-valuenow="0">
<div class="progress-bar progress-bar-success" style="width:0%;" data-dz-uploadprogress></div>
</div>
</div>
<div>
<button data-dz-remove type="button" class="btn btn-warning cancel">
<i class="glyphicon glyphicon-ban-circle"></i>
<span>Cancel</span>
</button>
</div>
</div>
</div>
</div>
</div>
Strangely, even though I have added code to replace the any existing file with a later one (so only one file can be uploaded), the second file chooser dialog lets me add a second file.
Its like dropzone has been initialized twice, but I checked that it is only initialized once, and also added the autoDiscover = false option for good measure.
Can anyone spot my mistake?
The problem seems to be in how we initialized dropzone:
$("div#photo").dropzone({
...
}
Doing it the non-jquery way solved the problem:
var myDropZone = new Dropzone("#photo",{
...
}
This was on dropzone 3.11.1.
An issue has been created on github/dropzone:
https://github.com/enyo/dropzone/issues/771
This happens for me when more than one dropzone exists on the page with the same class for a browse trigger, it seems that dropzone attaches the event to any element on the page and not just within its own container
In the issue opened for this, maliayas said:
This bug happens when your clickable element is already an
input[type=file]. Dropzone injects another one and now you have two.
Either dropzone should handle this case or documentation should
mention not to use an input[type=file] for the clickable element.
Changing my dropzone element to something other than an input[type=file] fixed the issue for me.
Attach dropzone to the parent, not the input.
In Chrome if you inspect and look at the eventListeners. You will see that once you attach dropzone to your input, you have an additional click eventListener.
Say you have a list of uploads for documents with a child input element.
<li class="upload drag-and-drop">
<input type="file"/>
</li>
Code:
$('input').dropzone();
Will attach an event listener to an already clickable element. So you have 2 event listeners. One from the browser. One from dropzone. Hence 2 dialogs...
If you attach it to the parent:
$('li.upload').dropzone();
You'll now had the listener at the parent. This allows the bubble up behavior to hit the correct element when you drag and drop and not inadvertently effect the input.

Resources