page-object 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +6 -0
- data/Gemfile +3 -0
- data/LICENSE +20 -0
- data/README.md +87 -0
- data/Rakefile +51 -0
- data/cucumber.yml +5 -0
- data/features/check_box.feature +39 -0
- data/features/html/static_elements.html +34 -0
- data/features/link.feature +42 -0
- data/features/page_level_actions.feature +19 -0
- data/features/radio_button.feature +40 -0
- data/features/select_list.feature +40 -0
- data/features/step_definitions/accessor_steps.rb +88 -0
- data/features/step_definitions/element_steps.rb +28 -0
- data/features/step_definitions/page_level_actions_steps.rb +12 -0
- data/features/step_definitions/page_traversal_steps.rb +5 -0
- data/features/support/env.rb +18 -0
- data/features/support/page.rb +45 -0
- data/features/support/url_helper.rb +16 -0
- data/features/text_field.feature +39 -0
- data/lib/page-object.rb +52 -0
- data/lib/page-object/accessors.rb +171 -0
- data/lib/page-object/elements.rb +8 -0
- data/lib/page-object/elements/button.rb +15 -0
- data/lib/page-object/elements/check_box.rb +15 -0
- data/lib/page-object/elements/element.rb +52 -0
- data/lib/page-object/elements/link.rb +34 -0
- data/lib/page-object/elements/radio_button.rb +15 -0
- data/lib/page-object/elements/select_list.rb +21 -0
- data/lib/page-object/elements/text_field.rb +33 -0
- data/lib/page-object/selenium_element.rb +12 -0
- data/lib/page-object/selenium_page_object.rb +190 -0
- data/lib/page-object/version.rb +3 -0
- data/lib/page-object/watir_element.rb +12 -0
- data/lib/page-object/watir_page_object.rb +190 -0
- data/page-object.gemspec +29 -0
- data/spec/page-object/accessors_spec.rb +297 -0
- data/spec/page-object/elements/button_spec.rb +23 -0
- data/spec/page-object/elements/check_box_spec.rb +21 -0
- data/spec/page-object/elements/element_spec.rb +54 -0
- data/spec/page-object/elements/link_spec.rb +34 -0
- data/spec/page-object/elements/radio_button_spec.rb +21 -0
- data/spec/page-object/elements/select_list_spec.rb +22 -0
- data/spec/page-object/elements/text_field_spec.rb +32 -0
- data/spec/page-object/page-object_spec.rb +78 -0
- data/spec/spec_helper.rb +31 -0
- metadata +179 -0
@@ -0,0 +1,28 @@
|
|
1
|
+
When /^I retrieve a check box element$/ do
|
2
|
+
@element = @page.cb_id_checkbox
|
3
|
+
end
|
4
|
+
|
5
|
+
When /^I retrieve a link element$/ do
|
6
|
+
@element = @page.google_search_id_link
|
7
|
+
end
|
8
|
+
|
9
|
+
When /^I retrieve a radio button$/ do
|
10
|
+
@element = @page.milk_id_radio_button
|
11
|
+
end
|
12
|
+
|
13
|
+
When /^I retrieve a select list$/ do
|
14
|
+
@element = @page.sel_list_id_select_list
|
15
|
+
end
|
16
|
+
|
17
|
+
When /^I retrieve a text field$/ do
|
18
|
+
@element = @page.text_field_id_text_field
|
19
|
+
end
|
20
|
+
|
21
|
+
Then /^I should know it exists$/ do
|
22
|
+
@element.should exist
|
23
|
+
end
|
24
|
+
|
25
|
+
Then /^I should know it is visible$/ do
|
26
|
+
@element.should be_visible
|
27
|
+
end
|
28
|
+
|
@@ -0,0 +1,12 @@
|
|
1
|
+
|
2
|
+
Then /^the page should contain the text "([^\"]*)"$/ do |text|
|
3
|
+
@page.text.should include text
|
4
|
+
end
|
5
|
+
|
6
|
+
Then /^the page should contain the html "([^\"]*)"$/ do |html|
|
7
|
+
@page.html.should include html
|
8
|
+
end
|
9
|
+
|
10
|
+
Then /^the page should have the title "([^\"]*)"$/ do |title|
|
11
|
+
@page.title.should include title
|
12
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '../../', 'lib'))
|
2
|
+
|
3
|
+
require 'rspec/expectations'
|
4
|
+
require 'watir-webdriver'
|
5
|
+
require 'selenium-webdriver'
|
6
|
+
|
7
|
+
require 'page-object'
|
8
|
+
|
9
|
+
Before do
|
10
|
+
@browser = Watir::Browser.new :firefox if ENV['DRIVER'] == 'WATIR'
|
11
|
+
@browser = Selenium::WebDriver.for :firefox if ENV['DRIVER'] == 'SELENIUM'
|
12
|
+
end
|
13
|
+
|
14
|
+
After do |s|
|
15
|
+
@browser.close
|
16
|
+
end
|
17
|
+
|
18
|
+
|
@@ -0,0 +1,45 @@
|
|
1
|
+
class Page
|
2
|
+
include PageObject
|
3
|
+
|
4
|
+
text_field(:text_field_id, :id => "text_field_id")
|
5
|
+
text_field(:text_field_class, :class => "text_field_class")
|
6
|
+
text_field(:text_field_name, :name => "text_field_name")
|
7
|
+
text_field(:text_field_xpath, :xpath => "//input[@type='text']")
|
8
|
+
text_field(:text_field_css, :css => "input[type='text']")
|
9
|
+
text_field(:text_field_tag_name, :tag_name => "input[type='text']")
|
10
|
+
text_field(:text_field_index, :index => 0)
|
11
|
+
text_field(:text_field_text, :text => "")
|
12
|
+
text_field(:text_field_value, :value => "")
|
13
|
+
|
14
|
+
link(:google_search_id, :id => "link_id")
|
15
|
+
link(:google_search_name, :name => "link_name")
|
16
|
+
link(:google_search_class, :class => "link_class")
|
17
|
+
link(:google_search_xpath, :xpath => "//a[text()='Google Search']")
|
18
|
+
link(:google_search_link, :link => "Google Search")
|
19
|
+
link(:google_search_link_text, :link_text => "Google Search")
|
20
|
+
link(:google_search_href, :href => "http://www.google.com")
|
21
|
+
link(:google_search_text, :text => "Google Search")
|
22
|
+
link(:google_search_index, :index => 0)
|
23
|
+
|
24
|
+
select_list(:sel_list_id, :id => "sel_list_id")
|
25
|
+
select_list(:sel_list_class, :class => "sel_list_class")
|
26
|
+
select_list(:sel_list_index, :index => 0)
|
27
|
+
select_list(:sel_list_name, :name => "sel_list_name")
|
28
|
+
select_list(:sel_list_value, :value => "option1")
|
29
|
+
select_list(:sel_list_xpath, :xpath => "//select")
|
30
|
+
select_list(:sel_list_text, :text => "Test 1")
|
31
|
+
|
32
|
+
checkbox(:cb_id, :id => 'cb_id')
|
33
|
+
checkbox(:cb_name, :name => 'cb_name')
|
34
|
+
checkbox(:cb_class, :class => 'cb_class')
|
35
|
+
checkbox(:cb_index, :index => 0)
|
36
|
+
checkbox(:cb_xpath, :xpath => "//input[@type='checkbox']")
|
37
|
+
|
38
|
+
radio_button(:milk_id, :id => 'milk_id')
|
39
|
+
radio_button(:milk_name, :name => 'milk_name')
|
40
|
+
radio_button(:milk_class, :class => 'milk_class')
|
41
|
+
radio_button(:milk_index, :index => 0)
|
42
|
+
radio_button(:milk_xpath, :xpath => "//input[@type='radio']")
|
43
|
+
|
44
|
+
radio_button(:butter_id, :id => 'butter_id')
|
45
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
Feature: Text Fields
|
2
|
+
In order to interact with text fields
|
3
|
+
Testers will need access and interrogation ability
|
4
|
+
|
5
|
+
|
6
|
+
Background:
|
7
|
+
Given I am on the static elements page
|
8
|
+
|
9
|
+
Scenario: Setting and getting a value from a text field
|
10
|
+
When I type "abcDEF" into the text field
|
11
|
+
Then the text field should contain "abcDEF"
|
12
|
+
|
13
|
+
Scenario Outline: Locating text fields on the Page
|
14
|
+
When I search for the text field by "<search_by>"
|
15
|
+
Then I should be able to type "I found it" into the field
|
16
|
+
|
17
|
+
Scenarios:
|
18
|
+
| search_by |
|
19
|
+
| id |
|
20
|
+
| class |
|
21
|
+
| name |
|
22
|
+
| xpath |
|
23
|
+
| css |
|
24
|
+
| tag_name |
|
25
|
+
|
26
|
+
@watir_only
|
27
|
+
Scenario Outline: Locating text fields on Watir only
|
28
|
+
When I search for the text field by "<search_by>"
|
29
|
+
|
30
|
+
Scenarios:
|
31
|
+
| search_by |
|
32
|
+
| index |
|
33
|
+
| text |
|
34
|
+
| value |
|
35
|
+
|
36
|
+
Scenario: Retrieve a text field
|
37
|
+
When I retrieve a text field
|
38
|
+
Then I should know it exists
|
39
|
+
And I should know it is visible
|
data/lib/page-object.rb
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
|
2
|
+
require 'page-object/version'
|
3
|
+
require 'page-object/accessors'
|
4
|
+
|
5
|
+
# Module that when included adds core functionality to a page object.
|
6
|
+
module PageObject
|
7
|
+
attr_reader :platform
|
8
|
+
|
9
|
+
# Construct a new page object. The browser parameter must be either a
|
10
|
+
# Watir::Browser or Selenium::WebDriver::Driver.
|
11
|
+
def initialize(browser)
|
12
|
+
include_platform_driver(browser)
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.included(cls)
|
16
|
+
cls.extend PageObject::Accessors
|
17
|
+
end
|
18
|
+
|
19
|
+
# navigate to the provided url
|
20
|
+
def navigate_to(url)
|
21
|
+
platform.navigate_to(url)
|
22
|
+
end
|
23
|
+
|
24
|
+
# Returns the text of the current page
|
25
|
+
def text
|
26
|
+
platform.text
|
27
|
+
end
|
28
|
+
|
29
|
+
# Returns the html of the current page
|
30
|
+
def html
|
31
|
+
platform.html
|
32
|
+
end
|
33
|
+
|
34
|
+
# Returns the title of the current page
|
35
|
+
def title
|
36
|
+
platform.title
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def include_platform_driver(browser)
|
42
|
+
if browser.is_a? Watir::Browser
|
43
|
+
require 'page-object/watir_page_object'
|
44
|
+
@platform = PageObject::WatirPageObject.new(browser)
|
45
|
+
elsif browser.is_a? Selenium::WebDriver::Driver
|
46
|
+
require 'page-object/selenium_page_object'
|
47
|
+
@platform = PageObject::SeleniumPageObject.new(browser)
|
48
|
+
else
|
49
|
+
raise ArgumentError, "expect Watir::Browser or Selenium::WebDriver::Driver"
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,171 @@
|
|
1
|
+
|
2
|
+
#
|
3
|
+
# Contains the class level methods that are inserted into your page objects
|
4
|
+
# when you include the PageObject module. These methods will generate another
|
5
|
+
# set of methods that provide access to the elements on the web pages.
|
6
|
+
#
|
7
|
+
module PageObject
|
8
|
+
module Accessors
|
9
|
+
#
|
10
|
+
# adds three methods to the page object - one to set text in a text field,
|
11
|
+
# another to retrieve text from a text field and another to return the text
|
12
|
+
# field element.
|
13
|
+
#
|
14
|
+
# Example: text_field(:first_name, {:id => "first_name"})
|
15
|
+
# will generate the 'first_name', 'first_name=' and 'first_name_text_field methods.
|
16
|
+
#
|
17
|
+
# @param the name used for the generated methods
|
18
|
+
# @param identifier how we find a text_field. The valid values are:
|
19
|
+
# :class => Watir and Selenium
|
20
|
+
# :css => Watir and Selenium
|
21
|
+
# :id => Watir and Selenium
|
22
|
+
# :index => Watir only
|
23
|
+
# :name => Watir and Selenium
|
24
|
+
# :tag_name => Watir and Selenium
|
25
|
+
# :text => Watir only
|
26
|
+
# :value => Watir only
|
27
|
+
# :xpath => Watir and Selenium
|
28
|
+
#
|
29
|
+
def text_field(name, identifier)
|
30
|
+
define_method(name) do
|
31
|
+
platform.text_field_value_for identifier
|
32
|
+
end
|
33
|
+
define_method("#{name}=") do |value|
|
34
|
+
platform.text_field_value_set(identifier, value)
|
35
|
+
end
|
36
|
+
define_method("#{name}_text_field") do
|
37
|
+
platform.text_field_for identifier
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
#
|
42
|
+
# adds three methods - one to select an item in a drop-down,
|
43
|
+
# another to fetch the currently selected item and another
|
44
|
+
# to retrieve the select list element.
|
45
|
+
#
|
46
|
+
# Example: select_list(:state, {:id => "state"})
|
47
|
+
# will generate the 'state', 'state=' and 'state_select_list' methods
|
48
|
+
#
|
49
|
+
# @param the name used for the generated methods
|
50
|
+
# @param identifier how we find a select_list. The valid values are:
|
51
|
+
# :class => Watir and Selenium
|
52
|
+
# :id => Watir and Selenium
|
53
|
+
# :index => Watir only
|
54
|
+
# :name => Watir and Selenium
|
55
|
+
# :text => Watir only
|
56
|
+
# :value => Watir only
|
57
|
+
# :xpath => Watir and Selenium
|
58
|
+
#
|
59
|
+
def select_list(name, identifier)
|
60
|
+
define_method(name) do
|
61
|
+
platform.select_list_value_for identifier
|
62
|
+
end
|
63
|
+
define_method("#{name}=") do |value|
|
64
|
+
platform.select_list_value_set(identifier, value)
|
65
|
+
end
|
66
|
+
define_method("#{name}_select_list") do
|
67
|
+
platform.select_list_for identifier
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
#
|
72
|
+
# adds two methods - one to select a link and another
|
73
|
+
# to return a PageObject::Elements::Link object representing
|
74
|
+
# the link.
|
75
|
+
#
|
76
|
+
# Example: link(:add_to_cart, {:text => "Add to Cart"})
|
77
|
+
# will generate the 'add_to_cart' and 'add_to_cart_link'
|
78
|
+
# method.
|
79
|
+
#
|
80
|
+
# @param the name used for the generated methods
|
81
|
+
# @param identifier how we find a link. The valid values are:
|
82
|
+
# :class => Watir and Selenium
|
83
|
+
# :href => Watir only
|
84
|
+
# :id => Watir and Selenium
|
85
|
+
# :index => Watir only
|
86
|
+
# :link => Watir and Selenium
|
87
|
+
# :link_text => Watir and Selenium
|
88
|
+
# :name => Watir and Selenium
|
89
|
+
# :text => Watir and Selenium
|
90
|
+
# :xpath => Watir and Selenium
|
91
|
+
#
|
92
|
+
def link(name, identifier)
|
93
|
+
define_method(name) do
|
94
|
+
platform.click_link_for identifier
|
95
|
+
end
|
96
|
+
define_method("#{name}_link") do
|
97
|
+
platform.link_for identifier
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
#
|
102
|
+
# adds four methods - one to check, another to uncheck, another
|
103
|
+
# to return the state of a checkbox, and a final method to return
|
104
|
+
# a PageObject::Elements::CheckBox object representing the checkbox.
|
105
|
+
#
|
106
|
+
# Example: checkbox(:active, {:name => "is_active"})
|
107
|
+
# will generate the 'check_active', 'uncheck_active',
|
108
|
+
# 'active_checked?' and 'active_checkbox' methods.
|
109
|
+
#
|
110
|
+
# @param the name used for the generated methods
|
111
|
+
# @param identifier how we find a checkbox. The valid values are:
|
112
|
+
# :class => Watir and Selenium
|
113
|
+
# :id => Watir and Selenium
|
114
|
+
# :index => Watir only
|
115
|
+
# :name => Watir and Selenium
|
116
|
+
# :xpath => Watir and Selenium
|
117
|
+
#
|
118
|
+
def checkbox(name, identifier)
|
119
|
+
define_method("check_#{name}") do
|
120
|
+
platform.check_checkbox(identifier)
|
121
|
+
end
|
122
|
+
define_method("uncheck_#{name}") do
|
123
|
+
platform.uncheck_checkbox(identifier)
|
124
|
+
end
|
125
|
+
define_method("#{name}_checked?") do
|
126
|
+
platform.checkbox_checked?(identifier)
|
127
|
+
end
|
128
|
+
define_method("#{name}_checkbox") do
|
129
|
+
platform.checkbox_for identifier
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
#
|
134
|
+
# adds four methods - one to select, another to clear,
|
135
|
+
# another to return if a radio button is selected, and
|
136
|
+
# another method to return a PageObject::Elements::RadioButton
|
137
|
+
# object representing the radio button element
|
138
|
+
#
|
139
|
+
# Example: radio_button(:north, {:id => "north"})
|
140
|
+
# will generate 'select_north', 'clear_north',
|
141
|
+
# 'north_selected?' and 'north_radio_button' methods
|
142
|
+
#
|
143
|
+
# @param the name used for the generated methods
|
144
|
+
# @param identifier how we find a checkbox. The valid values are:
|
145
|
+
# :class => Watir and Selenium
|
146
|
+
# :id => Watir and Selenium
|
147
|
+
# :index => Watir only
|
148
|
+
# :name => Watir and Selenium
|
149
|
+
# :xpath => Watir and Selenium
|
150
|
+
#
|
151
|
+
def radio_button(name, identifier)
|
152
|
+
define_method("select_#{name}") do
|
153
|
+
platform.select_radio(identifier)
|
154
|
+
end
|
155
|
+
define_method("clear_#{name}") do
|
156
|
+
platform.clear_radio(identifier)
|
157
|
+
end
|
158
|
+
define_method("#{name}_selected?") do
|
159
|
+
platform.radio_selected?(identifier)
|
160
|
+
end
|
161
|
+
define_method("#{name}_radio_button") do
|
162
|
+
platform.radio_button_for identifier
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
def button(name, identifier)
|
167
|
+
define_method(name) do
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
@@ -0,0 +1,8 @@
|
|
1
|
+
|
2
|
+
require 'page-object/elements/element'
|
3
|
+
require 'page-object/elements/link'
|
4
|
+
require 'page-object/elements/text_field'
|
5
|
+
require 'page-object/elements/select_list'
|
6
|
+
require 'page-object/elements/check_box'
|
7
|
+
require 'page-object/elements/button'
|
8
|
+
require 'page-object/elements/radio_button'
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module PageObject
|
2
|
+
module Elements
|
3
|
+
class Button < Element
|
4
|
+
|
5
|
+
def self.watir_identifier_for identifier
|
6
|
+
identifier_for identifier, watir_finders, watir_mapping
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.selenium_identifier_for identifier
|
10
|
+
identifier_for identifier, selenium_finders, selenium_mapping
|
11
|
+
return identifier.keys.first, identifier.values.first
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module PageObject
|
2
|
+
module Elements
|
3
|
+
class CheckBox < Element
|
4
|
+
|
5
|
+
def self.watir_identifier_for identifier
|
6
|
+
identifier_for identifier, watir_finders, watir_mapping
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.selenium_identifier_for identifier
|
10
|
+
identifier = identifier_for identifier, selenium_finders, selenium_mapping
|
11
|
+
return identifier.keys.first, identifier.values.first
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module PageObject
|
2
|
+
module Elements
|
3
|
+
|
4
|
+
#
|
5
|
+
# Contains functionality that is common across all elements.
|
6
|
+
#
|
7
|
+
class Element
|
8
|
+
|
9
|
+
def initialize(element, platform)
|
10
|
+
@element = element
|
11
|
+
include_platform_for platform
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.identifier_for identifier, find_by, find_by_mapping
|
15
|
+
how, what = identifier.keys.first, identifier.values.first
|
16
|
+
return how => what if find_by.include? how
|
17
|
+
return find_by_mapping[how] => what if find_by_mapping[how]
|
18
|
+
return nil => what
|
19
|
+
end
|
20
|
+
|
21
|
+
protected
|
22
|
+
|
23
|
+
def self.watir_finders
|
24
|
+
[:class, :id, :index, :name, :xpath]
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.watir_mapping
|
28
|
+
{}
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.selenium_finders
|
32
|
+
[:class, :id, :name, :xpath]
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.selenium_mapping
|
36
|
+
{}
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def include_platform_for platform
|
42
|
+
if platform[:platform] == :watir
|
43
|
+
require 'page-object/watir_element'
|
44
|
+
self.class.send :include, PageObject::WatirElement
|
45
|
+
else
|
46
|
+
require 'page-object/selenium_element'
|
47
|
+
self.class.send :include, PageObject::SeleniumElement
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|