Inconsistent element query with Cypress - cypress

I'm trying to use Cypress to click a react-select element. However, I get very inconsistent results.
My code for clicking the element is as follows:
cy.get('div[class*=container]').contains('Brand').click()
Sometimes this works, sometimes it doesn't. Sometimes if I repeat this line twice (which is kind of hacky...), it works, but on other occasions it doesn't...
What would be the correct and fool-proof way to wait for this element to properly load and click it only then in Cypress?

I looked into this cypress repo and it suggested two way to do the click().
cy.contains('.product', 'First item')
.find('button.order')
.click()
.wait(1000)
cy.contains('.product', 'First item')
.find('button.order')
.click()
.click()

Because its a select element, what you would want to do is:
cy.get('div[class*=container]').select('Brand')
or
cy.get('div[class*=container]').contains('Brand').realClick()

Looking at examples of react-select, there are a lot of classes with container in them, so 'div[class*=container]' is not the best selector.
I understand class*=container is to circumvent the style hash which can change on compile.
Ideally, add a specific class to the source, as per the first example on the home page
<Select
className="basic-single"
...
then you have a link to the top-most element, which is clickable.
cy.visit('https://react-select.com/home')
cy.get('div.basic-single')
.should('contain', 'Ocean')
.click()
cy.contains('Green').click() // option selection
cy.get('div.select__control').eq(0)
.should('contain', 'Green')

Related

How to select value from drop down using cypress?

Here I am using cypress tool for automation. How to write code for dropdown menu
Here is the HTML code
I just done like this way but its not working
cy.get('.dropdown-heading-dropdown-arrow').click()
cy.get('#0').click()
After dropdown opens search for the option with required text.
Not sure which selector might work for you, either role or .MuiMenuItem-root looks best, or try just getting any element with the text
cy.get('.dropdown-heading-dropdown-arrow').click()
cy.contains('[role="option"]', 'Select All')
.click()
// or
cy.contains('.MuiMenuItem-root', 'Select All')
.click()
// or
cy.contains('Select All')
.click()
Have a look at this. Gives a good explanation as well.
select dropdownlist item using cypress
Otherwise you can just get it by css selector, xpath or you can do cy.contains

Second drop down list does not get filled with Cypress

I ran into a problem. Can anyone help me ?
So, I have two drop down lists and the second is dependent on the option I choose on the first.
Say, for example: The first drop down list has the options 'numbers' and 'letters', while the second drop down list is empty by default. However, when I choose the option 'letters' on the first drop down list, the second is filled with the options 'A', 'B' and 'C'. Manually, it is working fine, but when I select the first drop down list with Cypress, the second doesnt get filled. It remains empty, so I cant choose anything on it.
HTML:
<select id="list" class="selectpicker form-control" onchange=""><option value="0">select your preferences</option><option value="2">numbers</option><option value="3">letters</option></select>
CYPRESS:
cy.get('#list').select('letters')
it does select the option letters, I can see the option letters selected on the first drop down list, but nothing happens on the second.
The solution from what it seems is to force the click because, from what I could gather, cypress chooses the option but IT DOESNT CLICK THE OPTION! Is this a bug?
So, this is the giant that was necessery, in the end to make it work:
//choose the option on the first drop down
cy.get('#list').select('letters')
cy.get('#list').contains('letters').then(option => {
cy.wrap(option).contains('letters');
option[0].click();
cy.get('#list').contains('letters');
});
//choose the option on the second drop down
cy.get('#list2').select('A')
cy.get('#list2').contains('A').then(option => {
cy.wrap(option).contains('A');
option[0].click();
cy.get('#list2').contains('A');
});
//click on the button to save the options selected
cy.get('.saveButton').click()
when, normally, it should be only:
cy.get('#list').select('letters')
cy.get('#list2').select('A')
cy.get('.saveButton').click()
Do you guys think this is a bug ?
I think you should "force" the refreshing data from the "non-updated" dropdown.
Try to "click()" it.
Something like this:
cy.get('#list')
.contains('letters')
.then(option => { // Confirm have correct option
cy.wrap(option).contains('letters');
option[0].click(); // After click, mdc-select should hold the text of the
// selected option: cy.get('#list').contains('letters');
});
Maybe this link can help you: select dropdownlist item using cypress
alternatively you can select by value cypress docs
cy.get('#list').select('3')

