How can I call a div class under div in watir? - ruby

I am creating automated test scripts with Ruby and Watir.
I am trying to call a div class from these lines of codes:
<div class="slimScrollDiv" style="position: relative; overflow: hidden; width: auto; height: 500px;">
<div class="modal-body" style="overflow: hidden; width: auto; height: 500px;">
<form id="user-form" class="form-inline" enctype="multipart/form-data" method="POST" novalidate="novalidate">
<fieldset></fieldset>
</form>
</div>
My aim is to use this one
browser.div(:class => '').send_keys :space because I want to scroll the div, for me to be able to send_key "" in some other textfield hidden.
I even try to use browser.scroll.to :bottom, but still it doesn't work.

So I am making some guesses as to what you are really trying to accomplish here. I'll first address your question as originally stated, then address how to do what I think you are trying to accomplish.
Selecting elements inside other elements
The high level answer is that there is nothing special to doing this, in many (most) cases you don't even need to worry about how deeply nested an element is, as long as you have a unique way to identify it, such as a class, name, etc that is unique.. For example in the code you provided, to get the div with class modal-body you would just do
browser.div(:class => 'modal-body)
If there were a lot of divs on the page with that class, then you might want to locate the one you want by looking inside some other container element that is unique so you find the right one.. in the code above that would be something like
browser.div(:class => 'slimScrollDiv').div(:class => 'modal-body)
Usually you only do that sort of thing when it is difficult to find an easy way to identify an element because it has few or no attributes, or non-unique attributes.
Scrolling a custom control
This I think is your real issue. You appear to have a control with a non-standard scrollbox. That is to say that instead of being simple HTML that is defined so that the browser creates and controls a scroll box (which would normally work with the methods you have already tried, or even get scrolled into view auto_magically) you instead have a custom control where the scroll box is driven by javascript code such as jQuery or Bootstrap. Such code usually is event driven, looking for things like mousewheel movement when the mouse is over the control, or manually grabbing and dragging the element that is being rendered to look like a scrollbar. Often such controls do NOT respond to keypresses like space or arrows, EVEN if they have been selected, clicked on, have focus etc.
Still I would first suggest try using .location_once_scrolled_into_view on the sub element you want that is inside the scrollbox. (See example in other answer) If that does not work then try manipulating the controls of the sçroll area.
Based on class values in your code fragment, I think you may be dealing with a jQuery powered 'slimScroll' control similar to those shown on this page. If that is indeed the case, then you can scroll the control by using drag methods on the scrollbar element. In slimScroll the element you want will be inside the div with class 'slimScrollDiv' and is another div with the class 'slimScrollBar'.
As long as the scrollbar is visible, you should be able to do a .drag_and_drop_by on it to scroll the content in the scrollbox. If it is not visible (as can happen in the first example on the linked page) then it may be harder, you might have to try firing mouseover events, or invoking some JS code to change it's style to not be hidden. You will need to experiment to see how many pixels to drag it at a time to scroll the window a 'right' amount based on how much content is in there. (potentially you might be able to figure that out based on the .style 'height' values for the elements, but that would take experimentation with the actual page and only needed if the amount of content in the box is variable)
For the second example on the linked page, I was able to scroll things using the following code
scrollbar = browser.div(:class => 'slimScrollBar', :index => 1)
scrollbar.drag_and_drop_by 0,10
I'm not sure what is inside your scrollbox, but for psuedo-code purposes of we just call it 'thing_I_want' then you might be able to scroll it into view with code something like this
scrollbar = browser.div(:class => 'slimScrollBar')
until thing_I_want.present?
scrollbar.drag_and_drop_by 0,5
end
as I said you might have to play with the drag distance there to get a 'right' amount, but 5 (pixels) seemed a reasonable starting place.

hidden text_field or just not visible in page?
you could try focus:
browser.text_field(:id => 'myid').focus
or if you need to scrolldown until it is visible
unless browser.text_field(:id => 'myid').visible?
browser.div(:class => 'slimScrollDiv').send_keys :arrow_down
end
or if you need to scrolldown to the footer (end of page)
browser.div(:id => 'footer').wd.location_once_scrolled_into_view

Related

I want to run aos fade up animation only once

When you enter the page for the first time, it should be fade up, but it's fade down. This problem seems to be caused by not only the fade-up effect when scrolling down the page, but also the fade-down effect when scrolling up the page. I only set the fade-up effect to the code.
How can I make it only fade up?
The web page and code are below.
https://www.dorothycard.com/v/48dc3e5f
<div class="mx-4" data-aos="fade-up" data-aos-duration="1500" data-aos-once=“true”>
When I inspect your page, all the animated elements have the following attribute:
data-aos-once=""true""
when that attribute should be:
data-aos-once="true"
The first sets the attribute to the string "true" which is quite different from the boolean true (which is what is expected).
I do not know how you set this attribute in your source, but you will want to look there for a fix to your issue.
Note that if you want ALL your animations in the page to only run once, you could also pass that option in the AOS.init() function call:
AOS.init({
// ... your other initialisation options here ...
once: true,
});
and you could then remove all individual data-aos-once attributes.

Handling Element is not clickable at point (x, y). Other element would receive the click: With Capybara, ruby, Webdriver

I am writing a UI test that goes to a list of articles and selects the load_more button until this is no longer available (because all articles have loaded). The problem is the button has been hidden at this point rather than removed and is returning this error
Selenium::WebDriver::Error::UnknownError: unknown error: Element <div
class="">...</div> is not clickable at point (x, y). Other element
would receive the click: <div class="" id="" data-module-name="">...
</div>
(Session info: chrome=65.0.3325.181)
(Driver info: chromedriver=2.36.540469
ruby-2.5.1/gems/selenium-webdriver
3.11.0/lib/selenium/webdriver/remote/response.rb:69:in `assert_ok'
I have tried a few loop types but for this, if we assume I'm using
while world.page.has_load_more?
world.page.load_more.click
break if world.page.has_load_more? == false
end
The question is how do I tell Selenium this is ok and not to error, so I can continue with the next step in my test case(cucumber). I realise that the choice of loop type may also be incorrect, so feel free to suggest changes there as well.
Firstly, as Rajagopalan has pointed out, the error that you're getting is not that your element is not visible (as in hidden by CSS) but that it is overlapped by another element. You can call save_and_open_screenshot to see what element is overlapping the button (possibly a fixed footer, etc?). Make sure you've set the window size large enough so you don't have elements unintentionally overlapping and make sure you're running the latest version of Capybara since it attempts to deal with overlapped elements in selenium by scrolling them into view if possible.
Secondly, the loop in your question doesn't make a lot of sense having both the while and break since they check the same thing. Also, assuming the "load more" button is loading and appending to the page via AJAX, you probably need to wait for the new elements to load before checking if the button exists (click does not wait for actions to complete since it has no idea what actions could/would be triggered). That would then become a structure something like
while page.has_button?('Load More')
# Get the current number of visible articles
article_count = page.all('div.article').count # Use whatever selector would match an article in the list
# click the button
page.click_button('Load More')
# ensure more articles have loaded
expect(page).to have_css('div.article', minimum: article_count + 1)
end
Note: You'll probably want to change that to use whatever page object methods you are using (has_load_more?, etc) but the general logic should be correct

How to set a span value with capybara?

Does anyone know how to set a value to span tag using capybara?
I tried using element.set or element.send_keys, they only selected the targeted element without modifing the previous value.
<div data-offset-key="bbpvo-0-0" class="_1mf _1mj"><span data-offset-key="bbpvo-0-0"><span data-text="true">aa</span></span></div>
HTML snippet is above, I want to set aa to bb.
Capybara is designed to emulate a user - A user can't edit a span unless there's some sort of javascript widget attached to it. If you have a JS widget attached to the span you would need to perform whatever actions a user would do in order to edit the span. So you say the user has to click on the span and then type on the span - if that is so then you could try something like
span = find('span[data-text="true"]')
span.click
span.send_keys("new content", :enter) # if enter is needed to end the editing
which may work - although I'm going to guess the element actually gets replaced with an input or something after it's clicked on, in which case you need to figure out what those elements are (using the browsers inspector) and then find and use send_keys or set on that element instead
To set text in span value,jquery can be used with capybara as shown below:
page.execute_script("$("<span css selector>").text("testing")");
or
page.execute_script("$("<span css selector>").html("testing <b>1 2 3</b>")");

onclick does not fire in first Item in GalleryView 1.1

So I have a page using GalleryView 1.1 here. I like the behaviors just fine except that the left-most item's onclick event won't fire for some reason.
I also grabbed the 2.1 version from the GoogleCode page; the author's page at http://spaceforaname.com/ has gone. So here is a page implementing 2.1.
Since 2.1 has a bunch of behaviors I hate and seems to completely prevent my onclick events I would like to sort out the issue with the left-most item's onclick in the v1 page.
I have read through the code but failed to find what is interfering.
The function looks like this:
$('.myslides').click(function() {
//alert($(this).attr('alt'));
$('#big_pic').attr("src", $(this).attr('alt'));
return false;
});
and the items like this
<li><img src='g/weddings/slides/1.jpg' width='165' height='110' alt='/g/weddings/slides/1_big.jpg' class='myslides'/></li>
I have tried moving the class attribute to the LI, and also adding an anchor around the image and giving it the class but neither of these had a visible effect.
// Edit
The page validates and yes I know the big pics are blurry. Don't have them from GD so did best I could stretching thumbs.
Does anyone have an idea of how I should pursue debugging this?
So when inspecting the elements in question I found that the working thumbnails were all image elements but the non working first thumbnail was a div with id "pointer".
Since the author's site with the docs has evaporated I can say what function #pointer has in my filmstrip slides but in jquery.galleryview-1.1.js on line 319 I changed its width to 1px in the JS CSS and this resolved the issue of the obstructed onclick. #pointer may have a function I am not employing here. At any rate the issue is resolved.
Width was previously set to
'width':opts.frame_width-pointer_width+'px',
Now set to
pointer.attr('id','pointer').appendTo(j_gallery).css({
'position':'absolute',
'zIndex':'1000',
'cursor':'pointer',
'top':getPos(j_frames[0]).top-(pointer_width/2)+'px',
'left':getPos(j_frames[0]).left-(pointer_width/2)+'px',
'height':opts.frame_height-pointer_width+'px',
'1px',
'border':(has_panels?pointer_width+'px solid '+(opts.nav_theme=='dark'?'black':'white'):'none')
});
Also tried adding display:none but this resulted in jerky animation.

JQuery Cycle plugin: overlay nav buttons?

I'm trying to using the jQuery cycle plugin (http://www.malsup.com/jquery/cycle/) to create a banner like the one on this page: http://www.epa.gov/. Specifically, I'd like the navigator buttons to lay on top of the images. The way it is done on epa.gov is the nav div is absolutely positioned on the page, so you have to absolutely position that div on every page you want to use it on. The easier solution would be to relatively position the nav div in the div that holds the images I want to scroll. The problem is I don't see how you can do that.
The code for cycling images is:
$('#banner').after('<div id="nav"></div>').cycle({ fx: 'fade', speed: 1000, timeout: 5000, pager: '#nav', autostop: true, autostopCount: 5 });
the "after" function creates the nav div and the pager option makes that div the navigation for the banner div, which holds the images, but the nav div is created either before or after the banner div. I want the nav div to be created inside the banner div so that I can relatively position it in that div, since it is the one that actually holds the images. Is this possible? Is there a different plugin I should be using for this?
There's actually a very similar example right on Malsup's example page here:
http://jquery.malsup.com/cycle/pager-over.html
Go to 'even more demos', and it's the top one (pager on top of slideshow).
It was hard to find, and the only reason that I know it was there was because I've spent hours there!

Resources