Cypress get element that a child contains - cypress

I'm trying to find in a table my row that cy.contains() a specific text.
I cannot do:
cy.get("tr").contains("specific text")
That will return my span element containing the text
I cannot do
cy.get("tr").contains("specific text").parent()
beacause the parent of the span my not be my
I cannot do
cy.get("tr").contains("specific text").parentUnitl("tr")
That will not return the element
I probably could do
cy.get("tr").contains("specific text").parentUnitl("tr").parent()
But I think that's becoming really complex for such a simple thing.
Am I missing something?
Thanks

You can do
cy.contains("tr", "specific text")
which will return the <tr> even though the text is in a descendent <span>.
It will also have better retry ability than cy.get().contains() if the row loads asynchronously.

Related

Inconsistent element query with 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')

Expect an element by xpath to have specific text

After pressing a save button a box will pop up and say if it was success or failed. The box has the same xpath no matter the result.
expect(element(by.xpath('path example')));
Inside the HTML for the element it says
<div class="panc lm-he" style="....."><span style="..."> Saved!</span></div>
edit -- oops it's early.
I want to know how can I have the expect come back true if the text "Saved!" is there or not. So if "Saved!" is present inside that element then it's true otherwise it's false.
Try with showing the output of the entire element like this:
element(by.xpath('path example')).then(function(element){
console.log(element);
});
not sure I understand want you want, but this way you will check if div with 'Saved!' text is Displayed
expect(element(by.xpath('.//div[text(), "Saved!"]')).isDisplayed).toBe(true);
As #Gunderson notes it doesn't matter what locator you use, the syntax will be the same. When I want to confirm text in an element I usually do something like this:
myElement.getText().then(function (text) {
expect(text).toContain(message)
});
That way you can tell by looking at the failure if the element didn't show up at all, or if it is visible but the text is not displayed, or if everything is fine and the test passes. So in your case it would just be
element(by.xpath('path example')).getText().then(function (text) {
expect(text).toContain('Saved!')
});

How to get the text of hidden check boxes inside a scroll bar using Selenium WebDriver?

I'm trying to automate Filter By Brand scenario in BigBasket and now stuck up in a situation where my code could not print the brand names that are hidden inside a scroll bar.
Steps to follow
Go to www.bigbasket.com
Click Skip & Explore button
Search Apple and view the list of brands on the left side
#FindAll({#FindBy(xpath="//*#id='filter_brands_list']/div/div1/li/label")})
List chkBrands;
The above lines of code identifies all the brand names but when I print them using the below code I can see only the brand names that are visible
for(WebElement eachElement:chkBrands){
System.out.println("No. of brands is "+chkBrands.size());
System.out.println(eachElement.getText());
}
Could you please let me know the solution? I apologize that I could not think of a solution as I'm an amateur in Selenium.
WebElement.getText() will return the text of the element only if it is displayed on the screen.
Meaning if the isDisplayed method returns false then getText()method will return empty.
Explanation with Examples Here
As defined in WebDriver spec, Selenium WebDriver will only interact
with visible elements, therefore the text of an invisible element will
always be returned as an empty string.
However, in some cases, one may find it useful to get the hidden text,
which can be retrieved from element's textContent, innerText or
innerHTML attribute, by calling element.attribute('attributeName') or
injecting JavaScript like return arguments[0].attributeName.
So you can get the text by textContent attribute
eachElement.getAttribute("textContent")
Try this one:
JavascriptExecutor je = (JavascriptExecutor)driver;
WebElement element = driver.findElement(By.xpath("Your_xpath"));
String text_value = ((JavascriptExecutor) driver).executeScript("return arguments[0].innerHTML;",element);

How to set a span value with capybara?

Does anyone know how to set a value to span tag using capybara?
I tried using element.set or element.send_keys, they only selected the targeted element without modifing the previous value.
<div data-offset-key="bbpvo-0-0" class="_1mf _1mj"><span data-offset-key="bbpvo-0-0"><span data-text="true">aa</span></span></div>
HTML snippet is above, I want to set aa to bb.
Capybara is designed to emulate a user - A user can't edit a span unless there's some sort of javascript widget attached to it. If you have a JS widget attached to the span you would need to perform whatever actions a user would do in order to edit the span. So you say the user has to click on the span and then type on the span - if that is so then you could try something like
span = find('span[data-text="true"]')
span.click
span.send_keys("new content", :enter) # if enter is needed to end the editing
which may work - although I'm going to guess the element actually gets replaced with an input or something after it's clicked on, in which case you need to figure out what those elements are (using the browsers inspector) and then find and use send_keys or set on that element instead
To set text in span value,jquery can be used with capybara as shown below:
page.execute_script("$("<span css selector>").text("testing")");
or
page.execute_script("$("<span css selector>").html("testing <b>1 2 3</b>")");

Reusable charts in d3: how do the create and update selections work?

Several of the reusable charts examples, such as the histogram, include the following:
// select the svg element, if it exists
var svg = d3.select(this).selectAll("svg").data([data]);
// append the svg element, if it doesn't exist
svg.enter().append("svg") ...
...where this is the current DOM element and data is the data that's been bound to it. As I understand it, this idiom allows a chart to be created the first time the chart function is called, but not 'recreated', if you like, following subsequent calls. However, could anyone explain this idiom in detail? For example:
Why is .selectAll("svg") used and not .select("svg")?
Why isn't .empty() used to check for an empty selection?
Can any single-element array be passed to .data()? (I assume the purpose of this array is simply to return the enter selection.)
Thanks in advance for any help.
When this is called the first time, there's no SVG and therefore the .enter() selection will contain the data passed to it. On subsequent calls, the .enter() selection will be empty and therefore nothing new added.
Concerning the specific questions:
.selectAll() returns an array which can then be matched to the array passed to .data().
.empty() could be used, but it's not necessary -- if the selection is empty, nothing happens. Checking .empty() would add an if statement and have exactly the same effect.
Yes. Have a look this tutorial for example for some more detail on selections.

Resources