How can I use pageobject navigation routes when I have multiple methods with parameters? - ruby

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

Related

How to convert a string to an object reference in ruby

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

Hanami parameters whitelisting

Following the hanami docs, in order to block a admin parameter inside an action, I can use the following configuration:
params do
required(:email).filled
required(:address).schema do
required(:country).filled
end
end
def call(params)
puts params[:email] # => "alice#example.org"
puts params[:address][:country] # => "Italy"
puts params[:admin] # => nil
end
But this does not work for nested parameters, i.e.:
params do
required(:email).filled
required(:address).schema do
required(:country).filled
end
end
def call(params)
puts params[:email] # => "alice#example.org"
puts params[:address] # => { country: "Italy", admin: true }
puts params[:address][:admin] # => true
end
I was able to solve this by using select to filter out the undesirable parameters with a private method, but this does not seems like the Hanami way. What would be the proper way to do this whitelisting of nested parameters?
I have never had this issue when using Hanami Validations. Within the app directory there should be a validations folder which should have the same directory structure as your controllers, views, templates etc. Your validation file should look something like this:
# apps/web/validations/users/create.rb
module Web
module Validations
module Users
class Create < Web::Action::Params
predicates Web::Validations::CommonPredicates
validations do
required(:email).filled
required(:address).schema do
required(:country).filled
end
end
end
end
end
end
And then your controller should set the params to be filtered through the validation:
module Web
module Controllers
module Users
class Create
include Web::Action
params Web::Validations::Users::Create
def call(params); end
end
end
end
end

Active Admin Custom Method Parameter

In ActiveAdmin I'm trying to get a value from a form when I press an action_item on the dashboard, but I'm not sure exactly how to do that this is what I have so far, and it runs, but I would like to be able to pass a parameter for different method calls.
ActiveAdmin.register_page "Dashboard" do
menu :priority => 1, :label => proc{ I18n.t("active_admin.dashboard") }
page_action :scrape, :method => :post do
#The scraper works, but I don't know how to pass the info
#from the form from below into this method
# scrape = Scraper.new
# scrape.scrape
redirect_to admin_dashboard_path, :notice => "Ran the scraper!"
end
action_item do
link_to "Run Scraper", admin_dashboard_scrape_path, :method => :post
end
content :title => proc{ I18n.t("active_admin.dashboard") } do
panel "Run Course Scraper" do
para "Run the course webscraper to pull current class list and insert into the Course table in the database"
form do |f|
f.input "Session"
end
end
end
end
I want to get the input form the form where it says session to pass to the page_action :scrape somehow, any ideas?
You could to try to add controller actions to the dashboard page and add f.buttons to the form etc.
Using javascript should also work I guess.

Mock current_account on Padrino for rspec test

I'm trying to test a padrino controller that depends on current_account provided by Padrino::Admin::AccessControl
To do so, I need to mock current_account.
the code is something like:
App.controller :post do
post :create, map => '/create' do
Post.create :user => current_account
end
end
and the rspec:
describe "Post creation" do
it 'should create' do
account = Account.create :name => 'someone'
loggin_as account #to mock current_account
post '/create'
Post.first.user.should == account
end
end
How can I implement "loggin_as" or how can I write this test?
I found a simple way to test:
App.any_instance.stub(:current_account).and_return(account)
So, the test code should be:
describe "Post creation" do
it 'should create' do
account = Account.create :name => 'someone'
App.any_instance.stub(:current_account).and_return(account)
post '/create'
Post.first.user.should == account
end
end
but I still like to build "loggin_as" helper. So, how can I dynamically get App class? (should I create another thread for this question?)

Rails 3.1 Rspec Creating test case validate field for Model

I'm trying to create a test case for User model. Basically, it will validate first_name and last_name to be present.
What I am trying to do is to check whether the error on a specific field is empty or not and it should be empty. However it always fails.
What is the correct way to do this?
Here is my code
On my user_spec.rb
require 'spec_helper'
describe User do
before do
#user = User.new
end
it "must have a first name" do
#user.errors[:first_name].should_not be_empty
end
it "must have a last name" do
#user.errors[:last_name].should_not be_empty
end
end
On my user.rb file
class User < ActiveRecord::Base
validates :first_name, :presence => true
validates :last_name, :presence => true
end
You can test by simply doing this as well:
describe 'validations' do
it { should validate_presence_of :firstname }
it { should validate_presence_of :lastname }
end
Take a look at the shoulda matchers for all such standard Rails Validation.
This way is not just more concise but also takes care of the positive case. Meaning you then dont need to test the scenario mentioned below:
it "passed validations when first_name is set"
user = User.create(:firstname => 'f', :lastname => 'l')
user.errors[:first_name].should be_empty
user.errors[:last_name].should be_empty
end
RSpec supports the notion of an "implicit" subject. If your first argument to the "describe" block is a class, RSpec automatically makes an instance of that class available to your specs. See http://relishapp.com/rspec/rspec-core/v/2-6/dir/subject/implicit-subject.
require 'spec_helper'
describe User do
it "must have a first name" do
subject.should have(1).error_on(:first_name)
end
it "must have a last name" do
subject.should have(1).error_on(:last_name)
end
end
which results in RSpec output (if using --format documentation) of:
User
must have a first name
must have a last name
You can abbreviate it even further if you are content with the RSpec output defaults:
require 'spec_helper'
describe User do
it { should have(1).error_on(:first_name) }
it { should have(1).error_on(:last_name) }
end
which results in:
User
should have 1 error on :first_name
should have 1 error on :last_name

Resources