I want to take in a page name in a gherkin step then set it as an object reference (I think that's what it's called.) Then I can use that to interact with page elements. Is there an easier way to do this in ruby?
When(/^I am on the (.*) page$/) do |page|
case page
when "home page"
#current_page = #home_page
when "my account page"
#current_page = #my_account_page
end
end
Then
When(/^I click the (.*)$/) do |element|
#current_page.send(element).click
end
You can use instance_variable_get:
When(/^I am on the (.*) page$/) do |page|
#current_page = instance_variable_get("##{page}")
end
This will work if the page values perfect match your instance variables, e.g.
page = "my_account_page"
# The following two lines are equivalent
instance_variable_get("##{page}")
#my_account_page
Related
I'm currently using Ruby and Capybara and writing tests. I have a login page already done and it works fine. I'm trying to create a separate test where I want it to already login before going to that page.
My login Code:
class LoginPage < SitePrism::Page
set_url '/'
element :username_field, '#username'
element :password_field, '#password'
element :login_button, '#login_button'
def login()
username_field.send_keys 'Cow'
password_field.send_keys 'dogs'
login_button.click
end
def load_and_login(*args)
self.load
login(*args)
self
end
end
This is my new page. Where I want it to login prior to going to this page.
describe login do
before(:each) do
home = LoginPage.new
home.load
home.login
end
end
class newPage < SitePrism::Page
include RSpec::Matchers
include Capybara::RSpecMatchers
set_url '/new'
end
This is the error that I"m getting:
Failure/Error: Dir['./pages/**/*.rb'].sort.each { |f| require f }
NameError:
undefined local variable or method `login' for main:Object
describe login do -- looks like problem here
Change it to describe '#login' do
Here is an example of my Gherkin:
require 'watir-webdriver'
require 'page-object'
include PageObject::PageFactory
Given(/^user is on google home page$/) do
visit_page GoogleHome
end
When(/^user enters search criteria in google search bar$/) do
#browser.text_field(:name, "q").set "latest news"
end
Then(/^user is redirected to results page$/) do
on_page ResultPage do |page|
page.text.include? page.WEB_STRING
end
end
Given(/^user is on result page$/) do
visit_page ResultPage
end
When(/^user clicks on website link$/) do
on_page ResultPage do |page|
page.news_link
end
end
Then(/^user is redirected to website$/) do
on_page FoxNews do |page|
page_url.value?("http://www.foxnews.com/")
end
end
Here is an example of my page definition:
require 'page-object'
class FoxNews
include PageObject
page_url "http://www.foxnews.com/"
end
Basically, I want to test that the user has actually been redirected to the example news site. The code runs smoothly but there is a problem with my test case. I have tried page_url.inlcude? and page_url.value?.
A page object has two methods related to getting the URL:
page_url_value - This is the URL specified in the page_url accessor (ie the expected URL).
current_url - This is the browser's current URL.
To check that the correct page is displayed, then you want to check the current_url. The step would be:
Then(/^user is redirected to website$/) do
on_page FoxNews do |page|
page.current_url == 'http://www.foxnews.com/'
end
end
However, this step will always pass. I assume that you actually want to make an assertion:
Then(/^user is redirected to website$/) do
on_page FoxNews do |page|
expect(page.current_url).to eq('http://www.foxnews.com/')
end
end
Instead of duplicating the expected URL in the page object and the test, you could also use the page_url_value:
Then(/^user is redirected to website$/) do
on_page FoxNews do |page|
expect(page.current_url).to eq(page.page_url_value)
end
end
Here, I have two methods in a class with one parameter each and I want to use routes advantage. How can I pass parameters if I am using cucumber I mean how can I pass parameters from step definitions to method if I use like this:
feature:
Feature: Github Test Case
Background:
Given I am on githubpage
Scenario Outline: I should see one of the repositories
When I click on "<user>" and select "<repo>" link
Then I should see "Information Technology Association website repo"
Examples:
| user | repo |
| sample | sample_repo |
step def:
Given(/^I am on githubpage$/) do
visit(LoginPage).do_login
end
Then(/^I should see "([^"]*)"$/) do |message|
#current_page.text.should include message
end
When(/^I click on "([^"]*)" and select "([^"]*)" link$/) do |user, repo|
# currently using like this
navigate_to(GithubPage).click_on(user)
navigate_to(GithubPage).select_repo(repo)
# but i need like this
navigate_to(GithubPage).select_repo
# or
navigate_all
end
class:
class GithubPage
include PageObject
link(:repo, text: /Repositories/)
def click_on(user)
span_element(text: "#{user}", index: 1).click
repo_element.click
end
def select_repo(repo)
link_element(xpath: "//a[contains(text(),'#{repo}')]").when_present.click
end
end
routes:
PageObject::PageFactory.routes = {
:default => [[GithubPage, :click_on], [GithubPage, :select_repo]]
}
Here's an example from PageObject::PageFactory where Cheezy passes an argument to a method as part of his routes definition:
PageObject::PageFactory.routes = {
:default => [[PageOne,:method1], [PageTwoA,:method2], [PageThree,:method3]],
:another_route => [[PageOne,:method1, "arg1"], [PageTwoB,:method2b], [PageThree,:method3]]
}
The problem is, of course, that you don't have that argument at the time these routes are defined. You need to load them dynamically. Something like this might work, but I haven't tested it:
When /^I click on "([^"]*)" and select "([^"]*)" link$/ do |user, repo|
PageObject::PageFactory.routes[:default].map do |route|
route << user if route[1] == :click_on
route << repo if route[1] == :select_repo
end
navigate_all
end
But if you're going to go to all that trouble, you're better off passing a block to PageObject::PageFactory#on:
When /^I click on "([^"]*)" and select "([^"]*)" link$/ do |user, repo|
on GithubPage do |page|
page.click_on user
page.select_repo repo
end
end
Right now under my posts controller i have methods
def main
#post = Post.all
end
def show
#post = Post.find(params[:id])
end
I am wondering what is the most basic and simple way to show one post per page and have next and previous links to it. Here i am referencing to main.html.erb . So for instance just have localhost:3000/posts and under that page i can have next and previous links to browse through the post.
Would I be needing some kind of ajax to this? If not then how i can do this using simple activerecord and other elements of rails?
Note: After I click on next, i do need to have the permalink of the post in the url tab.
You could do something like this. Add previous and next method to your model
def previous
posts = where('id > ?', id).limit(1)
if posts.nil?
nil
else
posts.first
end
end
def next
posts = where('id < ?',id).limit(1)
if posts.nil?
nil
else
posts.first
end
end
and then in your view you could do something like this.
unless #post.next.nil? #to show the link to the next post
link_to #post.next
end
unless #post.previous.nil? #to show the link to the next post
link_to #post.previous
end
Anyhow this method isn't that optimized since you will add more two more database queries to get previous and next posts.
You could use the gem will_paginate and set the default per page to 1, as in:
class Post
self.per_page = 1
end
For more information about will_paginate:
https://github.com/mislav/will_paginate
$browser.links.each do |link|
puts link.attribute_value("class")
end
How do I get all the visible/existing links in the put statement?
You can also write it by using shorter syntax like this:
puts $browser.links.find_all(&:present?).map(&:class_name)
This will output value of class attribute for all existing links on the page:
$browser.links.each {|link| puts link.attribute_value("class")}
This will output value of class attribute for all visible links on the page:
$browser.links.each {|link| puts link.attribute_value("class") if link.visible?}
If you require the class name of the links, you can use
$browser.links.each {|link| puts link.class_name if link.visible?}
or if you require any specific attribute of the link, you can use
$browser.links.each {|link| puts link.attribute_value("attribute_name") if link.visible?}