page-object 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. data/.gitignore +6 -0
  2. data/Gemfile +3 -0
  3. data/LICENSE +20 -0
  4. data/README.md +87 -0
  5. data/Rakefile +51 -0
  6. data/cucumber.yml +5 -0
  7. data/features/check_box.feature +39 -0
  8. data/features/html/static_elements.html +34 -0
  9. data/features/link.feature +42 -0
  10. data/features/page_level_actions.feature +19 -0
  11. data/features/radio_button.feature +40 -0
  12. data/features/select_list.feature +40 -0
  13. data/features/step_definitions/accessor_steps.rb +88 -0
  14. data/features/step_definitions/element_steps.rb +28 -0
  15. data/features/step_definitions/page_level_actions_steps.rb +12 -0
  16. data/features/step_definitions/page_traversal_steps.rb +5 -0
  17. data/features/support/env.rb +18 -0
  18. data/features/support/page.rb +45 -0
  19. data/features/support/url_helper.rb +16 -0
  20. data/features/text_field.feature +39 -0
  21. data/lib/page-object.rb +52 -0
  22. data/lib/page-object/accessors.rb +171 -0
  23. data/lib/page-object/elements.rb +8 -0
  24. data/lib/page-object/elements/button.rb +15 -0
  25. data/lib/page-object/elements/check_box.rb +15 -0
  26. data/lib/page-object/elements/element.rb +52 -0
  27. data/lib/page-object/elements/link.rb +34 -0
  28. data/lib/page-object/elements/radio_button.rb +15 -0
  29. data/lib/page-object/elements/select_list.rb +21 -0
  30. data/lib/page-object/elements/text_field.rb +33 -0
  31. data/lib/page-object/selenium_element.rb +12 -0
  32. data/lib/page-object/selenium_page_object.rb +190 -0
  33. data/lib/page-object/version.rb +3 -0
  34. data/lib/page-object/watir_element.rb +12 -0
  35. data/lib/page-object/watir_page_object.rb +190 -0
  36. data/page-object.gemspec +29 -0
  37. data/spec/page-object/accessors_spec.rb +297 -0
  38. data/spec/page-object/elements/button_spec.rb +23 -0
  39. data/spec/page-object/elements/check_box_spec.rb +21 -0
  40. data/spec/page-object/elements/element_spec.rb +54 -0
  41. data/spec/page-object/elements/link_spec.rb +34 -0
  42. data/spec/page-object/elements/radio_button_spec.rb +21 -0
  43. data/spec/page-object/elements/select_list_spec.rb +22 -0
  44. data/spec/page-object/elements/text_field_spec.rb +32 -0
  45. data/spec/page-object/page-object_spec.rb +78 -0
  46. data/spec/spec_helper.rb +31 -0
  47. 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,5 @@
1
+
2
+ Given /^I am on the static elements page$/ do
3
+ @page = Page.new(@browser)
4
+ @page.navigate_to(UrlHelper.static_elements)
5
+ 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,16 @@
1
+ module UrlHelper
2
+ class << self
3
+ def html
4
+ File.expand_path("#{File.dirname(__FILE__)}/../html")
5
+ end
6
+
7
+ def files
8
+ "file://#{html}"
9
+ end
10
+
11
+
12
+ def static_elements
13
+ "#{files}/static_elements.html"
14
+ end
15
+ end
16
+ 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
@@ -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