How to test if page_url is correct using the 'page-object' gem in Ruby - ruby

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

Related

Need to login before going to a new page

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

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

What is does this error method mean: undefined method `method name' for nil:NilClass (NoMethodError)

I am fairly new to automation testing and I am writing BDD automation test scenarios in Ruby using selenium-webdriver, when running my tests, they fail at the first step. (tumblr just as an example)
What does this error message mean and how do I fix it? Any help would be much appreciated!
In my feature file:
Feature: tumblr
#s1
Scenario: Logging in to Tumblr
Given I am on the Tumblr login page
When I enter my login details
Then I should be sent to the dashboard
In my login_page.rb:
def visit
#browser.goto "#{EnvConfig.base_url}/login"
await_on_page
end
In my login_step_defs.rb:
Given /^I am on the Odicci login page$/ do
#app.tumblr_login.visit
end
When /^I enter my login details$/ do
#app.tumblr_login.login
end
Then /^I should be sent to the dashboard$/ do
#app.tumblr_dashboard.go_to_dashboard
end
Initially when I was running 'cucumber features.feature' but the step definitions could not be located so the scenarios were finishing off as 'undefined' so running 'cucumber features.feature -r step_definitions works to run the tests but they fail because of this error message:
Scenario: Logging in to Tumblr # features.feature:4
Given I am on the Tumblr login page # step_definitions/login_step_defs.rb:2
undefined method `tumblr_login' for nil:NilClass (NoMethodError)
./step_definitions/login_step_defs.rb:3:in `/^I am on the Tumblr login page$/'
features.feature:5:in `Given I am on the Tumblr login page'
#maxpleaner
if ENV['HEADLESS']
require 'headless'
require 'selenium-webdriver'
headless = Headless.new display: '100'
headless.start
end
# Set up browser
# browser = Watir::Browser.new (ENV['BROWSER'] || 'chrome').to_sym
driver = Selenium::WebDriver.for :chrome
browser_type = ENV['BROWSER'] || 'chrome'
$setup_done = false
Before do |scenario|
#browser = browser
#app = App.new #browser
unless $setup_done
$setup_done = true
# This stuff will only run before the first scenario executed. Use it to set up data etc.
end
end
After do |scenario|
end
at_exit do
browser.quit
end

Set home routes to direct in Sinatra simple authentication

I'm trying to use Sinatra simple auth to force users to logon before being able to access the site. So the home page would be the logon then should be able to use the site without being prompted for it. At the moment I could not figure out a way to redirect to the home root page after logon. set :home is working as it should.
# -*- coding: utf-8 -*-
# Required gems
require 'sinatra'
require 'rubygems'
require 'dm-core'
require 'dm-migrations'
require 'sinatra/simple-authentication'
require 'rack-flash'
# Required models and database
require './models/note'
class Index < Sinatra::Base
DataMapper::Logger.new($stdout, :debug)
DataMapper::setup(:default, "sqlite3://#{Dir.pwd}/recall.db")
use Rack::Flash, :sweep => true
register Sinatra::SimpleAuthentication
enable :sessions
set :home, '/'
# ** SHOW **
# Root to the index page
# Pull all notes from the DB into an instance varible to access from the index page in descends order.
get '/' do
login_required
#notes = Note.all :order => :id.desc
haml :index
end
# ** SAVE **
# Retrieves note contents from :contents on the index view and save them into the DB.
# Redirects back to the index page.
post '/' do
n = Note.new
n.content = params[:content]
n.created_at = Time.now
n.updated_at = Time.now
n.save
redirect '/'
end
# ** EDIT **
# Retrieves notes ID to edit the note
# Title varible is to display the note ID to the user to be able to edit/delete a specific note.
get '/:id' do
#note = Note.get params[:id]
#title = "Edit note ##{params[:id]}"
haml :edit
end
# Edit
# Retrieves the saved note for the user to edit then save it with the same ID and new timestamp
put '/:id' do
n = Note.get params[:id]
n.content = params[:content]
n.complete = params[:complete] ? 1 : 0
n.updated_at = Time.now
n.save
redirect '/'
end
# ** DESTROY **
# Delete note by the ID
# Retrun the note ID to the view page to confirm the deletion of the right note.
get '/:id/delete' do
#note = Note.get params[:id]
#title = "Confirm deletion of note ##{params[:id]}"
haml :delete
end
# Delte note by ID
delete '/:id' do
n = Note.get params[:id]
n.destroy
redirect '/'
end
# Check the completion of note (still not working)
get '/:id/complete' do
n = Note.get params[:id]
n.complete = n.complete ? 0 : 1 # flip it
n.updated_at = Time.now
n.save
redirect '/'
end
# To resturn the "Page not found" insted of the default Sinatra error page.
not_found do
halt 404, "Page not found 404"
end
end
**strong text**
If what you want to do is check if a user is logged in before any routes except "/" you can use this:
before do
if request.path != "/"
if # statement which returns false if a user is logged in
redirect "/"
end
end
end

Facebook Graph API for websites using Ruby Koala gem in Sinatra

I want to implement Facebook login for web apps. All I need is the basic public information of a user for the account creation steps.
This is what I have done:
Created a basic Facebook app with nearly no custom permissions.
Used the APP_ID and APP_SECRET in Koala to get access_token.
Everything worked perfectly, I am able to login/logout.
Just that the only information I am able to get back when I do: graph.get_object('me') is the logged in user's name and an id (It doesn't look like the default Facebook id).
Surprised whether something changed in the new API, I tested the gem in the console using the access_token from graph explorer (where all permissions are enabled by default). And I get all data using the same method call.
When I review what all the app gets while signing up; I see that the user's basic information, profile pic and other public data will be accessible to the app.
Any idea why this is so? It seems I am missing something obvious. The code is available in Github. But this is pretty much everything to it:
require 'bundler'
Bundler.require :default
Dotenv.load '.env'
require_relative './app/constants.rb'
module Banana
class App < Sinatra::Base
use Rack::Session::Cookie, secret: COOKIE_SECRET
set :public_folder, File.dirname(__FILE__) + '/bower_components'
get '/' do
if logged_in?
haml :welcome_in, layout: :layout
else
haml :log_in, layout: :layout
end
end
get '/log_out' do
session['oauth'] = nil
session['access_token'] = nil
redirect '/'
end
get '/log_in' do
session['oauth'] = Koala::Facebook::OAuth.new(APP_ID, APP_SECRET, "#{request.base_url}/call_back")
redirect session['oauth'].url_for_oauth_code()
end
get '/call_back' do
begin
session['access_token'] = session['oauth'].get_access_token(params[:code])
rescue
redirect '/?error=user_denied'
end
redirect '/'
end
get '/test' do
if logged_in?
p graph.get_object("rakeshbs")
"e"
else
redirect '/'
end
end
def logged_in?
!session['access_token'].nil?
end
def toggle_access
logged_in? ? '/log_out' : '/log_in'
end
def graph
#graph ||= Koala::Facebook::API.new(session['access_token'])
end
def errored?
!params["error"].nil?
end
def user
p graph.get_connections(:me, :photos) # This is just nil
#user ||= OpenStruct.new(
name: graph.get_object("me")["name"], # All I get here is just a hash with the name and an id!
photo: 'http://semantic-ui.com/images/avatar/small/elliot.jpg'
)
end
end
end
You should add fields parameter.
Something like this:
graph.get_object('me', { fields: 'id,first_name,last_name,gender,birthday,photos,email' })

Resources