Checking values with Cucumber and Watir - cucumber

I've been trying to get started with Cucumber and Watir. I've done the installation and written/copied a simple 'feature'. However, I'm not getting anywhere with checking what's on a page.
This my feature:
Feature: Search Google
In order to make sure people can find my documentation
I want to check it is listed on the first page in Google
Scenario: Searching for JS.Class docs
Given I have opened "http://www.google.com/"
When I search for "JS.Class"
Then I should see a link to "http://jsclass.jcoglan.com/" with text "JS.Class v3.0"
My env.rb file looks like this
require 'watir'
require 'rspec'
And this is my search_steps.rb
#ie
Given /^I have opened "([^\"]*)"$/ do |url|
#ie = Watir::IE.new
#ie.goto(url)
end
When /^I search for "([^\"]*)"$/ do |arg1|
#ie.text_field(:name, "q").set(arg1)
#ie.button(:name, "btnG").click
end
Then /^I should see a link to "([^\"]*)" with text "([^\"]*)"$/ do |arg1, text|
puts arg1
# #ie.text.should include(arg1)
#ie.close
end
When I uncomment the line '#ie.text.should include(arg1)' I get this error thrown.
Then I should see a link to "http://jsclass.jcoglan.com/" with text "JS.Class v3.0" # features/step_definitions/search_steps.rb:13
true
undefined method `split' for ["http://jsclass.jcoglan.com/"]:Array (NoMethodError)
./features/step_definitions/search_steps.rb:17:in `/^I should see a link to "([^\"]*)" with text "([^\"]*)"$/'
features\search.feature:8:in `Then I should see a link to "http://jsclass.jcoglan.com/" with text "JS.Class v3.0"'
Failing Scenarios:
cucumber features\search.feature:5 # Scenario: Searching for JS.Class docs
Right now the Then function isn't doing its job. If I comment out the line then all it's really doing is writing out some text.
The gems I have include the following cucumber <1.1.9>, rspec <2.9.0>, watir<2.0.4> and watir-webdriver <0.5.3>
The version of ruby I have is: ruby 1.9.3p125.
I'm running this on Windows 7 Ultimate.
I'm wondering if I'm missing a gem or something. Reading the message implies that I'm calling a method it can't find but I've found quite a few pages on the web that use this method.
Any help, guidance or pointers in the right direction are gratefully welcomed.

The problem is that if you (manually) look at the text of the Google search results, you will noticed that there is no text "http://jsclass.jcoglan.com/". So, as expected, the test will fail.
To fix this, you can correct the call to the step by removing the 'http://':
Then I should see a link to "jsclass.jcoglan.com/" with text "JS.Class v3.0"
That said, it would be more robust if you actually make check for the link using the following code. Checking that the text is somewhere on the page can lead to false positives (see the latest post on WatirMelon)
#ie.link(:url => arg1, :text => text).exists?.should be true

Related

pgfopts: arguments with spaces don't play well with babel

If I define a new package like this
\NeedsTeXFormat{LaTeX2e}
\ProvidesClass{myPlanning}[2022/07/16 my Planning class]
\LoadClass[french]{article}
\RequirePackage{pgfopts}
\pgfkeys{
/myOrg/.cd,
lang/.initial = english , lang/.store in = \myOrg#lang,
title/.initial = title , title/.store in = \myOrg#title,
}
\ProcessPgfOptions{/myOrg}
\RequirePackage[\myOrg#lang]{babel}
and I try to compile this document
\documentclass[lang=french,title={truc bidul}]{myPlanning}
\begin{document}
some text here
\end{document}
I get the following error:
This is pdfTeX, Version 3.141592653-2.6-1.40.22 (TeX Live 2022/dev/Debian) (preloaded format=pdflatex)
restricted \write18 enabled.
entering extended mode
(./Test.tex
LaTeX2e <2021-11-15> patch level 1
L3 programming layer <2022-01-21>
(/home/hylkema/texmf/tex/latex/local/Org/myPlanning.cls
Document Class: myPlanning 2022/07/16 my Planning class
(/usr/share/texlive/texmf-dist/tex/latex/base/article.cls
Document Class: article 2021/10/04 v1.4n Standard LaTeX document class
(/usr/share/texlive/texmf-dist/tex/latex/base/size10.clo))
(/usr/share/texlive/texmf-dist/tex/latex/pgfopts/pgfopts.sty
(/usr/share/texlive/texmf-dist/tex/latex/pgf/utilities/pgfkeys.sty
(/usr/share/texlive/texmf-dist/tex/generic/pgf/utilities/pgfkeys.code.tex
(/usr/share/texlive/texmf-dist/tex/generic/pgf/utilities/pgfkeysfiltered.code.t
ex))))) (/usr/share/texlive/texmf-dist/tex/generic/babel/babel.sty
(/usr/share/texlive/texmf-dist/tex/generic/babel/txtbabel.def)
(/usr/share/texlive/texmf-dist/tex/generic/babel-french/french.ldf)
! LaTeX Error: Missing \begin{document}.
See the LaTeX manual or LaTeX Companion for explanation.
Type H <return> for immediate help.
...
l.4261 \ifin#\edef\bbl#tempc{\bbl#tempb}\fi}
?
However, if I compile this (No spaces in the title argument):
\documentclass[lang=french,title=truc]{myPlanning}
\begin{document}
some text here
\end{document}
It compiles fine with no errors.
What's more, the first document with spaces in the title argument compiles fine if I remove the \RequirePackage[\myOrg#lang]{babel} line from the package definition.
Is this a known problem and is there a solution ?
Thanks for your help,
Jouke
Update: The underlying issue was fixed in upstream babel on 2022-11-24 and should be resolved in the next release.
The issue is not the key=value parser but a code block of babel that tries to detect whether the wrong language is loaded if it got both options from the \documentclass and options when the package was called. That being said, pgfopts isn't up-to-date with current LaTeX (there were substantial changes to the option-system about a year ago that pgfopts has not yet followed suit), the only solutions to key=value options that are compatible to my knowledge are the builtin mechanism and expkv-opt.
But as I said, neither will solve your issue. Using main=\myOrg#lang in the options of babel however will, as if you used the main-option the problematic code of babel will not be used. So if you change your class to the following the only (admittedly strange) warning regarding your options you'll get will be
LaTeX Warning: Unused global option(s):
[french].
(but that stems from your strange usage of \LoadClass, in which article will add french to the unused options list though it isn't in the global options list, hence babel will not pick it up and remove it from said list).
\NeedsTeXFormat{LaTeX2e}
\ProvidesClass{myPlanning}[2022/07/16 my Planning class]
\LoadClassWithOptions{article}
\RequirePackage{pgfopts}
\pgfkeys{
/myOrg/.cd
,lang/.initial = english
,lang/.store in = \myOrg#lang
,title/.initial = title
,title/.store in = \myOrg#title,
}
\ProcessPgfOptions{/myOrg}
\RequirePackage[main=\myOrg#lang]{babel}

Selenium Select Input Box that Changes Name Every Session

I'm trying to access a search text box inside of our company's ERP system using Selenium. The screenshot shows the text box and the Xpath of the element.
This is a little tricky, because that Menu Search pop-up isn't really a pop-up. It somehow shows up when a user types Control + M.
By installing ChroPath and testing I've found the text-box always starts with the following string:
txtMenuSearch_Namespace_
I've tried to imitate what's described here, here and here with no luck.
The latest attempt in the snippet of my code looks like this:
menu_search_input_box_elements = driver.find_elements_by_xpath("//*[contains(#id, ‘txtMenuSearch_Namespace_’)]")
for item in menu_search_input_box_elements:
print(item)
I get the following error message:
SyntaxError: Failed to execute 'evaluate' on 'Document': The string '//*[contains(#id, ‘txtMenuSearch_Namespace_’)]' is not a valid XPath expression.
In all my attempts to get the syntax right I keep getting this message. Any help in figuring out how to .send_keys() to this field is greatly appreciated.
You get en error because of the ‘’ quotes, replace them with correct ones.
# id starts with txtMenuSearch_Namespace_
menu_search_input_box_elements = driver.find_elements_css_selector("[id^='txtMenuSearch_Namespace_']")
menu_search_input_box_elements = driver.find_elements_by_xpath("//*[contains(#id, 'txtMenuSearch_Namespace_')]")

How to repair this issue when i click on result link in modx ajaxSearch?

I used ajaxSearch on this site: http://www.rhemapress.pl/www_poradnia/ and when I type something, e.g: czwarta or wspomaganie then when i clicked on one of return links then it redirect me to this document but on end of this link is something like this:
&searched=wspomaganie&advsearch=oneword&highlight=ajaxSearch_highlight+ajaxSearch_highlight1 and i've got this error after I clicked.
MODx encountered the following error while attempting to parse the requested resource:
htmlentities() [function.htmlentities]: charset `ISO-8859-2' not supported, assuming iso-8859-1
/home/users/rhemapress/public_html/rhemapress/www_poradnia/manager/includes/document.parser.class.inc.php(790) : eval()'d code
Where is the problem? How can i do this correctly? Database is UTF8.
I think you need to replace the character set similar to how they do it here:
http://forums.modx.com/index.php?topic=17161.0
Find instances similar to this, specifically the "etomite_charset":
htmlentities($output,ENT_QUOTES,$modx->config['etomite_charset']);
Replace with something similar to this:
htmlentities($output, ENT_QUOTES);
However I don't know all the instance of where this would appear in the ajax search plugin.

