Question: How would you E2E test a SPA with many custom elements which are created multiple times and able to retrieve them by unqiue ID?
The problem we have is to unique identify the custom elements. Thus, you can't place an id inside the custom element like this:
<customelement id="MyCustomElement"></customelement>
because as you would instantiate the custom element multiple times the id will be added twice to the DOM.
Aurelia uses protractor as E2E test tooling. Including the Aurelia flavoured locator to retrieve/check value.bind="VMproperty" syntax. The elment(by.valueBind("VMproperty")) won't work for multiple custom elements which have the VMProperty.
We're thinking in creating somekind of breadcrumb which includes the parent id, creating an unique ID for that specific custom element.
I'm sure people would be using Aurelia for larger projects/sites and require proper E2E testing. The example on Aurelia HUB: http://aurelia.io/hub.html#/doc/article/aurelia/testing/latest/end-to-end-testing/5 is fine for initial setup, but doesnt state in how to E2E test mulitple custom elements.
Any help would be appreciated :)
It sounds like you could walk down to the custom element from the parent element with $('#parentID customelement') if there's just one of them.
If you have multiple custom elements within the parent, you can just get all of them with $('#parentID').$$('customelement') and iterate through the ElementArrayFinder.
If you don't have to worry about custom elements within other parent elements, you could even just use $$('customelement') to grab all of them in an ElementArrayFinder.
To go over each element in the ElementArrayFinder when you don't know the order, I tend to go two ways.
The first way filters the ElementArrayFinder down to the ElementFinder you want:
var item = $$('.someclass').filter((elem)=>{
return elem.isWhatIWant(); //chose any qualifier that returns a boolean
}).first();
expect(item.isWhatIWant()).toBeTruthy();
The second way goes over and checks each element:
$$('.someclass').each((elem)=>{
expect(elem.isWhatIWant()).toBeTruthy();
})
I use the second way more often, since you can always add qualifiers within the each to determine which elements should be checked, but the first way can be better if you want to save the ElementFinder for later use.
Related
The component I have has a list of names with an add button beside each
<h1>Select one of me!</h1>
<div>
<button>contrived</button>[I am already selected]
<button>example</button>
<button>beep</button> [I am already selected]
<button>boop</button>
</div>
<h1>Selected</h1>
<button>contrived</button>
<button>beep</button>
If I wanted to select beep or contrived in the bottom list, how should the buttons be configured so that I can easily find them without test-ids or using my knowledge of the current structure (i.e. I want to avoid getting the parent element and using the within helper if there's a better way).
Without using explicit test IDs or other attributes, you could use the getAllByText query to retrieve both and use the one you want.
const [firstBeep, secondBeep] = screen.getAllByText('beep')
This does assume you have knowledge about their ordering in the DOM, but doesn't take into account the structure itself.
This probably applies to other UI libraries like Prime-NG and the like, but I'm using ng-lightning.
I am trying to grab the ngl-checkbox element with a querySelector in one of my unit tests.
fixture = TestBed.createComponent(Component);
fixture.debugElement.nativeElement.querySelector('ng-lightning element here?');
I tried adding an id attribute on the ngl-checkbox and also the input within the ngl-checkbox tags, but that doesn't work. Since the ng-lightning element renders into a bunch of different things, what do I need to pass into the querySelector to get that checkbox?
Another thing is how do I target the ng-lightning element in an external css file? I can't just target that element like a regular h1 tag.
I have been testing using protractor and no way to refer the element except via css because it only do have class attribute given. The problem is there are more than 7 elements having this class name. Thus I use the syntax
element.all(by.css('h4.ng-binding')).first();
for the first one and it works fine but for the others it doesn't work! I use the same logic that I used also for the first one. Here is my snippets code for the others to locate them.
element.all(by.css('h4.ng-binding')).second();
element.all(by.css('h4.ng-binding')).third();
element.all(by.css('h4.ng-binding')).fourth();
element.all(by.css('h4.ng-binding')).fifth();
element.all(by.css('h4.ng-binding')).sixth();
element.all(by.css('h4.ng-binding')).seventh();
element.all(by.css('h4.ng-binding')).eighth();
There are no functions of those kind in protractor. Only available functions are first(), last() and get(). You can implement everything using these 3 functions on top of the ElementArrayFinder. Here's how -
element.all(by.css('h4.ng-binding')).first(); //get the first element
element.all(by.css('h4.ng-binding')).get(0); //get the first element as get() function is a '0' based index
element.all(by.css('h4.ng-binding')).get(1); //get the second element
element.all(by.css('h4.ng-binding')).get(2); //get the third element
element.all(by.css('h4.ng-binding')).last(); //get the last element
Hope it helps.
Now you can use functions like .second(); .third(); .fourth(); etc. - I developed a small package - https://github.com/Marketionist/protractor-numerator - that can be used with protractor to select second, third, fourth, etc. elements.
Use nth-child i.e.
element.all(by.css('h4.ng-binding:nth-child(2)'))...
I am still experimenting how far I can go with building a widget in Polymer and I am stuck in one place. I want to create an element with children that are also polymer elements. Something like:
<my-view name="Hello">
<my-child-view attribute="test">Test</my-child-view>
<my-child-view attribute="test1">Test2</my-child-view>
<my-child-view attribute="test2">Test3</my-child-view>
<my-child-view attribute="test3"></my-child-view>
<my-other-child-view var="test5"></my-other-child-view>
</my-view>
I want to get children that are the tag name "my-child-view". Using this.children takes all the children. Is there a native polymer functionality like this.getChildrenWithQuery('my-child-view')? Or should I just loop through children and check the ones with tag name myself?
this.querySelectorAll('my-child-view')
Native JS DOM! Yes, querySelectorAll() works on elements as well as the document.
Actual case is much more complicated but please play along. I am trying to select siblings of element that has class 'sss', by using
$('.sss').parent().parent().find(">div.childCollapsible>div[data-onthemovecollapsible=true]")
I can only use CSS selectors (this is part of Selenium thest). I expected to get only siblings of 'sss' however I am getting all the children of sub elements too.
How could I restrict it only to siblings?
or any other workaround that can get me from any element in the tree siblings only of any
data-onthemovecollapsible="true"
attribute holder.
EDIT: Firstly I would like apologise for failing to express myself clearly. The structure that I am working with is 'infinite tree structure' that has unknown amount of nodes on each layer, mechanism I am looking for is ability to get siblings on the same level that I am starting search from is and only children of his parent (his brothers + himself). All levels of tree have identical HTML syntax, so looking at them relatively from element one starts from, each layer is identical, hence the CSS selector should be identical too. I cannot use any other Jquery method but 'find', and only can use CSS selectors, as mechanism is part of selenium test so only By.CssSelector("...") can be used. I can traverse up the elements by using element.FindElements(By.XPath("..")) that gets me parent as I know how many levels up parent is, but from parent position I need to get all siblings without children (that have identical html syntax) in one go, so i would assume selector with only certain layer should do (like one in jsfiddle below), however it selects all the children nodes too - does not respect '>' for some reason. This would do nicely if I could use all JQuery functions.
$('.sss').parent().parent().children().children()
what I need is same result but with CSS selector.
http://jsfiddle.net/2a46U/
I think this will work for you:
.find("body>div>div>div>div.childCollapsible>div[data-onthemovecollapsible=true]")
If I'm understanding this correctly, you have two different restrictions here. One is that you only want siblings of an .sss element. The other is that the parent of the element is div.childCollapsible. I don't believe you will be able to do this with a single selector/find. You would need something like this:
// get the siblings of .sss with appropriate data attribute
var $els = $('.sss').siblings("div[data-onthemovecollapsible=true]");
// filter the collection to only those with appropriate parent
$els = $els.filter(function(){
return $(this).parent().is("div.childCollapsible");
});
http://jsfiddle.net/2a46U/4/
I've updated your jsfiddle with two options (check the console please):
Get all the siblings:
$('.sss').siblings();
Get specific siblings:
$('.sss').siblings("div.AppletBase")
If you need to set styles you can use the siblings selector in CSS3:
.sss ~ div.AppletBase {/* Your styles in here */}
Anything please leave a comment and I will review it again if is needed