Playwright: How to select element inside other element that has text - playwright

So I run into a problem with selecting an element within another element that contains text.
I have a list item, within the list item I have a link with a text and a button. So I try to do this like:
const listItem = this.page.locator('data-test-id=list-item:has-text('someText')')
const button = listItem.locator("data-test-id=button")
await button.click()
But it does not really do the trick and the element is not being found. What am I missing here?

Try this:
const listItem = this.page.locator('data-test-id=list-item', { hasText: 'someText' })
const button = listItem.locator("data-test-id=button")
await button.click()

Related

Priority web SDK method getSubform returns parent form

Parent form is the same I only change the company in the request and on some company i get parent form instead of sub form. So for example I have default company make a request get some form. According to user actions I change company in form request( but it is the same form name).
After that I try to get some sub form and on one particular company/form get the parent sub form instead of a child.
I already read topic about the problem that looks the same, but get rows and set active rows doesn't help me.
Do somebody had this problem?
async getDocuments(formName: string, getMappedRows: Function) {
const _currentOrderType = this.priorityService.getCurrentOrderType();
const _groupForm = await this.priorityService.getFormBridge(eSharedForm.GROUP.toString());
await _groupForm.setActiveRow(_currentOrderType.company.key);
const ListForm = await this.priorityService.getSubFormBridge(formName.toString(), _groupForm);
//some more logic
}
private async _getSubForm(name: string, form: any) {
try {
const subform = await form.startSubForm(name, this.onMessage, this.onUpdate);
debugger;
return subform;
} catch (e) {
this.subForms[name] = undefined;
const _e = JSON.stringify(e);
console.log(`[PriorityService::_getSubForm] Error starting subform '${name}': ${_e}`);
throw e;
}
}
and after that i see the same form as before
It is not clear from your code snippet what getSubFormBridge does or what is the value of _currentOrderType.company.key Is it numeric? is this the number of the row you want to retrieve?
When you start the Parent form, try to set autoRetrieveFirstRows to 1, which means, select the first row of the current form. If you know for sure what row you want to retrieve, pass the correct row number.
For example:
const form = await priority.formStart('ORDERS', this.onError, this.onSuccess, '', 1);
If you need to filter first and than select a row, use setActiveRow method and pass it the number of the row you want to retrieve. (Starts from 1)
Once the row is selected, retrieve the subform. For example:
const subform = await form.startSubForm("ORDERITEMS");

How to Drag and Drop an element using Proractor.net c# UI Automation

What will be the possible reason for the Drag And Drop functionality stopped working for me with Protractor.net c#?
Used http://marceljuenemann.github.io/angular-drag-and-drop-lists/demo/#/advanced to test this feature. But didn't worked for me.
Here is the sample code i tried:
Wait.Until(ExpectedConditions.ElementIsVisible(By.XPath("//h3[.='Container (effects allowed: all)']")));
var elem = NgDriver.FindElement(By.XPath("//h3[.='Container (effects allowed: all)']"));
IWebElement parentElement = elem.FindElement(By.XPath(".."));
IWebElement mov = parentElement.FindElement(NgBy.Repeater("item in container.items"));
Wait.Until(ExpectedConditions.ElementIsVisible(By.XPath("//h3[.='Container (effects allowed: move)']")));
var drropElem = NgDriver.FindElement(By.XPath("//h3[.='Container (effects allowed: move)']"));
IWebElement parentElement2 = drropElem.FindElement(By.XPath(".."));
IWebElement mov2 = parentElement2.FindElement(NgBy.Repeater("item in container.items"));
Actions builder = new Actions(Driver);
Actions action = builder.ClickAndHold(mov);
builder.Build();
action.Perform();
builder = new Actions(Driver);
action = builder.MoveToElement(mov2);
builder.Release(mov2);
builder.Build();
action.Perform();
Also Tried with DragAndDrop() function in thee Action .
Any help will be appreciated.
Create a Javscript file named "drop.js" and set the following content.
function e(e,t,n,i){var r=a.createEvent("DragEvent");r.initMouseEvent(t,!0,!0,o,0,0,0,c,g,!1,!1,!1,!1,0,null),Object.defineProperty(r,"dataTransfer",{get:function(){return d}}),e.dispatchEvent(r),o.setTimeout(i,n)}var t=arguments[0],n=arguments[1],i=arguments[2]||0,r=arguments[3]||0;if(!t.draggable)throw new Error("Source element is not draggable.");var a=t.ownerDocument,o=a.defaultView,l=t.getBoundingClientRect(),u=n?n.getBoundingClientRect():l,c=l.left+(l.width>>1),g=l.top+(l.height>>1),s=u.left+(u.width>>1)+i,f=u.top+(u.height>>1)+r,d=Object.create(Object.prototype,{_items:{value:{}},effectAllowed:{value:"all",writable:!0},dropEffect:{value:"move",writable:!0},files:{get:function(){return this._items.Files}},types:{get:function(){return Object.keys(this._items)}},setData:{value:function(e,t){this._items[e]=t}},getData:{value:function(e){return this._items[e]}},clearData:{value:function(e){delete this._items[e]}},setDragImage:{value:function(e){}}});if(n=a.elementFromPoint(s,f),!n)throw new Error("The target element is not interactable and need to be scrolled into the view.");u=n.getBoundingClientRect(),e(t,"dragstart",101,function(){var i=n.getBoundingClientRect();c=i.left+s-u.left,g=i.top+f-u.top,e(n,"dragenter",1,function(){e(n,"dragover",101,function(){n=a.elementFromPoint(c,g),e(n,"drop",1,function(){e(t,"dragend",1,callback)})})})})
And in your code
string jsScript = Path.Combine(currentDirectory, "JavaScript", "drop.js");
if (File.Exists(jsScript))
{
string dragAndDropScript = File.ReadAllText(jsScript);
IJavaScriptExecutor jse = (IJavaScriptExecutor)NgDriver;
jse.ExecuteScript(dragAndDropScript, dragFrom, dragTo);
}
drafFrom and dragTo are the controls used for dragging and dripping. These control should contain attributes like "draggable" or "dropable" in their HTML tag.

