Retrieve text from nested shadow elements in cypress - cypress

I have nested shadow elements written like below in cypress:
cy.get('app-screen')
.shadow()
.find('app-toolbar')
.shadow()
.find('app-container .csr-content .csr-content_primary:nth-child(1) csr-multi-record')
.shadow()
.find('.stud-container .stud-rec .stud__title span')
.should('have.text', 'Viola');
The element 'span' has the text (student name - Viola).
But, I don't want to use the whole statement like this. Rather, updated the 'cypress.json' with "includeShadowDom" : true.
Now, the statement I used is:
cy.get('app-screen')
.find('.csr-content_primary:nth-child(1) .stud-container .stud-rec .stud__title span')
.should('have.text', 'Viola');
The results states the text was '' and also it states never found the element.
Again, rewrote the statement as:
cy.get('app-screen')
.find('.csr-content_primary:nth-child(1)')
.find('.stud-container .stud-rec .stud__title span')
.should('have.text', 'Viola');
This time the element was found but the result was 'Viola Marcus Helen Roy Belinda...' instead of just 'Viola'. There were more than 10 elements with class as '.csr-content_primary'.
This statement took the text for all those elements that had '.csr-content_primary' in the 1st find method.
Is that possible to get the required text from '.csr-content_primary:nth-child(1)'? And, how to write in one find method instead of two?
Could someone please help me on this?
The HTML structure looks like this:
<app-screen _ngcontent-put-c111>
#shadow-root (open)
<style>...</style>
<style>...</style>
<style>...</style>
<style>...</style>
<style>...</style>
<div class="app-toolbar">
<app-toolbar-root class="ng-star-inserted">
#shadow-root (open)
<style>...</style>
<style>...</style>
<style>...</style>
<style>...</style>
<style>...</style>
<div class="app-container">
<div class="top-level-bar">
<div id="csrContent">
<app-csr-content _ngcontent-put-c121>
<div class="csr-content">
<app-csr-toolbar>...</app-csr-toolbar>
<div _ngcontent-put-c121>...</div>
<div class="csr-content-main">
<div class="csr-content_primary">
<csr-multi-record _ngcontent-put-c121>
#shadow-root (open)
<style>...</style>
<style>...</style>
<style>...</style>
<style>...</style>
<style>...</style>
<div class="stud-container">
<div class="stud_rec">
<div class="stud__title">
<img-icon class="img-icon">title</img-icon>
<span class="title-desc">Viola</span>
</div>
</div>
</div>
</csr-multi-record>
</div>
</div>
</div>
<app-crs-content>
</div>
</div>
</div>
</app-stud-container>
</div>
</app-screen>

Have to guess a bit without seeing the web page, but seems like you can move the :nth-child(1) to Cypress .eq(0) which should give the same effect.
cy.get('app-screen')
.find('.csr-content_primary')
.find('.stud-container .stud-rec .stud__title span')
.eq(0)
.should('have.text', 'Viola');
The shadow DOM is having an unusual effect of the Cypress search, normally the 1st and 2nd version are equivalent.
Perhaps you can also add visibility checks, in case there's delay in loading elements.
cy.get('app-screen')
.find('.csr-content_primary:nth-child(1)')
.should('be.visible')
.find('.stud-container .stud-rec .stud__title span')
.eq(0)
.should('have.text', 'Viola');

Related

How to check if a div has a sibling div using cypress?

Hi below is the html,
<div class="styledCard">
<div class="cardHeader">
<div class="headerLeft">
<div class="title">title1</div>
<div class="subtitle">subtitle1</div>
</div>
</div>
</div>
in here i want to check if title1 has subtitle1. i have like below
cy.textEqualsR('title', 'title1')
.parentsR('styledCard')
.containsR('div', 'subtitle1')
but the above fails. i am new to cypress. could someone help me out with this. thanks
If you want to use parent() and contains() you can do something like:
cy.contains('div.title', 'title1')
.parent() //yields.headerLeft
.contains('div.subtitle', 'subtitle1')
Or, if you want to use parents(), you can use:
cy.contains('div.title', 'title1')
.parents('div.styledCard')
.contains('div.subtitle', 'subtitle1')

D3js: ":last is not a valid selector"?

d3.select('.activity:last') and d3.selectAll('.activity:last') both fail. Meanwhile; $('.activity:last') works.
d3.selectAll('.activity:last')
.append('<div class="hook-table">Table comes here</div>');
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<div class="container">
<div class="activity"></div>
<div class="activity"></div>
<div class="activity"></div>
<div class="activity"></div>
<div class="activity"></div>
</div>
Is there a D3 way to pass :last selector.
:last is not a valid css selector. It works with jQuery because jquery has added support for this selector:
:last is a jQuery extension and not part of the CSS specification (docs)
As D3 only contemplates valid CSS selector strings so :last won't work with D3.
Instead you'll require a bit more code to get the last element.
If your div is the last of of its siblings, then you can use :last-child:
d3.select(".container").select(".activity:last-child")
.text("5: This div selected");
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<div class="container">
<div class="activity"><p>1</p></div>
<div class="activity"><p>2</p></div>
<div class="activity"><p>3</p></div>
<div class="activity"><p>4</p></div>
<div class="activity"><p>5</p></div>
</div>
However, this won't work if you have another element below the last div. The above will select the div with class "activity" that is the last child of .container (see MDN).
For more complex structures, where the last div or element with class "activity" isn't the last sibling, you'll need to take a more complex approach.

v-if not working with conditional rendering on Dropdown value changes