How can I make cucumber run all the steps (not skip them) even if one of them fails?

I am using Cucumber with RubyMine, and I have a scenario with steps that verify some special controls from a form (I am using cucumber for automation testing). The controls don't have anything to do with each other, and there is no reason for the steps to be skipped if one in front of them fails.
Does anyone know what configurations or commands should I use to run all the steps in a scenario even if they all fail?
I think the only way to achieve desired behavior (which is quite uncommon) is to define custom steps and catch exceptions in it yourself. According to cucumber wiki step is failed if it raises an error. Almost all default steps raise error if they can't find or interact with an element on the page. If you'll catch this exceptions the step will be marked as passed, but in rescue you can provide custom output. Also I recommend you to carefully define exceptions you want to catch, I think if you're Ok if selenium can't find an element on the page rescue only from ElementNotFound exceptions, don't catch all exceptions.
I've seen a lot of threads on the Web about people wanting to continue steps execution if one failed.
I've discussed with Cucumber developers: they think this is a bad idea: https://groups.google.com/forum/#!topic/cukes/xTqSyR1qvSc
Many times, scenarios can be reworked to avoid this need: scenarios must be split into several smaller and independent scenarios, or several checks can be aggregated into one, providing a more human scenario and a less script-like scenario.
But if you REALLY need this feature, like our project do, we've done a fork of Cucumber-JVM.
This fork let you annotate steps so that when they fail with a determined exception, they will let let next steps execute anyway (and the step itself is marked as failed).
The fork is available here:
https://github.com/slaout/cucumber-jvm/tree/continue-next-steps-for-exceptions-1.2.4
It's published on the OSSRH Maven repository.
See the README.md for usage, explanation screenshot and Maven dependency.
It's only available for the Java language, tough: any help is welcome to adapt the code to Ruby, for instance. I don't think it will be a lot of work.
The question is old, but hopefully this will be helpful. What I'm doing feels kind of "wrong", but it works. In your web steps, if you want to keep going, you have to catch exceptions. I'm doing that primarily to add helpful failure messages. I'm checking a table full of values that are identified in Cucumber with a table having a bunch of rows like:
Then my result should be:
| Row Identifier | Column Identifier | Subcolum Identifier | $1,247.50 |
where the identifiers make sense in the application domain, and name a specific cell in the results table in a human-friendly way. I have helpers that convert the human identifiers to DOM IDs, which are used to first check whether the row I'm looking for exists at all, then look for the specific value in a cell in that row. The default failure message for a missing row is clear enough for me (expected to find css "tr#my_specific_dom_id" but there were no matches). But the failure message for checking specific text in a cell is completely unhelpful. So I made a step that catches the exception and uses the Cucumber step info and some element searching to get a good failure message:
Then /^my application domain results should be:$/ do |table|
table.rows.each do |row|
row_id = dom_id_for(row[0])
cell_id = dom_id_for(row[0], row[1], row[2])
page.should have_css "tr##{row_id}"
begin
page.should have_xpath("//td[#id='#{cell_id}'][text()=\"#{row[3].strip.lstrip}\"]")
rescue Capybara::ExpectationNotMet => exception
# find returns a Capybara::Element, native returns a Selenium::WebDriver::Element
contents = find(:xpath, "//td[#id='#{cell_id}']").native.text
puts "Expected #{ row[3] } for #{ row[0,2].join(' ') } but found #{ contents } instead."
#step_failures_were_rescued = true
end
end
end
Then I define a hook in features/support/hooks.rb like:
After do |scenario|
unless scenario.failed?
raise Capybara::ExpectationNotMet if #step_failures_were_rescued
end
end
This makes the overall scenario fail, but it masks the step failure from Cucumber, so all the step results are green, including the ones that aren't right. You have to see the scenario failure, then look back at the messages to see what failed. This seems kind of "bad" to me, but it works. It's WAY more convenient in my case to get the expected and found values listed in a domain-friendly context for the whole table I'm checking, rather than to get a message like "I looked for "$123.45" but I couldn't find it." There might be a better way to do this using the Capybara "within" method. This is the best I've come up with so far though.

