Capybara has_no_css? throws StaleElementReferenceError - capybara

I am using has_no_css? to verify if certain elements are no more visible in UI.
ex:- After clicking 'ok' on confirmation popup, popup should no more be visible in UI. To verify that we use
page.has_no_css?('.modal.dialog', visible: true)
Tests failing randomly at has_no_css? with Selenium::WebDriver::Error::StaleElementReferenceError: Element not found in the cache - perhaps the page has changed since it was looked up
I see people talking about this problem in few places(roughly few years old threads)..
https://github.com/jnicklas/capybara/issues/578 << Labeled as 'Waiting for response'
https://groups.google.com/forum/#!topic/ruby-capybara/O3Ib6INOP58
Currently I am catching this exception to overcome this issue.I would love to hear what are you folks who faced this issue doing/done ? Am I overlooking something and just blindly catching exception ?? suggestions please...
we are using capybara (2.3.0)

Related

ElementNotVisibleError when using headless chrome for testing in rails

I test following assumption And I click on the text "2018/2019" within ".year" with capybara/headless_chrome and constantly get the error
element not visible
(Session info: headless chrome=67.0.3396.87)
(Driver info: chromedriver=2.40.565386 (45a059dc425e08165f9a10324bd1380cc13ca363),platform=Mac OS X 10.13.5 x86_64) (Selenium::WebDriver::Error::ElementNotVisibleError)
I've already tried to adjust the window size, as suggested here. But it didn't work.
My step definition:
When(/^(?:|I )click on the text "([^"]*)"(?: within "([^"]*)")?$/) do |link, selector|
begin
page.find(:css, selector).click
end
end
The element is actually visible and found by Capybara
[1] pry(#<Cucumber::Rails::World>)> page.find(:css, ".year")
=> #<Capybara::Node::Element tag="a" path="/html/body/div[2]/div[2]/section/div[2]/div/div[1]/div[1]/div[2]/div/div[2]/ul/li/a">
But click fails
[2] pry(#<Cucumber::Rails::World>)> page.find(:css, ".year").click
Selenium::WebDriver::Error::ElementNotVisibleError: element not visible
Why doesn't click work here?
EDIT:
The HAML of the link is
%ul.facet_values
- unselected.each do |facet_value|
%li.filtered{data: {hayf: {text: facet_value.name.downcase}}}
= link_to facet_value.path, title: facet_value.name, class: 'year' do
=truncate("#{facet_value.name}", length: 24)
- if facet.has_counts?
%span.small="(#{facet_value.count})"
I tried headless testing with Poltergeist and got Poltergeist detected another element with CSS selector 'html body header div.container-fluid' at this position which was solved with .trigger('click') and the test passed.
Since this doesn't work in non-headless Chrome or Poltergeist, then the simplest answer is that the element isn't actually visible. Firstly remove the Capybara.ignore_hidden_elements = false setting since that makes no sense when testing an app, and will screw up all sorts of waiting behaviors. Secondly use save_and_open_screenshot to get a picture of what the page actually looks like before you are trying to click the link.
I'm guessing you'll see that the link isn't actually visible at that point and your test is missing a step a user would have to do to make the link visible, is it in a menu where you have to hover over a different element first? is it in a popup where you have to click on something else first?, does it need to be scrolled to? etc.
Finally, you'll generally have less issues if you stick with Chrome via Selenium. Poltergeist uses PhantomJS which hasn't been updated in quite some time and doesn't support modern JS or CSS which can lead to all sorts of strangeness.

Ruby Thread Deadlock in XMPP (xmpp4r)

I'm implementing a Google Talk listener that updates me with all my contact list items' presence.
require 'xmpp4r'
require 'xmpp4r/roster'
require 'xmpp4r/roster/helper/roster'
sender_jid = Jabber::JID.new('email')
client = Jabber::Client.new(sender_jid)
client.connect('talk.google.com')
client.auth('password')
client.send(Jabber::Presence.new.set_type(':available'))
#Presence updates:
client.add_presence_callback do |pres|
puts pres.from.to_s.split("/")[0] unless pres.nil?
puts pres.show.to_s.inspect unless pres.nil?
end
Thread.stop
client.close
The code works fine and the thread continues to listen on one gmail account but gives me this error after a few contacts appear:
client.rb:33:in `stop': deadlock detected (fatal)
from client.rb:33:in `<main>'
This other account for which this error appears has a lot more contacts with varying statuses. Can't seem to figure out why this is happening. Any help would be amazing.
Thanks.
Solved the problem through the logger. It was throwing a deadlock because there was a parsing error. There are certain contacts I have with characters that weren't able to get parsed.
It seems xmpp4r has not been updated in a while and my solution was to move over to a repo that some people have updated.
If anyone is having a similar problem check out:
https://github.com/whitehat101/xmpp4r
The parsing is done through nokogiri.
UPDATE:
there are a bunch of new maintainers who have forked over many of the updates from above + fixing other issues:
https://github.com/xmpp4r/xmpp4r

How to close all the windows before the next test in a test suite?

[7] pry(#<RSpec::Core::ExampleGroup::Nested_1>)> page.execute_script "window.close()"
Selenium::WebDriver::Error::NoSuchWindowError: Script execution failed. Script: window.close();
The window could not be found
[8] pry(#<RSpec::Core::ExampleGroup::Nested_1>)> page.driver.browser.window_handles
=> ["f1-2"]
I had a browser open with two tabs, the above command does close one but the last tab never closes. It is open but when I try to run page.execute_script "window.close()" it gives the above error.
page.driver.browser.window_handles.each do |handle|
page.driver.browser.switch_to.window(handle)
page.execute_script "window.close()"
end
The above code was working for me sometime back but doesnt work anymore. It gives the same error.
UPDATE:
When I use,
page.driver.browser.window_handles.each do |handle|
page.driver.browser.switch_to.window(handle)
page.driver.browser.close
end
it gives the following error Selenium::WebDriver::Error::UnknownError: 'auto_id' does not refer to an open tab
Two ways you can do it
In line with your technique using JS. You would first need to switch back to your first browser window (window_handle) and then perform "window.close()". (Not Preferred) (Not sure why its not working now for you, did you upgrade server version or different browser?)
Simply use #driver.quit (Preferred)
Update
Just write this once. This will close all windows.
after(:each) do
#driver.quit
end
If you want to close only one browser tab/window/popup, switch to that window_handle and then perform
#driver.close();
page.driver.browser.close closes current tab towards the end and the last (second) tab closes itself after each example.
in case if you are using cucumber, you can the use the BEFORE/AFTER hooks .please refer similar question on stackoverflow
for some more on cucumber,please refer this Cucumber Hooks

jquery-1.5.1.min.js and IE8

IE8 gives an error from jquery 1.5.1 minimized: Invalid argument, but firefox doesn't.
The error comes from this line:w
a.elem.style&&a.elem.style[a.prop]!=null?a.elem.style[a.prop]=(a.prop==="width"||a.prop==="height"?Math.max(0,a.now):a.now)+a.unit:a.elem[a.prop]=a.now}}}),d.expr&&d.expr.filters&&(d.expr.filters.animated=function(a){return d.grep(d.timers,function(b){return a===b.elem}).length});var ce=/^t(?:able|d|h)$/i,cf=/^(?:body|html)$/i;"getBoundingClientRect"in c.documentElement?d.fn.offset=function(a){var b=this[0],c;if(a)return this.each(function(b){d.offset.setOffset(this,a,b)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return d.offset.bodyOffset(b);try{c=b.getBoundingClientRect()}catch(e){}var f=b.ownerDocument,g=f.documentElement;if(!c||!d.contains(g,b))return c?{top:c.top,left:c.left}:{top:0,left:0};var h=f.body,i=cg(f),j=g.clientTop||h.clientTop||0,k=g.clientLeft||h.clientLeft||0,l=i.pageYOffset||d.support.boxModel&&g.scrollTop||h.scrollTop,m=i.pageXOffset||d.support.boxModel&&g.scrollLeft||h.scrollLeft,n=c.top+l-j,o=c.left+m-k;return{top:n,left:o}}:d.fn.offset=function(a){var b=this[0];if(a)return this.each(function(b){d.offset.setOffset(this,a,b)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return d.offset.bodyOffset(b);d.offset.initialize();var c,e=b.offsetParent,f=b,g=b.ownerDocument,h=g.documentElement,i=g.body,j=g.defaultView,k=j?j.getComputedStyle(b,null):b.currentStyle,l=b.offsetTop,m=b.offsetLeft;while((b=b.parentNode)&&b!==i&&b!==h){if(d.offset.supportsFixedPosition&&k.position==="fixed")break;c=j?j.getComputedStyle(b,null):b.currentStyle,l-=b.scrollTop,m-=b.scrollLeft,b===e&&(l+=b.offsetTop,m+=b.offsetLeft,d.offset.doesNotAddBorder&&(!d.offset.doesAddBorderForTableAndCells||!ce.test(b.nodeName))&&(l+=parseFloat(c.borderTopWidth)||0,m+=parseFloat(c.borderLeftWidth)||0),f=e,e=b.offsetParent),d.offset.subtractsBorderForOverflowNotVisible&&c.overflow!=="visible"&&(l+=parseFloat(c.borderTopWidth)||0,m+=parseFloat(c.borderLeftWidth)||0),k=c}if(k.position==="relative"||k.position==="static")l+=i.offsetTop,m+=i.offsetLeft;d.offset.supportsFixedPosition&&k.position==="fixed"&&(l+=Math.max(h.scrollTop,i.scrollTop),m+=Math.max(h.scrollLeft,i.scrollLeft));return{top:l,left:m}},d.offset={initialize:function(){var a=c.body,b=c.createElement("div"),e,f,g,h,i=parseFloat(d.css(a,"marginTop"))||0,j="<div style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;'><div></div></div><table style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;' cellpadding='0' cellspacing='0'><tr><td></td></tr></table>";d.extend(b.style,{position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",height:"1px",visibility:"hidden"}),b.innerHTML=j,a.insertBefore(b,a.firstChild),e=b.firstChild,f=e.firstChild,h=e.nextSibling.firstChild.firstChild,this.doesNotAddBorder=f.offsetTop!==5,this.doesAddBorderForTableAndCells=h.offsetTop===5,f.style.position="fixed",f.style.top="20px",this.supportsFixedPosition=f.offsetTop===20||f.offsetTop===15,f.style.position=f.style.top="",e.style.overflow="hidden",e.style.position="relative",this.subtractsBorderForOverflowNotVisible=f.offsetTop===-5,this.doesNotIncludeMarginInBodyOffset=a.offsetTop!==i,a.removeChild(b),a=b=e=f=g=h=null,d.offset.initialize=d.noop},bodyOffset:function(a){var b=a.offsetTop,c=a.offsetLeft;d.offset.initialize(),d.offset.doesNotIncludeMarginInBodyOffset&&(b+=parseFloat(d.css(a,"marginTop"))||0,c+=parseFloat(d.css(a,"marginLeft"))||0);return{top:b,left:c}},setOffset:function(a,b,c){var e=d.css(a,"position");e==="static"&&(a.style.position="relative");var f=d(a),g=f.offset(),h=d.css(a,"top"),i=d.css(a,"left"),j=e==="absolute"&&d.inArray("auto",[h,i])>-1,k={},l={},m,n;j&&(l=f.position()),m=j?l.top:parseInt(h,10)||0,n=j?l.left:parseInt(i,10)||0,d.isFunction(b)&&(b=b.call(a,c,g)),b.top!=null&&(k.top=b.top-g.top+m),b.left!=null&&(k.left=b.left-g.left+n),"using"in b?b.using.call(a,k):f.css(k)}},d.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),c=this.offset(),e=cf.test(b[0].nodeName)?{top:0,left:0}:b.offset();c.top-=parseFloat(d.css(a,"marginTop"))||0,c.left-=parseFloat(d.css(a,"marginLeft"))||0,e.top+=parseFloat(d.css(b[0],"borderTopWidth"))||0,e.left+=parseFloat(d.css(b[0],"borderLeftWidth"))||0;return{top:c.top-e.top,left:c.left-e.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||c.body;while(a&&(!cf.test(a.nodeName)&&d.css(a,"position")==="static"))a=a.offsetParent;return a})}}),d.each(["Left","Top"],function(a,c){var e="scroll"+c;d.fn[e]=function(c){var f=this[0],g;if(!f)return null;if(c!==b)return this.each(function(){g=cg(this),g?g.scrollTo(a?d(g).scrollLeft():c,a?c:d(g).scrollTop()):this[e]=c});g=cg(f);return g?"pageXOffset"in g?g[a?"pageYOffset":"pageXOffset"]:d.support.boxModel&&g.document.documentElement[e]||g.document.body[e]:f[e]}}),d.each(["Height","Width"],function(a,c){var e=c.toLowerCase();d.fn["inner"+c]=function(){return this[0]?parseFloat(d.css(this[0],e,"padding")):null},d.fn["outer"+c]=function(a){return this[0]?parseFloat(d.css(this[0],e,a?"margin":"border")):null},d.fn[e]=function(a){var f=this[0];if(!f)return a==null?null:this;if(d.isFunction(a))return this.each(function(b){var c=d(this);c[e](a.call(this,b,c[e]()))});if(d.isWindow(f)){var g=f.document.documentElement["client"+c];return f.document.compatMode==="CSS1Compat"&&g||f.document.body["client"+c]||g}if(f.nodeType===9)return Math.max(f.documentElement["client"+c],f.body["scroll"+c],f.documentElement["scroll"+c],f.body["offset"+c],f.documentElement["offset"+c]);if(a===b){var h=d.css(f,e),i=parseFloat(h);return d.isNaN(i)?h:i}return this.css(e,typeof a==="string"?a:a+"px")}}),a.jQuery=a.$=d})(window)
My code doesn't have an error...
I suggest that you debug your code, as the min version of jquery works just fine. You have a problem with your code that is indirectly causing an error in internet explorer and you have to do a work around.
My favorite thing (and what I did for a similar problem that I just figured out) is to
cut out all your javascript and run it to make sure that it works
paste it back in, a chunk at a time, testing each time
once you find the offending chunk of javascript code, cut that out and put everything else back in to make sure that is the only problem
narrow it down in that chunk to see where internet explorer is being retarded. If you are using PHP, you might need to do something like this to have internet explorer skip the code that is causing it to fail
$('li[title]').qtip({
style: {
name: 'dark',
background: $('.ui-widget-header:first').css('background-color')
<?php
//internet explorer is retarded
if(!preg_match('/MSIE/i',$_SERVER["HTTP_USER_AGENT"]))
{
echo ", tip: true";
}
?>
},
position: {
target: 'mouse',
corner: {
target: 'topLeft',
tooltip: 'bottomLeft'
}
}
});
I hope that helps! (If it did, please mark as answer)
I used the "slideToggle" from jquery version "jquery-1.6.4.min.js" on one big DIV element.
The "DIV" element has inside more html elements.
In internet explorer 8 (maybe on FF too) when I try to load the slideToggle function on this big DIV I received an error. Not sure what was the real cause of error but during my investigation I found a bug into the jquery:
_default:function(a){a.elem.style&&a.elem.style[a.prop]!=null?a.elem.style[a.prop]=(a.prop==="width"||a.prop==="height"?Math.max(0,a.now):a.now)+a.unit:a.elem[a.prop]=a.now}}})
There are situations when "a" variable is "NAN". Because of this I got some errors.
So I placed this check routine inside:
if(isNaN(a.now)){return;}
And all my problems gone.
_default:function(a){if(isNaN(a.now)){return;}a.elem.style&&a.elem.style[a.prop]!=null?a.elem.style[a.prop]=(a.prop==="width"||a.prop==="height"?Math.max(0,a.now):a.now)+a.unit:a.elem[a.prop]=a.now}}})
For me, this comes up when setting the padding or margins to a negative number. This has been discussed in a number of places online re: "IE negative padding". The following are the watch values from my IE console that prove this.
a.prop >> 'paddingTop'
a.prop==="width"||a.prop==="height" >> false
Math.max(0,a.now) >> 0
a.now >> -1.8277004484618357
(a.prop==="width"||a.prop==="height"?Math.max(0,a.now):a.now)+a.unit >> "-1.8277004484618357px"
a.elem.style[a.prop]=(a.prop==="width"||a.prop==="height"?Math.max(0,a.now):a.now)+a.unit >> Invalid Argument
experimenting:
- a.elem.style[a.prop] = '1px' >> '1px'
- a.elem.style[a.prop] = '-1px' >> Invalid Argument
The thread over at: StackOverflow: jQuery, IE & Animate proposes the following:
a.elem.style[a.prop]=(a.prop==="width"||a.prop==="height"?Math.max(0,a.now||0):a.now)+a.unit;
... which did nothing for me.
I don't really think this is a jQuery bug, and I haven't found it in their bug tracking system (I'll admit I haven't looked too hard), but rather an issue with IE not being able to handle negative padding/margins. It's a tough call whether jQuery should handle this or not ...
EDIT: This was opened as jQuery bug 4571, where they decided that the behavior was correct and that developers should be more careful in setting margins/padding values since a negative margin/pad really isn't valid. They went on to say that they wish FF would throw an error like IE. Wow! don't hear that often!

RTE validation not happening

https://gist.github.com/773349
RTE field validation is not happening if I traverse from RTE to RTE. Please find the attached git.
Steps to reproduce
Case 1
Focus into RTE1, type Hello
Tab out to text input (Node Selector)
Validation works
Case 2
Focus into RTE1, type Hello
Tab out to RTE2
Validation doesn't work
I tried with nightly build and was able to reproduce the above error and case 1 is failing too. An other difference that I noticed is "xxforms-value-change-with-focus-change" event is not fired when moved from RTE to RTE.
This is fixed as of 2011-01-24, and this fix will be included in the Orbeon Forms 3.9 release. Also see: [ #315639 ] RTE: values are not sent to the server when the RTE looses the focus.

Resources