I have implemented a Kendo DropDownlist as below:
<kendo-dropdownlist v-if="PaymentTypeList != null"
name='PayType'
class="form-control"
v-model="vModel.PayType"
:data-text-field="'Text'"
:data-value-field="'Id'"
:auto-bind="true"
:data-source="PaymentTypeList">
</kendo-dropdownlist>
I have to render only one div below according the value selected on the dropdown list.
<div v-if="vModel.PayType == PaymentTypes.Cash">
<div class="row">
<div class="col-sm-3">
<div class="form-group">
<label>Pay Code
<span class="text-red">*</span>
</label>
<input type="text" class="form-control" id="PayCode" name="PayCode" autocomplete="off" v-model="vModel.PayCode">
</div>
</div>
</div>
</div>
<div v-else>
<kendo-dropdownlist v-model="dropdownlistValue"
:data-source="dataSourceArray"
:data-text-field="'text'"
:data-value-field="'value'">
</kendo-dropdownlist>
</div>
But the first div is never shown whatever is the condition either false or true.
When i try with the v-show it works.
How should i make this code able to work on v-if.
The plunker implementation is here on the link
https://plnkr.co/edit/Xbhm67KjnpovOWNBy2O2?p=preview
Edited: According to vue js
v-if is also lazy: if the condition is false on initial render, it will not do anything - the conditional block won’t be rendered until the condition becomes true for the first time.
But in my case when the initial condition is true the first div is rendered, and after that the first division is never rendered whatever will be the condition either true or false.
I suggest you solve this issue by using v-show. v-if is "better" suited for (not) rendering the DOM at all opposed to v-show that is just manipulating display of DOM (hidden/shown).
Forked your Plunker to this one: https://plnkr.co/edit/PjOhBbuTO6czxvQQ10da?p=preview (had to introduce "empty" select value).
Hope it helps...

listElement property not behaving as expected

Hi have created a JSFiddle of my problem here.
http://jsfiddle.net/L7o1nct6/2/
I will also repeat the code here as Stackoverflow is forcing me to do.
JavaScript
<!-- using fine uploader 5.1.3 at http://keysymmetrics.com/jsfiddle/jquery.fine-uploader.js -->
$(document).ready(function()
{
$("#fine-uploader").fineUploader({
listElement: $('#listElement'),
debug: true,
template: 'qq-template-bootstrap',
request: {
endpoint: "/my-endpoint"
}
});
});
HTML
<script type="text/template" id="qq-template-bootstrap" class="qq-uploader-selector">
<div class="row">
<div class="col-sm-4" >
<div class="qq-upload-button-selector
qq-upload-drop-area-selector
drag-drop-area" >
<div>Drag and drop files here or click to upload</div>
</div>
</div>
</div>
<div class="qq-upload-list-selector" id="#listElement" >
<div class="panel panel-default" >
<div class="panel-body" >
<div class="qq-progress-bar-container-selector progress">
<div class="qq-progress-bar-selector progress-bar"></div>
</div>
<span class="qq-upload-spinner-selector qq-upload-spinner"></span>
<span class="qq-upload-file-selector qq-upload-file"></span>
<span class="qq-upload-size-selector qq-upload-size"></span>
<span class="qq-upload-status-text-selector qq-upload-status-text"></span>
<img class="qq-thumbnail-selector" qq-max-size="100" />
</div><!-- close panel-body -->
</div><!-- close panel -->
</div>
</script>
<h1>Fine Uploader Test</h1>
<div id="fine-uploader"></div>
When viewing the JSFiddle example, if you open the debug console, you will see the message "Uncaught Error: Could not find the file list container in the template!".
I am unsure what this means, I thought I could use the listElement property to tell fine-uploader which element to use for this list?
On a side note, if I cut and paste the div with id=listElement and move it adjacent to the div with class=qq-upload-button-selector then this example works fine.
Any help would be appreciated, I have spent hours on this and haven't found an answer for this on stackoverflow either.
A couple issues with your code:
"#listelement" is not a valid html element ID in all browsers.
You are attempting to select an element that does not yet exist in the DOM. It's not clear why you are specifying a list element anyway. Fine uploader should find the list in the template when it renders.

Xpath: locate a node by multiple attributes of a parent node

Here is the code:
<li class="abc">
<div class="abc">
<input type="checkbox">
</div>
<div class="xyz">
<div class="headline">Mongo like candy</div>
<div>
</li>
<li class="abc">
<div class="abc">
<input type="checkbox">
</div>
<div class="xyz">
<div class="headline">Candygram for mongo</div>
<div>
</li>
Xpath challenge. I want locate the checkbox of the li which contains the headline "Mongo like candy" so I can select it using Selenium. In other words, how do you locate the checkbox from here:
li//div[#class='abc']//input[#type='checkbox']
but qualifying it with a different attribute within the same parent node:
li//div[#headline][contains(text(),"Mongo like candy")]
The basic idea is to qualify the final path with a predicate, i.e.
li[/*predicate here*/]//div[#class='abc']//input[#type='checkbox']
The predicate expresses the condition on the li that you want:
.//div[#class='headline' and contains(text(), "Mongo like candy")]
Putting them together yields:
li[.//div[#class='headline' and contains(text(), "Mongo like candy")]]//div[#class='abc']//input[#type='checkbox']
something like
li[div[#class='xyz']//div[#class='headline' and contains(text(),"Mongo like candy"))]]//input[#type='checkbox']
unless I messed up parentheses. (that is, you select not just li, but the proper li).
Even this works:
//li[1]/div[1]/input[#type='checkbox']
It may fail if more div tags are introduced in the page.

Resources