codeceptJS - how to click specific element from list

With protractor it's possible by doing element.all(by.css("li")).get(0)
How to do it with codecept?
I tried with no success:
I.click('.item').get(1);
I.click('.item:nth-child(2)');
Using XPath to click the element is the best option you have. However, you might have various instances of the element's tag. So your XPath has to be absolute
For example:
I.click("//li[contains(#class,'next')]");
or
I.click("//div[contains(#class,'next')]/li[1]");
Note: #class can be changed to whatever identifier you want to use.
You could just use XPath to click the first li element.
I.click('//li[1]');
It's also possible to grab all the elements that match a certain pattern and then specify the one you want by its index. In my case I needed to click all the checkboxes on a page. Here I grabbed all the elements that had the same xpath pattern (using I.grabNumberOfVisibleElements("//fieldset/label") and went through their indexes using a for loop.
module.exports = {
firstCheckbox: { xpath: '//li[1]//fieldset/label'},
async clickOnClassAssociations() {
await I.waitForElement(this.firstCheckbox, WAIT_FOR_TIMEOUT)
const totalCb = await I.grabNumberOfVisibleElements("//fieldset/label")
for (let i=1; i<=totalCb; i++) {
await I.waitForElement(`//li[${i}]//fieldset/label`, WAIT_FOR_TIMEOUT);
await I.click( `//li[${i}]//fieldset/label`);
}
},
};

Dart PaperDropdownMenu getting selected item

I'm kind of struggling getting the selected item id or even the text displayed in a dropdown menu list. Here's my code:
HTML:
<paper-dropdown-menu label="Currency" on-core-select="{{selectCurrency}}">
<paper-dropdown class="dropdown" halign='right'>
<core-menu class="menu" selected="{{selectedCurrency}}">
<template repeat="{{c in currencies}}">
<paper-item>{{c}}</paper-item>
</template>
</core-menu>
</paper-dropdown>
</paper-dropdown-menu>
Dart:
void selectCurrency(CustomEvent e, var detail, PaperDropdownMenu m) {
var id = m.getAttribute("selected");
//id = mCurrencyDropdown.selected;
JsObject detail = new JsObject.fromBrowserObject(e)['detail'];
if(detail['isSelected']) {
PaperItem selected = detail['item'] as PaperItem;
print( 'source | $selected' );
}
print(detail);
}
I can see several properties from which I might get the information I want but I can't access them as the don't seem to be public:
https://drive.google.com/file/d/0B9-4jVIpB0XuTXJ5eVBMZllyanM/view
Any idea? Thank you!
Thanks to Günter I have found the answer:
I have an observable like this:
#observable int selectedCurrency = 20;
Apparently you can simply add a method to your class matching the members name like this and it's called each time the observable is changed:
selectedCurrencyChanged(var oldValue, var newValue) {
print(newValue);
}
Official Documentation
Where is the field selectedCurrency you have bound to ?
I guess you can drop the on-core-select event handler entirely and instead add a method
selectedCurrencyChanged(newValue) {
// event handler code here
}

How do I turn these results into a list for use w/ Polymer's repeat attribute?

In the following code f.onChildAdded is an Instance of '_BroadcastStream<Event>':
f.onChildAdded.forEach((e) {
print(e.snapshot.val());
//TODO: Turn this somehow into a list
});
The print outputs each item fine, and now I'd like to turn it into a list that's friendly with Polymer's repeat="{{item in items }}" magic.
How do I turn it into a list? List myList = new List(); and myList.add(e.snapshot.val()); isn't helping me there.
How do I pass that from my main() in my index.dart to my-element.dart?
FWIW, here's my project: https://github.com/DaveNotik/dartstack. Any other guidance as I get a handle on this would be great!
At first you should ensure that your main look like shown here
how to implement a main function in polymer apps
in your main:
List myList = new List();
f.onChildAdded.forEach((e) {
myList.add(e.snapshot.val());
});
(querySelector('your-element') as YourElement).myList = myList;
or when you don't want to create a new list each time:
The list field in you custom element should look like
#observable List myList = toObservable([]);
in your main:
List myList = (querySelector('your-element') as YourElement).myList;
f.onChildAdded.forEach((e) {
myList.add(e.snapshot.val());
});

Resources