Cypress not finding data-test element

Morning/evening everyone. Have a weird issue that, according to the best practices, should just work.
I have the following element on a page which I need to click:
<a data-test="sign-out-link" href="/redirect/onejl/sign-out"><span>Sign out</span></a>
I'm doing this in my test:
cy.get('[data-test="sign-out-link"]') .should('be.visible') .click()
But cypress times out saying the element cannot be found...
This gives the same behaviour:
cy.get('a[data-test="sign-out-link"]') .should('be.visible') .click()
Even this just fails, which is kinda weird (it should find that text fairly easily):
cy.contains('Sign out').click()
Anything obvious I'm doing wrong?
Have you tried to find out this element in selector playground. check here.
One obvious error I see is on your hyperlink. Try with below
cy.get('a[data-test=sign-out-link]').should('be.visible').click()
Can you please add a small cy.wait() before cypress Sign out test code and see if that is working for you.
cy.wait(2000);
cy.get('[href="/redirect/onejl/sign-out"] > span').contains("Sign out").click();
cy.wait(2000);
cy.get('a > span').contains("Sign out").click();
cy.wait(2000);
cy.get('[data-test ="sign-out-link"]').should('be.visible').click();

Difficulties with Cypress scrollTo method

I am having a few issues testing a virtual scroll component with Cypress. I have a test that checks the li elements present in the DOM after scrolling to the bottom of a container.
When written like this the test passes:
cy.get('.virtual-scroll').scrollTo('bottom')
cy.wait(0)
cy.get('li').last().children('h4').contains('1999')
When written like this it doesn't:
cy.get('.virtual-scroll').scrollTo('bottom')
cy.get('li').last().children('h4').contains('1999')
This also fails:
cy.get('.virtual-scroll').scrollTo('bottom').get('li').last().children('h4').contains('1999')
In the second and third examples, get('li') is returning the li elements present before the scroll has completed, and therefore failing the test. I can fix this by adding .wait, but don't fully understand the behaviour and wonder if this is a bug.
Any ideas?
Make an assertion that will always pass when the DOM is rendered, such as using .get() for an element that gets added to the DOM
ex) if you had a <ul class="myloadedlist">.... :
cy.get('.virtual-scroll').scrollTo('bottom')
cy.get('ul.myloadedlist')
cy.get('li').last().children('h4').contains('1999')
That way, Cypress will continue with the test as soon as that element becomes visible.
Why?
I'm assuming the elements get added to the DOM in some sort of scroll eventListener. In that case this is correct behavior.
Essentially what you've tested is the race condition of a user scrolling very quickly to the bottom of the page, to see that the DOM has not yet finished rendering- a valid senario.
Since you targeted the last() li element, Cypress finds the last element of the page before the DOM gets updated, and expects it to contain 1999, which it does not, even after Cypress retries for 4 seconds.
This is actually a great feature of Cypress, because you can test on the state of the DOM at times that the User might only see for a split second.
In my case, adding a duration to the scroll option did the trick.
cy.get("#dialogContent").scrollTo("center", { duration: 500 });

Can't click an input type="button" that exists but it's not visible

