can there be a divs method in PageObject::Accessors and is my workaround ok? - page-object-gem

In page object I would like to have access to multiple divs in a particular way.
This is access to the first div that matches:
div(:search_result, id: /rptSearchResults/)
This would be access to multiple divs that match if divs existed in PageObject::Accessors:
divs(:search_result, id: /rptSearchResults/)
So far I have tried:
visit_page SearchResultsPage do |page|
#This outputs the first div that matches
page.search_result_element.div_elements(id: /rptSearchResults/).each { |i| puts i.text }
#This accesses the page and outputs text in all divs that match
page.div_elements(id: /rptSearchResults/).each { |i| puts i.text}
end
Can anyone suggest a better way of doing this within page-object?
Thanks in advance...

By using the way you defined multiple divs, divs(:search_result, id: /rptSearchResults/), you can access the elements by search_result_elements.
Some examples:
Get the first div element - search_result_elements[0]
Get the length of elements returned - search_result_elements.length
Get the texts of the divs - search_result_elements.map(&:text)
Get a child element from the third div - search_result_elements[2].element
Hope this helps!

Related

What is the problem with my JS function searching html classes and conditionally hiding or showing?

I am trying to modify a Dawn 2.0 theme to, on the product page, only render images with certain tags depending on an input selector. I have one product which consists of 8 items, each item has an image. This product can be ordered in three variations:
The first variation would be the product with 4 items.
The second variation would be the product with 6 items.
The third variation would be the product with 8 items.
There is a variant selector in the products page:
and the three variants have been created on the Shopify admin products page. The solution that I'm attempting to use is this one. I chose it as it's the only one I found reference to elsewhere (apart from buying an add on which I don't want to do), it seemed a logical approach to me, though I have no particular loyalty to this approach if anyone can think of a better way to achieve what I'm trying to.
This solution involves using values assigned to image's alt text attribute via the Shopify admin products page. The alt text values applied are:
set_all for the first 4 images, because these 4 items would be included in all three of variants (the one with only x4 itmes, the one with x6 items, and the one with x8 items).
set_6&8 for the 5th and 6th images, because these 2 items would be included in both the 2nd variant (the one with x6 items) and the 3rd variant (the one with x8 items).
set_8 for the 7th and 8th images, because these 2 items would only be included in the 3rd variant (the one with x8 items)
Then interpolating that alt text value into a data tag in the html:
data-thumbnail-set-number="{{media.alt}}"
which is applied to the <li> that each image is housed within and then writing a js function which:
hides all images
stores in local variable the alt text value of the featured image ('featured image' being the one, and only, image that you can apply to each variant in the Shopify admin products page. Therefore if the user selects a different variant a different featured image with different alt text is attached to that variant).
shows the images whose data-thumbnail-set-number value matches the value from the variant's featured_image.alt text. JS being:
'./assets/global.js' in VariantSelects class, line ~561
onVariantChange() {
...
this.filterThumbnails();
...
};
filterThumbnails() {
if (this.currentVariant.featured_media != null && this.currentVariant.featured_media.alt != null) {
document.querySelectorAll('[data-thumbnail-set-number]').forEach(function(el) {
el.style.display = 'none';
});
// show thumbnails for selected set
var selected_set = this.currentVariant.featured_media.alt;
document.querySelectorAll('[data-thumbnail-set-number="' + selected_set + '"]').forEach(function(el) {
el.style.display = 'block';
});
}
else {
//show all thumbnails
document.querySelectorAll('[data-thumbnail-set-number]').forEach(function(el) {
el.style.display = 'block';
});
}
// console.log("thumbnail update", this.currentVariant.featured_media.alt)
}
This all works apart from two problems:
I need to write further conditions in the JS to not just match the featured_image.alt text but to also include:
the set_all images as those items come with all 3 variations, and for the set_8 variant to include the set_6&8 images. I should be able to deal with this fine, will probably hard code the data-thumbnail-set-number that each three conditional is looking for.
Even though the JS function seems to be effective at searching and showing the images with a data-thumbnail-set-number value that matches the variant's featured image alt text value, the page also always seems to render one other image, which does not have the data-thumbnail-set-number class applied to the <li> at all, and it seems that that image is always the first of the images saved to the main product.
Despite a good deal of time looking I can't seem to understand why issue 2. is happening, and how to stop it. Can anybody help me solve this?
PEBCAK 🥴
To solve issue 2, I found that another <li> is inserted in the main-product.liquid above the <li> which iterates and shows all images in the image colleciton just to show just the featured image. I don't really understand why this featured image is separated out for rendering apart from the others in the collection, but it it. I just needed to add the data-thumbnail-set-number="{{media.alt}}" into this newly found featured image <li>.
As i took some time to write out this question I thought that I'd leave it here in case it's of help to anyone else.

Get multiple elements from span inside of div - Python 3 Selenium

I am trying to extract two elements from span inside of div.
The HTML code is:
<div id="market_commodity_buyrequests">
<span class="market_commodity_orders_header_promote">16337</span>
" requests to buy at "
<span class="market_commodity_orders_header_promote">$6.67</span>
" or lower"
</div>
I am trying to extract the second element (the price) from span but can only seem to get the first element to show up. What am I doing wrong?
Here is my code:
driver.get('https://steamcommunity.com/market/listings/730/AK-47%20%7C%20Redline%20%28Field-Tested%29')
data = driver.find_element_by_xpath('//div[#id="market_commodity_buyrequests"]//span[#class="market_commodity_orders_header_promote"]')
print(data.text)
which returns the response:
16337
I need it to return the "$6.67" instead. Thanks!
You are using find_element which is singular and only gets one element.
Use find_elements to get all of them and then loop through them to find your specific need.

How to find the index of HTML child tag in Selenium WebDriver?

I am trying to find a way to return the index of a HTML child tag based on its xpath.
For instance, on the right rail of a page, I have three elements:
//*[#id="ctl00_ctl50_g_3B684B74_3A19_4750_AA2A_FB3D56462880"]/div[1]/h4
//*[#id="ctl00_ctl50_g_3B684B74_3A19_4750_AA2A_FB3D56462880"]/div[2]/h4
//*[#id="ctl00_ctl50_g_3B684B74_3A19_4750_AA2A_FB3D56462880"]/div[3]/h4
Assume that I've found the first element, and I want to return the number inside the tag div, which is 1. How can I do it?
I referred to this previous post (How to count HTML child tag in Selenium WebDriver using Java) but still cannot figure it out.
You can get the number using regex:
var regExp = /div\[([^)]+)\]/;
var matches = regExp.exec("//[#id=\"ctl00_ctl50_g_3B684B74_3A19_4750_AA2A_FB3D56462880\"]/div[2]/h4");
console.log(matches[1]); \\ returns 2
You can select preceeding sibling in xpath to get all the reports before your current one like this:
//h4[contains(text(),'hello1')]/preceding-sibling::h4
Now you only have to count how many you found plus the current and you have your index.
Another option would be to select all the reports at once and loop over them checking for their content. They always come in the same order they are in the dom.
for java it could look like this:
List<WebElement> reports = driver.findElements(By.xpath("//*[#id='ctl00_ctl50_g_3B684B74_3A19_4750_AA2A_FB3D56462880']/div/h4")
for(WebElement element : reports){
if(element.getText().contains("report1"){
return reports.indexOf(element) + 1;
}
}
Otherwise you will have to parse the xpath by yourself to extract the value (see LG3527118's answer for this).

Wordpress - Consecutive Nested Shortcode Execution Fails Without Line Breaks

If I have multiple items nested at the same level, such as a list and a enter it as such into the content of the page:
[list]
[list_item]My Item[/list_item]
[list_item]My Item[/list_item]
[list_item]My Item[/list_item]
[/list]
It renders fine. If I do the same and format it like this:
[list][list_item]My Item[/list_item][list_item]My Item[/list_item][list_item]My Item[/list_item][/list]
Every second list_item doesn't render properly. Does anyone know why this is and how to fix it?

<span> </span> in Table<td>

I have a time table as below:
<table id="timetable">
<tr><td>00:00</td><td id="tm0"></td></tr>
<tr><td>00:30</td><td id="tm1"></td></tr>
<tr><td>01:00</td><td id="tm2"></td></tr>
<tr><td>01:30</td><td id="tm3"></td></tr>
</table>
so if i want insert <span></span> into <td> start from id="tm0" - id="tm3" how can i make it ?? instead of "rowspan" can anyone help ??
First get td elements using getElementById if you want frm 0 to 3 loop through the elements using something like ById("tm"+i).
Create the span element using creatingElement and set its properties.
Append this new element to the element retrieved in setp 1.
http://www.w3schools.com/DOM/dom_element.asp
But you are asking for this, in place of rowspan- which carries dynamic values. So i'm not user if i answered your query. But let us know why you want to use span in place of rowspan ?
Using jquery you can do it like following process:
$('table td:last-child').append('<span></span>');
You can't. Elements are arranged in a hierarchy. If the start tag for X is a child of Y, then the end tag for X must also be a child of Y.