I have some XML that looks like so:
<closure1>
<topClosure>
<ellipsoidalHead>
<standardComponentData>
<variousElements>
<idNumber>234567</idNumber>
<nominalThickness units="in">0.3750</nominalThickness>
</standardComponentData>
</ellipsoidalHead>
</topClosure>
</closure1>
<shell>
<standardComponentData>
<various_elements>
<nominalThickness units="in">0.6250</nominalThickness>
<idNumber>123456</idNumber>
</standardComponentData>
</shell>
<nozzle>
<standardComponentData>
<various_elements>
<attachedToidNumber>123456</attachedToidNumber>
</standardComponentData>
<nozzle>
In my JS code, I already have the <nozzle> element bomNode as a jQuery set, i.e.
var bomNode = $("nozzle");
So, for each nozzle element, I need to
Get the value of <attachedToidNumber> in the <nozzle> element.
Find the element that contains the <idNumber> that matches
<attachedToidNumber> (<shell> in this case).
Get the value in the <nominalThickess>
element.
As you can see, the depth of the desired <idNumber> element can vary. This is also a very small subset of the whole XML structure, so it can be very large.
I've tried something like this:
var attachedToElement = bomNode.parents().find('idNumber').text() === attachedToId;
but I get false returned. What's the easiest way to get the desired idNumber value? I'm sure it's something simple, but I'm just missing it.
Thanks.
UPDATE: I realized that bomNode is at the top level, I don't need to go up. a level. Doing something like this
var attachedToElement = bomNode.parents().siblings().find('idNumber')
gives me a list of children elements that have an <idNumber> element. So, I need to find the one that has the desired value. My thought is to use .each(). However, that value is defined outside of the .each() function, so I don't have anything to match against. Once I have the list of matches, what's the easiest way to get the set that has the <idNumber> value I want?
You were right - you missed a simple thing:
shell is not a parent of nozzle. They are siblings. Try this:
var attachedToElement = bomNode.siblings().find('idNumber').text() === attachedToId;
But this would return true (if true) - not the actual value.
Related
how to fetch the values of all paragraph (p) at a time ..
for example below is how my inspect view looks like
"testing sample one."
"testing sample two."
and below is my code sample to extract the value of id 'run'
browser.findElement(by.css('[id=run]')).getText()
this just extract the first value or I can modify and get the second value of id.. my need is I need to get both values at one go.. in the same line of code.. could you please advise
Though missing an html-example and a bit more description of what you like to extract, I'll give it a try.
In general you could/should use element.all(by.css()), aka $$(), instead of browser.findElements, except you know exactly, why you use findElements.
Read some details about the difference here.
Then as mentioned in a comment already, there is a findElements() (see API-Doc for findElements() here), returning an array of all values, matching the criteria. Just you can't immediately use getText() on it, as you get an array of elements and getText() requires a single element (see API-Doc for getText() here). Therefore you'd need to pass it through some loop.
Without knowing enough context here a small set of ideas to pick from.
var allP = new Array();
var allPString = null; //if one long string is desired
//here I'm using now element.all() instead of browser.findElements
var allPEl = $$('p#run'); //equal to element.all(by.css('p[id=run]')); //returns array of all found elements
var allPElBrowser = browser.findElements(by.id('run')); //returns array of all found elements
var i = allPEl.length();
var j = 0;
allPEl.each().getText().then(function(text){ //getAttribute('value') instead of getText(), if getText doesn't work.
allP.push(text); //add it to Array
allPString += text+' '; //add to String with a space at the end
j++; //counter
if(i === j-1){continueTest()}; //call continuation at the end of last loop, due to asynchronous nature of 'then()'.
});
continueTest = function(){
allP.toString() //in case of comma separated list from Array is desired
// here comes the rest of your test case logic
};
Note, that I go with the assumption that you need resolved promises, so the content of your <p>'s to continue.
If you can continue just with the array of <p>-objects, which you later resolve within an expect() all you need is $$('p#id');.
If the solution doesn't work for you, let me know, what part is still missing or where problems occur.
I am trying to access child element of an ng-repeat element but I am having troubles doing that.
I have searched around about the problem and the solutions that I have found did not work for me. One of those solutions was to do something like this:
var parent = element(by.repeater(''));
var child = parent.element(by.....);
When I try the child line I cant see the element function on the parent element..
http://prikachi.com/images/11/8338011u.png
If you see the screenshot above you will see the structure of the code of the page that I am trying to test.
I need to access the alt attribute of the image of the avatar and get its value (thats the Username of the User).
One thing that came to my mind is to use .getInnerHTML() on the ng-repeat row which will return a string with all that code. From there I can find the alt attribute and its value with string manipulation but this seems too brute and I am sure that there has to be a better way.
Simply I want to be able to get row 4 from the repeater and get the Username of the user at row 4, that's all I wanna do actually.
Try this,
var parent = element(by.repeater('f in feed'));
var child = parent.all(by.xpath('//img[#alt="Pundeep"]')).first()
(or)
var parent = element(by.repeater('f in feed'));
var child = parent.all(by.xpath('//img[#alt="Pundeep"]')).get(0)
You can get it directly using element.all() and get() locator in protractor. Here's how -
var child = element.all(by.repeater('parent_locator')).get(3); //gets 4th element in repeater. Its a 0 based index.
child.getAttribute('alt').then(function(user){
var username = user; //username contains the alt text
});
Hope this helps.
In Protractor element documentation it gives an example like this to find child elements, which is same as chaining element find:
// Chain 2 element calls.
let child = element(by.css('.parent')).
$('.child');
expect(child.getText()).toBe('Child text\n555-123-4567');
// Chain 3 element calls.
let triple = element(by.css('.parent')).
$('.child').
element(by.binding('person.phone'));
expect(triple.getText()).toBe('555-123-4567');
// Or using the shortcut $() notation instead of element(by.css()):
// Chain 2 element calls.
let child = $('.parent').$('.child');
expect(child.getText()).toBe('Child text\n555-123-4567');
// Chain 3 element calls.
let triple = $('.parent').$('.child').
element(by.binding('person.phone'));
expect(triple.getText()).toBe('555-123-4567');
https://www.protractortest.org/#/api?view=ElementFinder.prototype.$
this example could help :
return element(by.css('select.custom-select:nth-child(1) option[value="12"]'));
you can use nth-child() selector to access to a child element.
In my example i used a plugin with 2 select with same classes and i wanted to click on a defined option in the select 1, and a second in the select 2.
I have this line at the very beginning of a Chrome extension:
var macroXML = parser.parseFromString(localStorage["myMacro"], "text/xml").getElementsByTagName("section");
After doing some changes, I try to update macroXML, but nothing happens.
alert(macroXML[1]);
macroXML[1] = 'RAWR';
alert(macroXML[1]);
No errors, no anything. It outputs the exact same thing.
Anyone perhaps know why?
You are dealing with a dynamic nodes list. It will change if the document changes, e.g. to remove the second element from the list you can do:
macroXML[1].parentNode.removeChild(macroXML[1]);
Or you replace it by a different node:
var newNode = macroXML[1].ownerDocument.createElement("section");
macroXML[1].parentNode.replaceChild(newNode, macroXML[1]);
But you cannot work with that list as you would do with an array - for that you need an actual array. You can copy the list like this:
var macroArray = Array.prototype.slice.apply(macroXML);
macroArray[1] = 'RAWR';
This will work as expected then.
I'm having a bit of a brain fart here, and hoping someone can help me find a 1-line solution to this problem, without having to call .each().
So I get a list of all checkboxes within a container like this:
var checkboxes = $(':checkbox', '#surveyModal');
At some point later, I need to find out if any (or none) of the checkboxes are checked within that list.
I expected something like these to work:
$(':checked', checkboxes)
// or
checkboxes.attr(':checked')
// or
$(checkboxes).attr(':checked')
But it doesn't. The only thing I've had success with is calling each() and then checking each individually. But that means I'll have to keep a separate variable (.e.g. someAreChecked at a higher-level scope, which I don't feel is optimal.
checkboxes.each(function () {
if ($(this).attr('checked')) {
someAreChecked = true;
}
});
I was hoping that I can easily in a single line do such a check:
if (checkboxes.('get checked count') == 0)
{
}
Thanks in advance.
The filter function is what you're looking for :)
checkboxes.filter(':checked').length;
.attr returns the value of an attribute, and you have to pass the attribute's name to it, not a selector.
Just use .is instead.
Description: Check the current matched set of elements against a
selector, element, or jQuery object and return true if at least one of
these elements matches the given arguments.
$(checkboxes).is(':checked')
This should do it:
$("input[type=checkbox][checked]").length
Assuming I have this:
var wrap = $("#someId");
I need to access the original object that I would get by
var orig = document.getElementById("someId");
But I don't want to do a document.getElementById.
Is there something I can use on wrap to get it? something like:
var orig = wrap.original();
I searched high and low but I didn't find anything; or maybe I'm not looking for the right thing.
The function for this is get. You can pass an index to get to access the element at that index, so wrap.get(0) gets the first element (note that the index is 0-based, like an array). You can also use a negative index, so wrap.get(-2) gets the last-but-one element in the selection.
wrap.get(0); // get the first element
wrap.get(1); // get the second element
wrap.get(6); // get the seventh element
wrap.get(-1); // get the last element
wrap.get(-4); // get the element four from the end
You can also use array-like syntax to access elements, e.g. wrap[0]. However, you can only use positive indexes for this.
wrap[0]; // get the first element
wrap[1]; // get the second element
wrap[6]; // get the seventh element
$("#someId") will return a jQuery object, so to get at the actual HTML element you can do:
wrap[0] or wrap.get(0).
You can use get() to retrieve the HTML element.
var orig = wrap.get(0);
However, if wrap consists of multiple elements, you will need to know the correct index which to use when you use the get() function.
You can just use var orig = wrap[0]; as far as I know, if there's more than one element. If there's just the one, you can just use wrap without $() around it.
You can use wrap still.. Wrap is the same as 'orig' would be in the above! :)
If you really want:
var orig = wrap;