How to access child element via wdio - webdriver-io

Below code is for finding parent. What needs to be passed instead of ".." to access child?
const parent = paragraph.$('..')
console.log(parent.getTagName()) // outputs: "body"

Do you know which elements are you looking for? Check these examples:
paragraph.$$('//*') // find all childs
paragraph.$('a') // find first child link
paragraph.$('*=Submit') // find first child element which contains 'Submit'
You can use any locator strategy as you want - CSS, XPath, TagName or by text. Check documentation

Related

locate displayed element with webdriverio

When developing in the Ionic framework, the generated html sometimes will contain duplicate DOM elements, where all but one tree of elements is hidden with a class="ion-page-hidden" at the top level.
When using webdriverio to try and locate an element inside this tree, it find duplicated elements. Since the ion-page-hidden class is at the top of the tree, and not on the element itself, how can we use Xpath to locate only the displayed element.
I couldn't figure out any way to modify the XPath selector with a second condition since the elements are exactly the same!
So instead I have tried to use the webdriverio isDisplayed() function:
get openHamburgerMenu() { return Utils.visibleElement($$("//ion-button[#name='button-open-menu']")); }
where the Utils function is:
async visibleElement(elementArray) {
let returnElement;
elementArray.forEach(element => {
if (element.isDisplayed()) {
returnElement = element;
}
});
return returnElement;
}
but no elements are passed into the function. In the chrome browser, I can see two that match the xpath //ion-button[#name='button-open-menu']. I need the one not in the ion-page-hidden block!
tree
The tree looks like this:
app-for-homes[1]/ion-header/ion-toolbar/ion-buttons[1]/ion-button
app-for-homes[2]/ion-header/ion-toolbar/ion-buttons[1]/ion-button
where app-for-homes[2] happens to have the ion-page-hidden class.
I think it should be possible to use ancestors to identify which of the two elements, matching the xpath, does not have a 4th level ancestor with that class? But I'm way out of my depth on day one of working with xpaths...
Quick and Dirty
The desired outcome can be achieved using this Xpath:
//app-for-homes[1]/ion-header/ion-toolbar/ion-buttons/ion-button[#name='button-open-menu']
However, this only works where the order in which the elements appears is known.
Better Answer
When you have exactly 1 element that is not hidden, Xpaths allow you to look at an elements ancestors as far back as you want to identify the presence / or absence of the hidden class. In this case, we start by finding the ancestor app-for-homes which does not include the ion-page-hidden class:
//app-for-homes[not(contains(#class,'ion-page-hidden'))]
and then simply append the remainder of the path to the desired element. Full answer =
//app-for-homes[not(contains(#class,'ion-page-hidden'))]/ion-header/ion-toolbar/ion-buttons/ion-button[#name='button-open-menu']

Testcafe - How to write testcafe selector to identify element with class contains

I need to write the location of an element in page which has just the tag name and only 1 attribute - class and the class value has number characters which is dynamic so I have to use contains to specify the element.
Could not traverse from parent node as it is a list with similar parent name.
Any Suggestions please??
You can use the Selector.withAttribute method.
For example, the following code finds an input with an attribute, which name ends with 'testId' and clicks on it.
await t.click(Selector('input').withAttribute(/.*testid/);

ExtJS how to prevent DomHelper from generate element id

When using Ext.DomHelper.append() method to generate html markup it sometime generate id attribute for the element, how can I prevent that from happen?
One option would be to supply your own ID through the id: config option. Ext.Element needs any DOM element it wraps to have an ID, so it will automatically create one whenever it touches a DOM element that doesn't already have one
Ext.DomHelper.append() returns Ext.Element by default. Ext.Element is wrapper for DOM node and Extjs adds id for corresponding node automaticaly while wrapping.
You can pass false as the third param and then Ext.DomHelper.append() will return DOM node instead of Ext.Element:
Ext.core.DomHelper.append(
Ext.getBody(),
{tag: 'div', html: 'bla'},
false // this is required in order to return DOM node instead of Ext.Element
);

Is there a way in Dojo to find all widget descendants in a DOM element?

Is there a way in Dojo to find all widget descendants in a DOM element? I used the example below it will only list the children of the element, in this case any widgets that are children of the document object, but not all the descendants or nested widgets. Hopefully that's clear.
var widgets = dijit.findWidgets(dojo.doc);
dojo.forEach(widgets, function(w) {
console.log(w);
});
I could just write my own recursive function but I want to make sure I'm not missing out on a Dojo method which already does this.
Many thanks
Hmm, dijit.findWidgets(parentWidget.domNode) ?
Edit Oh, now I nee findWidgets doesn't search recursively.
I checked the dijit.findWidgets source code and all it does is check for nodes with a widgetid attribute that are represented in the dijit registry. The following version uses dojo.query to do this same search recursively:
function findEvenTheNestedWidgets(innitialNode){
return dojo.query("[widgetid]", innitialNode)
.map(dijit.byNode)
.filter(function(wid){ return wid;}) //filter invalid widget ids that yielded undefined
}

Confusion using dijit.byId and dojo.byId

I am trying to understand the difference between
dijit.byId and dojo.byId
For this i have taken a Button and a div .(To set the
data inside the div on click of the Button)
Show Me!
<div id="findMe">
Hiya!
</div>
This is working (dojo.byId)
function callMe()
{
var node = dojo.byId('findMe');
node.innerHTML = "Hello World";
}
But this isn't working (dijit.byId)
function callMe()
{
var node = dijit.byId('findMe');
node.innerHTML = "Hello World";
}
My understanding is , when refering to the div we need to use dojo.byId
and when we are refering to Individual components use dijit.byId
Please correct me if i am wrong .
As previously stated, dojo.byId retrieves the DOM node with that id if existent.
dijit.byId retrieves the instance of a dijit._Widget (and its subclasses), that is dojo's abstraction of UI objects, rather than the widget's DOM node. But it is important to note that dijit.byId searches through the widgets by the atrribute "widgetId", not "id". These are equal if you declare your widgets by passing a container node that already has an "id", but still dojo creates an attribute "widgetId" for every widget if not specified explicitly.
This means that widgetId and id are usually the same, but it is possible that they are different. Plus, widgetId is always set for a given widget even in cases where the id attribute of the container node is absent.
This implies that you should use dojo.byId whenever you intend to work on the DOM tree itself and dijit.byId only in case where you'd like to obtain the instance of a certain widget instance. If no widgets are present, there is no reason to use dijit.byId at all.
You are right:
dojo.byId finds elements in the DOM tree of your website with a certain ID - it searches and returns HTML elements.
dijit.byId finds dijits you created with a certain id - it searches and returns dijits (javascript objects), although these objects usually refer to a certain DOM node.