How do I get the HTML in an element using Capybara?

I’m writing a cucumber test where I want to get the HTML in an element.
For example:
within 'table' do
# this works
find('//tr[2]//td[7]').text.should == "these are the comments"
# I want something like this (there is no "html" method)
find('//tr[2]//td[7]').html.should == "these are the <b>comments</b>"
end
Anyone know how to do this?
You can call HTML DOM innerHTML Property:
find('//tr[2]//td[7]')['innerHTML']
Should work for any browser or driver.
You can check all available properties on w3schools
This post is old, but I think I found a way if you still need this.
To access the Nokogiri node from the Capybara element (using Capybara 1.0.0beta1, Nokogiri 1.4.4) try this:
elem = find('//tr[2]//td[10]')
node = elem.native
#This will give you a Nokogiri XML element
node.children[1].attributes["href"].value.should == "these are the <b>comments</b>"
The last part may vary for you, but you should be able to find the HTML somewhere in that node variable
In my environment, find returns a Capybara::Element - that responds to the :native method as Eric Hu mentioned above, which returns a Selenium::WebDriver::Element (for me). Then :text gets the contents, so it could be as simple as:
results = find(:xpath, "//td[#id='#{cell_id}']")
contents = results.native.text
if you're looking for the contents of a table cell. There's no content, inner_html, inner_text, or node methods on a Capybara::Element. Assuming people aren't just making things up, perhaps you get something different back from find depending on what else you have loaded with Capybara.
Looks like you can do (node).native.inner_html to get the HTML content, for example with HTML like this:
<div><strong>Some</strong> HTML</div>
You could do the following:
find('div').native.inner_html
=> '<strong>Some</strong> HTML'
I ran into the same issue as Cyril Duchon-Doris, and per https://github.com/teampoltergeist/poltergeist/issues/629 the way to access the HTML of an Capybara::Poltergeist::Node is via the outerHTML property, e.g.:
find('//tr[2]//td[7]')['outerHTML']
Most of the other answers work only in Racktest (as they use Racktest-specific features).
If your driver supports javascript evaluation (like Selenium) you can use innerHTML :
html = page.evaluate_script("document.getElementById('my_id').innerHTML")
If you're using the Poltergeist driver, these methods will allow you to inspect what matches:
http://www.rubydoc.info/gems/poltergeist/1.5.1/Capybara/Poltergeist/Node
For example:
page.find('[name="form-field"]').native.value == 'something'
try calling find('//tr[2]//td[10]').node on it to get at the actual nokogiri object
Well, Capybara uses Nokogiri to parse, so this page might be appropriate:
http://nokogiri.org/Nokogiri/XML/Node.html
I believe content is the method you are looking for.
You could also switch to capybara-ui and do the following:
# define your widget, in this case in your role
class User < Capybara::UI::Role
widget :seventh_cell, [:xpath, '//tr[2]//td[7]']
end
# then in your tests
role = User.new
expect(role.widget(:seventh_cell).html).to eq(<h1>My html</h1>)

Resources