First of all... I red everything I could and tried everything I found!!
With the following gems installed in WinXp:
Watir-webdriver 0.6.10 |
selenium-webdriver 2.42.0 |
Firefox 30
I have a type="button", inside an input tag element, which I'm sure it exists in the browser (returns true to exists?), but that it's not visible to watir (returns false to visible? or present?), despite being visible to the user.
I've tried the .hover, .fire_event "onmouseover", .click and fire_event("onclick") approaches and none solved the problem.
With the first I get a native event problem whether I disable native events in firefox, as suggested in watir webdriver website, or not.
b.div(:class, "buttons btnGuardarCancelar").button(:id, "guardar").hover
b.div(:class, "buttons btnGuardarCancelar").button(:id, "guardar").when_present.click
With the second I get a true answer, but nothing happens, even with a wait_until_present or when_present after that command.
b.div(:class, "buttons btnGuardarCancelar").button(:id, "guardar").fire_event("onmouseover")
b.div(:class, "buttons btnGuardarCancelar").button(:id, "guardar").when_present.click
With the third I get a timeout, saying the element is not visible.
b.div(:class, "buttons btnGuardarCancelar").button(:id, "guardar").when_present.click
And with the last one it fires some other onclick event, but not the one associated with the button I indicate.
b.div(:class, "buttons btnGuardarCancelar").button(:id, "guardar").fire_event("onclick")
Also tried xpath with the following:
b.element(:xpath, "//input[#id='guardar']").when_present.click
and
b.button(:xpath, "//input[#id='guardar']").when_present.click
the code is what follows:
<div class="buttons btnGuardarCancelar" name="">
<input id="cancelar" class="formButton margingleft" type="button" value="Cancelar" onclick="openUserServiceConfigMenu(1);" tabindex="12"></input>
<input id="guardar" class="formButton margingleft" type="button" value="Guardar" name="guardar" onclick="sendForm();" tabindex="12"></input>
</div>
The behaviour is the same for both buttons. I don't know what to do more, to get this working. Important to say that I have no control over the website.
add-ons:
1) it works when interacted directly by a human user.
2) it also doesn't work via irb.
3) i don't need the click any other buttons to access this button.
Edited:
Just tried:
b.element(:css, "div.buttons.btnGuardarCancelar > input[name=guardar]").click
Received the following error:
[remote server] file:///D:/DOCUME~1/p056988/LOCALS~1/Temp/webdriver-profile20140
708-5676-32980a/extensions/fxdriver#googlecode.com/components/command_processor.
js:8791:5:in `fxdriver.preconditions.visible': Element is not currently visible
and so may not be interacted with (Selenium::WebDriver::Error::ElementNotVisible
Error)...
Well, found my answer... tried to answer yesterday, but since my rep is still low I couldn't until 8 hours after I posted.
After digging deep in the website code, using the Firefox built-in inspector, I found the issue ...
It seems that there are some other buttons in the same page, with the same identifiers - html just like the one I was trying to address -, but they are hidden and so watir-webdriver tries to click the first it gets in the html page code and it gets a not visible error.
I managed to solve the problem by editing the button parents to be more specific, starting with the first "present?==true" element in the path.
b.td(:class, "tab_user_service_options").div.div.div.div(:class, "buttons btnGuardarCancelar").button(:id, "guardar").click
Thanks for all your kind answers.
Cheers.
Sometimes the .click doesn't work. There are many different factors that could cause this and that really depends on the implementation of your application. Utilize the OpenQA.Selenium.Interactions.Actions class to simulate the user movements instead of executing a click event on an element.
OpenQA.Selenium.Interactions.Actions actions = new OpenQA.Selenium.Interactions.Actions(driver);
actions.MoveToElement([IWebElementGoesHere]).Perform();
actions.click().Perform();
This will move the mouse to the desired location and then click it. Based on your previous comments you are able to find the web element so it should function to move the mouse and click there. There is also an actions.click([IWebElementGoesHere]).Perform(); which I have found also usually works, but if it doesn't then you can use the move and then click.
Depending on your application you might have to move your mouse and wait before clicking if there is some behind the scenes actions that take place...but that totally depends on the implementation of your application.
The element you are trying to 'click' is most likely being 'covered' by another element (possibly a 'span' element). The element will return 'exists?' but is not 'clickable', "because another element would receive the click"
On the site I'm currently testing the UI guy will use a 'span' to stylize the elements on the page. So where it looks like i'm clicking on a 'button' element, in actuality I'm clicking on the span that is on top of the button element.
I would suggest using Selenium IDE and recording the flow, it should give you some clues as to the element you can use in your script.
As per the documentation of Watir, it first check whether element exists(Returns whether this element actually exists), and which doesn't check element is visible or not. So before performing any action,it is necessary that element should be visible.
def click
assert_exists
assert_enabled
#element.click
run_checkers
end
I generally check for presence for element and then check whether element is preset or not. If not use, wait_until_present and then perform any desired action.
browser.element(:css => locator).wait_until_present
browser.element(:css => locator}").click
Try out this and revert if this works for you!

Resources