if page has selector - Capybara - ruby

I'm trying to implement a simple piece of logic that says if element exists on page do something`
The issue I am facing is that if the element doesn't exist then the find method provided returns an exception and will fail my test.
(Capybara::ElementNotFound)
so for example I want to do something like:
if page.find(".element")
do something
end
If the element doesn't exist then the test should just carry on as normal.
Is there a way to do this?

Consider using something like this:
if page.has_css?('selector')
do something
end
This method is described here

Related

What would be an easy way to check if a `q-input` element is in a error state?

I have q q-input with a data-cy="inputEmail" property
Is there an easy way to check if the q-input is in an error state ?
The data-cy prop is attached to the native input element and it looks like the only way is to use some relatively complex css selectors, for instance by checking if the input's parent's parent has a text-negative class ?
Ideally from an e2e perspective you want to test for what a user sees, for the presence/absence of the error message
cy.get('[data-cy="inputEmail"]')
.parent('.q-input')
.should('contain', 'must be a valid email')
If you look at the DOM, nothing changes on the input itself.
So assuming that in the error state text-negative class is added to the element, so you can assert the presence of this class like:
cy.get('q-input selector').should('have.class', 'text-negative')

how to call clear method on the element object

In my project I have located the text_Field via some other element(via label), something like
element.following_sibling(tag_name: 'input').send_keys 'something'
But now it's typing into the text_field without any problem but I am missing clear method of text_field as it combines both clear and type together. Now I have to call clear method on element.following_sibling(tag_name: 'input') but since it's returning element object, I couldn't do that. Is there any way I can call clear method here? Or can I pass this object by some way to the text_field() method? Any help appreciated.
I know it can be called by converting the watir element into selenium element as given below
element.following_sibling(tag_name: 'input').wd.clear
But here I am missing WATIR waiting time for an element.
This appears to be a limitation in Watir's adjacent methods:
klass = if !plural && opt[:tag_name]
Watir.element_class_for(opt[:tag_name])
elsif !plural
HTMLElement
elsif opt[:tag_name]
Object.const_get("#{Watir.element_class_for(opt[:tag_name])}Collection")
else
HTMLElementCollection
end
Notice that only the :tag_name is used for determining the element's class. For input elements, we need to also consider the type attribute so that we can the right sub-class.
We should fix this in Watir (logged as Issue 878), but in the mean time, you can manually correct the class (ie Watir::TextField) using #to_subtype:
element.following_sibling(tag_name: 'input').to_subtype.clear
I got an answer to my question now.
Here is the answer.
b.text_field(element: element.following_sibling(tag_name: 'input').wd).set 'something'
If anybody has any better idea, please write your answer.Thanks.

How to call a method on a local variable in Ruby?

Probably a stupid question but I was following along this article and came across a bit of code I couldn't quite grasp. Here it is:
class CreateArticle
attr_reader :validate_article, :persist_article
def initialize(validate_article, persist_article)
#validate_article = validate_article
#persist_article = persist_article
end
def call(params)
result = validate_article.call(params)
if result.success?
persist_article.call(params)
end
end
end
More specifically, the problematic line is this:
if result.success?
Here's my problem with it: where did the success? method come from? It's not default in Ruby, and result is a local variable, so it should be nearby. But even if it's just omitted in the code sample, where would it have to be defined for that line to work? Everywhere I tried to define it just gave me an 'undefined method' error.
For example, I tried to define it both in the CreateArticle class and in the (only alluded to) ValidateArticle class, the obvious culprits, but no dice.
Update:
The reason I ask is not so much about what success? does as it is because I'm interested in using the pattern in my code. So, for example, my version of the success? method could be just checking whether a value got updated, or an item was inserted into an array. For example, let's say it's just this:
def success? # or self.success?
return true
end
Problem is, I can find no place where I can put this that works. I even created a module just for it and included it into the class, and still it doesn't work (it just returns 'undefined method'). So I'm still at a loss as to where I would have to define such a method so that it would work the way it looks like it should.
It's a method that comes with rails. It checks.for a server response with a 200 code. If it gets a 200 code it returns true else it returns false. Read the rails API docs about it... https://apidock.com/rails/v3.2.3/ActiveResource/Response/success%3F
Actually . success? is a built in ruby method. Check here. What it actually does is checking Stat and returns a boolean.
I did some more digging around the blog and from what I found I suspect that the code is probably making use of the dry-monads gem:
You can explicitly check the type by calling failure? or success? on a monadic value.
It's not explicit in the code excerpt but it's the only thing that makes sense.

What can I put as my watir-webdriver page "element" in a condition where it's not there?

I'm testing a nightmarish website that in most situations sticks all the important stuff in an iframe.
However, there are other common situations where the system will, annoyingly, open a page in a new tab, but not wrapped in the iframe.
I'm trying to figure out a conditional method that will check for the existence of the iframe and use it, otherwise not.
Here's what I've come up with, so far:
# The browser object...
#br = Watir::Browser.new
"frm" is the conditional method I'm trying to get working...
# Just an example element definition...
def click_my_button
#br.frm.button(id: "button").click
end
I define it in Watir's Container module, like so:
module Watir
module Container
def frm
if frame(id: "iframeportlet").exist?
frame(id: "iframeportlet")
else
# This is the part that I can't figure out.
end
end
end
end
That works fine when the iframe is there, but not surprisingly I get a NilClass error when it's not.
So, my question is: what can go into the else clause to make it work? More broadly, is there perhaps a better way to accomplish this? As you can imagine, I really want to avoid having to define every element in the web site twice.
I figured it out, and it's quite simple. The frm method's else clause just needs a "self"...
else
self
end
That's it. I'd love to know if there are any hidden pitfalls with this approach, though.

How do I add a name.value to the header when generating a soap message from ruby with soap4r

I've created a driver from wsdl
When I invoke my request, I would like the header to contain an element, i.e, I want to see something like the following:
REPLACE_WITH_ACTUAL
blah blah blah
However, looking around, everyone talks about subclassing SOAP::Header::SimpleHandler and then injecting an instance into the driver.headerhandler
However, if I do that, then I end up with a nested header, i.e,
REPLACE_WITH_ACTUAL
So there must be a way to just add an element to the existing headerhandler so I can do something like
driver.headerhandler.AddElement("session", "123")
but I can't find any way to do that. I also tried things like
driver.headerhandler["session"]="123" and other such tricks, but I can't find any way to make this work.
Looking at driver.headerhandler.methods, I cannot see any obvious mechanism.
Would really appreciate a pointer to how to to this.
Well, a colleague in my team solved the problem above after looking at some of the typical examples that I had previously found including the one at http://dev.ctor.org/soap4r/browser/trunk/sample/soapheader/authheader/client2.rb
Turns out that the trivial (sigh) solution is to replace
def on_simple_outbound
if #sessionid
{ "sessionid" => #sessionid }
end
end
with
def on_simple_outbound
if #sessionid
#sessionid
end
end
Now, if you just name the header "session" (in the QName creation), you get the unnested header, exactly what I wanted.
I thought I'd paste my solution to my own problem on the assumption that others might be running into the same problem.

Resources