page_object_wrapper 0.0.1 → 0.0.2

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.
data/.gitignore CHANGED
@@ -8,6 +8,8 @@ InstalledFiles
8
8
  _yardoc
9
9
  coverage
10
10
  doc/
11
+ coverage
12
+ InstalledFiles
11
13
  lib/bundler/man
12
14
  pkg
13
15
  rdoc
@@ -15,3 +17,7 @@ spec/reports
15
17
  test/tmp
16
18
  test/version_tmp
17
19
  tmp
20
+ # YARD artifacts
21
+ .yardoc
22
+ _yardoc
23
+ doc/
data/README.md CHANGED
@@ -4,6 +4,8 @@ Wraps watir-webdriver with convenient testing interface, based on PageObjects au
4
4
 
5
5
  ## Installation
6
6
 
7
+ Install Firefox on your system
8
+
7
9
  Add this line to your application's Gemfile:
8
10
 
9
11
  gem 'page_object_wrapper'
@@ -18,7 +20,352 @@ Or install it yourself as:
18
20
 
19
21
  ## Usage
20
22
 
21
- TODO
23
+ ####please look into specs for more detailed usage examples
24
+
25
+ #Page object
26
+
27
+ ##PageObjectWrapper
28
+
29
+ ###has .start_browser method which puts Watir::Browser.new to Page.accessor by default
30
+ PageObjectWrapper.start_browser
31
+ PageObjectWrapper::Page.accessor.should be_a(Watir::Browser)
32
+ ###has .stop_browser method which closes browser
33
+ PageObjectWrapper.stop_browser
34
+ PageObjectWrapper::Page.accessor.should_not exist
35
+ ###has .restart_browser method which restart current browser
36
+ PageObjectWrapper.start_browser
37
+ PageObjectWrapper.restart_browser
38
+ PageObjectWrapper::Page.accessor.should be_a(Watir::Browser)
39
+ ###has .domain= method which reprsents the domain of DUT
40
+ PageObjectWrapper.domain = 'www.google.com'
41
+ google_search_page_class.new(true)
42
+ PageObjectWrapper::Page.accessor.title.should eq('Google')
43
+ ###has .timeout= method which sets implicit timeout for webdriver (default is 5 sec)
44
+ not working yet
45
+ ##PageObject class and instance in general
46
+ let(:page_object){
47
+ class GoogleSearchPage < PageObjectWrapper::Page
48
+ attr_accessor :find_form
49
+ @url="/"
50
+ def initialize visit=false
51
+ super visit
52
+ end
53
+ end
54
+ GoogleSearchPage
55
+ }
56
+ ###PageObject class has @url class variable which can be treated as Page specific path inside current domain
57
+ page_object.url.should eq('/')
58
+ ###init with 'true' is similar to openning page in browser
59
+ google_search_page = page_object.new(true)
60
+ page_object.accessor.title.should eq('Google')
61
+ ###init with 'false' just returns new instanse, but does not opens browser on that page
62
+ google_search_page = page_object.new(false)
63
+ page_object.accessor.title.should_not eq('Google')
64
+ ##expected element
65
+ let(:google_search_with_wrong_expected_element_page_class){
66
+ class NotGoogleSearchPage < PageObjectWrapper::Page
67
+ attr_accessor :find_form
68
+ @url="/"
69
+ expected_element :text_field, :name => 'some element that does not exist on the page'
70
+
71
+ def initialize visit=false
72
+ super visit
73
+ end
74
+ end
75
+ NotGoogleSearchPage
76
+ }
77
+ let(:google_search_with_correct_expected_element_page_class){
78
+ class GoogleSearchPage < PageObjectWrapper::Page
79
+ attr_accessor :find_form
80
+ @url="/"
81
+ expected_element :text_field, :name => 'q'
82
+
83
+ def initialize visit=false
84
+ super visit
85
+ end
86
+ end
87
+ GoogleSearchPage
88
+ }
89
+ ###should raise error when trying to init google_search_with_wrong_expected_element_page_class
90
+ begin
91
+ gsearch_page = google_search_with_wrong_expected_element_page_class.new(true)
92
+ rescue PageError => e
93
+ e.should be_a(PageError)
94
+ e.message.should =~ /PROBLEM:/
95
+ e.message.should =~ /PAGE:/
96
+ e.message.should =~ /URL:/
97
+ end
98
+ ###should init google_search_with_correct_expected_element_page_class successfully
99
+ gsearch_page = google_search_with_correct_expected_element_page_class.new(true)
100
+ gsearch_page.should be_a(google_search_with_correct_expected_element_page_class)
101
+ ##creation of a PageObject method
102
+ let(:pages_definition){
103
+ class GoogleAdvancedSearchPage < PageObjectWrapper::Page
104
+ attr_accessor :as_form
105
+ @url="/advanced_search"
106
+ expected_element :text_field, :name => 'as_q'
107
+ def initialize visit=false
108
+ super visit
109
+ @as_form = form(GoogleResultsPage, {:name => 'f'})
110
+ @as_form.editable(:text_field, {:name => 'as_q'}, :with_words, 'with_words default value', true)
111
+ @as_form.editable(:text_field, {:name => 'as_epq'}, :with_phrase, 'with_phrase default value', true)
112
+ @as_form.editable(:text_field, {:name => 'as_oq'}, :with_any_word, 'with_any_word default value', false)
113
+ @as_form.submitter(:input, {:type => 'submit'})
114
+ end
115
+ end
116
+
117
+ class GoogleResultsPage < PageObjectWrapper::Page
118
+ @url="/"
119
+ expected_element :button, :name => 'btnG'
120
+ def initialize visit=false
121
+ super visit
122
+ end
123
+
124
+ def open_advanced_search
125
+ @@accessor.span(:id => 'ab_opt_icon').when_present.click
126
+ @@accessor.a(:id => 'ab_as').when_present.click
127
+ GoogleAdvancedSearchPage.new
128
+ end
129
+ end
130
+
131
+ class GoogleSearchPage < PageObjectWrapper::Page
132
+ attr_accessor :find_form
133
+ @url="/"
134
+ expected_element :text_field, :name => 'q'
135
+ def initialize visit=false
136
+ super visit
137
+ @find_form = form(GoogleResultsPage, {:action => '/search'})
138
+ @find_form.editable(:text_field, {:name => 'q'}, :seach_what, '@find_form default value', true)
139
+ end
140
+ end
141
+ {:gsearch_page_class => GoogleSearchPage, :gresults_page => GoogleResultsPage, :gadv_page => GoogleAdvancedSearchPage}
142
+ }
143
+ ###return value should be another PageObject instance
144
+ gsearch_page = pages_definition[:gsearch_page_class].new(true)
145
+ gsearch_page.find_form.fill_required
146
+ gresults_page = gsearch_page.find_form.submit(true)
147
+ gadv_page = gresults_page.open_advanced_search
148
+ gadv_page.should be_a(pages_definition[:gadv_page])
149
+
150
+ #Form wrapper
151
+
152
+ ##form definition
153
+ let(:page_objects){
154
+ class GoogleAdvancedSearchPage < PageObjectWrapper::Page
155
+ attr_accessor :as_form
156
+ @url="/advanced_search"
157
+ expected_element :text_field, :name => 'as_q'
158
+ def initialize visit=false
159
+ super visit
160
+ @as_form = form(GoogleResultsPage, {:name => 'f'})
161
+ @as_form.editable(:text_field, {:name => 'as_q'}, :with_words, 'with_words default value', true)
162
+ @as_form.editable(:text_field, {:name => 'as_epq'}, :with_phrase, 'with_phrase default value', true)
163
+ @as_form.editable(:text_field, {:name => 'as_oq'}, :with_any_word, 'with_any_word default value', false)
164
+ @as_form.submitter(:input, {:type => 'submit'})
165
+ end
166
+ end
167
+ class GoogleResultsPage < PageObjectWrapper::Page
168
+ @url="/"
169
+ expected_element :button, :name => 'btnG'
170
+ def initialize visit=false
171
+ super visit
172
+ @find_form = form(GoogleResultsPage, {:action => '/search'})
173
+ @find_form.editable(:text_field, {:name => 'q'}, :seach_what, '@find_form default value', true)
174
+ end
175
+ end
176
+ {:gresults_page_class => GoogleResultsPage, :gadv_page_class => GoogleAdvancedSearchPage}
177
+ }
178
+ ###is defined as #form(TargetPage, how_find_hash)
179
+ @as_form = form(GoogleResultsPage, {:name => 'f'})
180
+ @find_form = form(GoogleResultsPage, {:action => '/search'})
181
+ ###has #editable(:field_type, how_find_hash, :label, default_value, required?) method to set form's fields
182
+ ### :field_type sets corresponding watir element type
183
+ ### how_find_hash is used to locate corresponding watir element on the page
184
+ ### :label is used to reffer to the form field after definition
185
+ ### default_value is used to populate fields with default test data
186
+ ### required = true | false and indicates if the field is required
187
+ ###
188
+ @as_form.editable(:text_field, {:name => 'as_q'}, :with_words, 'with_words default value', true)
189
+ @as_form.editable(:text_field, {:name => 'as_epq'}, :with_phrase, 'with_phrase default value', true)
190
+ @as_form.editable(:text_field, {:name => 'as_oq'}, :with_any_word, 'with_any_word default value', false)
191
+ ###has #submitter(:field_type, how_find_hash, how_click_mehtod, click_params) method to set form's submitter
192
+ ### :field_type sets corresponding watir element type
193
+ ### how_find_hash is used to locate corresponding watir element on the page
194
+ ### how_click_mehtod is used to tell Waitr the method which should be applied to click the submitter
195
+ ### click_params set parameters for the how_click_mehtod
196
+ ###
197
+ @as_form.submitter(:input, {:type => 'submit'})
198
+ ##form usage
199
+ let(:page_objects){
200
+ class GoogleAdvancedSearchPage < PageObjectWrapper::Page
201
+ attr_accessor :as_form
202
+ @url="/advanced_search"
203
+ expected_element :text_field, :name => 'as_q'
204
+ def initialize visit=false
205
+ super visit
206
+ @as_form = form(GoogleSearchPage, {:name => 'f'})
207
+ @as_form.editable(:text_field, {:name => 'as_q'}, :with_words, 'with_words default value', true)
208
+ @as_form.editable(:text_field, {:name => 'as_epq'}, :with_phrase, 'with_phrase default value', true)
209
+ @as_form.editable(:text_field, {:name => 'as_oq'}, :with_any_word, 'with_any_word default value', false)
210
+ @as_form.submitter(:input, {:type => 'submit'})
211
+ end
212
+ end
213
+ class GoogleSearchPage < PageObjectWrapper::Page
214
+ attr_accessor :find_form
215
+ @url="/"
216
+ expected_element :text_field, :name => 'q' # tells Watir that we expect this element which identifies the page in a uniq way
217
+ def initialize visit=false
218
+ super visit
219
+ @find_form = form(GoogleSearchPage, {:action => '/search'})
220
+ @find_form.editable(:text_field, {:name => 'q'}, :search_what, '@find_form default value', true)
221
+ end
222
+ end
223
+ {:gsearch_page_class => GoogleSearchPage, :gadv_page_class => GoogleAdvancedSearchPage}
224
+ }
225
+ ###has #submit(flag) method which submits form
226
+ ### if flag = true than TargetPage instance is returned
227
+ ### if flag = false than CurrentPage instance is returned
228
+ ### if submitter is defined, than it's used to submit the form, otherwise standart Watir::Form submit is used
229
+ ###
230
+ gadv_page = page_objects[:gadv_page_class].new(true)
231
+ gsearch_page = gadv_page.as_form.submit(true)
232
+ gsearch_page.should be_a(GoogleSearchPage)
233
+ gsearch_page_reloaded = gsearch_page.find_form.submit(false)
234
+ gsearch_page_reloaded.should be_a(GoogleSearchPage)
235
+ ###field's watir elements can be accessed by labels
236
+ gsearch_page = page_objects[:gsearch_page_class].new(true)
237
+ gsearch_page.find_form.search_what.should be_a(Watir::TextField)
238
+ ###fields default values set during form definition can be retrieved with #default(:label) method
239
+ gsearch_page = page_objects[:gsearch_page_class].new(true)
240
+ gsearch_page.find_form.default(:search_what).should eq('@find_form default value')
241
+ ###has #each method which allows navigating between form fields
242
+ gadv_page.as_form.each{|form_field|
243
+ form_field.should be_a(Editable)
244
+ form_field.watir_element.should be_a(Watir::TextField)
245
+ ###has #each_required method which allows navigating between form required fields
246
+ gadv_page.as_form.each_required{|form_field|
247
+ form_field.should be_a(Editable)
248
+ form_field.watir_element.should be_a(Watir::TextField)
249
+ form_field.should be_required
250
+ }
251
+ ###has #fill_only(:label => value) method which populated form's :label field with 'value'
252
+ ### method returns form object
253
+ ###
254
+ form = gadv_page.as_form.fill_only(:with_words => 'some value')
255
+ gadv_page.as_form.with_words.value.should eq('some value')
256
+ ###has #fill_all(:except => labels_array | label) method which populated all form's fields with default values
257
+ ### if except_hash is not nil than provided fields are not populated
258
+ ### method returns form object
259
+ ###
260
+ form = gadv_page.as_form.fill_all
261
+ gadv_page.as_form.each{|field|
262
+ field.watir_element.value.should eq(gadv_page.as_form.default(field.label))
263
+ }
264
+ ###has #fill_required(:except => labels_array | label) method which populated all required form's fields with default values
265
+ ### if except_hash is not nil than provided fields are not populated
266
+ ### method returns form object
267
+ ###
268
+ gadv_page.as_form.fill_required(:except => :with_words)
269
+ gadv_page.as_form.each_required{|field|
270
+ if field.label==:with_words
271
+ field.watir_element.value.should eq ''
272
+ else
273
+ field.watir_element.value.should eq(gadv_page.as_form.default(field.label))
274
+ end
275
+ }
276
+
277
+ #Table wrapper
278
+ before :all do
279
+ PageObjectWrapper.domain = 'http://wiki.openqa.org'
280
+ end
281
+ let(:page_object){
282
+ class WatirPage < PageObjectWrapper::Page
283
+ attr_accessor :some_table
284
+ @url="/display/WTR/HTML+Elements+Supported+by+Watir"
285
+ expected_element :a, :text => 'HTML Elements Supported by Watir'
286
+ def initialize visit=false
287
+ super visit
288
+ @some_table = table(:class => 'confluenceTable')
289
+ end
290
+ end
291
+ WatirPage
292
+ }
293
+ ##table definition
294
+
295
+ ###has #table(how_find_hash) method to define a table on the page
296
+ @some_table = table(:class => 'confluenceTable')
297
+ ##table usage
298
+ before :all do
299
+ PageObjectWrapper.domain = 'http://wiki.openqa.org'
300
+ end
301
+ let(:page_object){
302
+ class WatirPage < PageObjectWrapper::Page
303
+ attr_accessor :some_table
304
+ @url="/display/WTR/HTML+Elements+Supported+by+Watir"
305
+ expected_element :a, :text => 'HTML Elements Supported by Watir'
306
+ def initialize visit=false
307
+ super visit
308
+ @some_table = table(:class => 'confluenceTable')
309
+ end
310
+ end
311
+ WatirPage
312
+ }
313
+ ###has #cells method which returns all Watir table cells
314
+ page = page_object.new(true)
315
+ page.some_table.cells.first.should be_a(Watir::TableCell)
316
+ ###has #has_cell?(text) method wich returns true if the table has a cell with specified text
317
+ page = page_object.new(true)
318
+ page.some_table.should have_cell('<td>')
319
+ ###has #select(column_name, where_hash) method wich returns cell inside specified column wich corresponds to a specified where_hash
320
+ page = page_object.new(true)
321
+ cell = page.some_table.select('HTML tag', :where => {'Watir method' => 'cell'})
322
+ cell.should be_a(Watir::TableCell)
323
+ cell.text.should eq '<td>'
324
+ ###is possible to specify just parts of column names in #select method
325
+ cell = page.some_table.select('HTML', :where => {'Watir met' => 'cell'})
326
+
327
+ #Pagination wrapper
328
+
329
+ ##pagination definition
330
+
331
+ ###TODO
332
+ Needs to be reimplemented. Current realization is fo rails apps only
333
+ ##pagination usage
334
+
335
+ ###TODO
336
+ Needs to be reimplemented. Current realization is fo rails apps only
337
+
338
+ #TestData class
339
+ let(:user1){
340
+ "login: user1
341
+ email: user1@example.com
342
+ password: secret1
343
+ etc: other data"
344
+ }
345
+ let(:user2){
346
+ "login: user2
347
+ email: user2@example.com
348
+ password: secret2
349
+ etc: other data"
350
+ }
351
+ ##is initialized with hash and generates dynamic attributes for an instance
352
+ dynamically_defined_user = PageObjectWrapper::TestData.new(YAML.load(user1))
353
+ dynamically_defined_user.login.should eq 'user1'
354
+ dynamically_defined_user.email.should eq 'user1@example.com'
355
+ dynamically_defined_user.password.should eq 'secret1'
356
+ dynamically_defined_user.etc.should eq 'other data'
357
+ ##has .find method which allows finding dynamically defined objects
358
+ dynamically_defined_user1 = PageObjectWrapper::TestData.new(YAML.load(user1))
359
+ dynamically_defined_user2 = PageObjectWrapper::TestData.new(YAML.load(user2))
360
+ user1 = PageObjectWrapper::TestData.find(:login,'user1')
361
+ user1.email.should eq 'user1@example.com'
362
+ ##has .each method which allows navigating between objects
363
+ dynamically_defined_user1 = PageObjectWrapper::TestData.new(YAML.load(user1))
364
+ dynamically_defined_user2 = PageObjectWrapper::TestData.new(YAML.load(user2))
365
+ PageObjectWrapper::TestData.each{|user|
366
+ user.etc.should eq 'other data'
367
+ }
368
+
22
369
 
23
370
  ## Contributing
24
371
 
@@ -27,3 +374,7 @@ TODO
27
374
  3. Commit your changes (`git commit -am 'Add some feature'`)
28
375
  4. Push to the branch (`git push origin my-new-feature`)
29
376
  5. Create new Pull Request
377
+ page_object_wrapper
378
+ ===================
379
+
380
+ Wraps watir-webdriver with convenient testing interface, based on PageObjects automation testing pattern. Simplifies resulting automated test understanding.
@@ -1,6 +1,99 @@
1
- require "page_object_wrapper/version"
2
- require "Page"
1
+ # -*- encoding : utf-8 -*-
2
+ require "watir-webdriver"
3
+ require "version"
4
+ require 'Exceptions'
5
+ require 'Form'
6
+ require 'Table'
7
+ require 'Pagination'
8
+ require 'DynamicClass'
3
9
 
4
10
  module PageObjectWrapper
5
- # Your code goes here...
11
+
12
+ class TestData < DynamicClass; end
13
+
14
+ def self.start_browser b=nil
15
+ Page.accessor = (b.nil?)? Watir::Browser.new : b
16
+ Page.accessor.driver.manage.timeouts.implicit_wait=3
17
+ Page.accessor.driver.manage.timeouts.page_load=30
18
+ Page.accessor.driver.manage.timeouts.script_timeout=30
19
+ end
20
+
21
+ def self.stop_browser
22
+ Page.accessor.quit
23
+ end
24
+
25
+ def self.restart_browser
26
+ self.stop_browser
27
+ self.start_browser
28
+ end
29
+
30
+ def self.domain=(val)
31
+ Page.base_url = val
32
+ end
33
+
34
+ class Page
35
+ class << self
36
+ attr_accessor :url, :expected_elements, :full_url
37
+ end
38
+
39
+ @@base_url = ''
40
+ @@accessor = nil
41
+ @url = ''
42
+ @expected_elements = {}
43
+
44
+ def initialize visit = false
45
+ self.class.full_url = @@base_url + self.class.url
46
+ @@accessor.goto self.class.full_url if visit
47
+
48
+ if not self.class.expected_elements.nil?
49
+ if not (self.class.expected_elements.empty?)
50
+ self.class.expected_elements.each{|element_type, identifier|
51
+ begin
52
+ @@accessor.send(element_type,identifier).wait_until_present
53
+ rescue
54
+ raise PageError.new("expected_element #{element_type}, #{identifier.inspect} not found after a set timeout",self.class,self.class.full_url)
55
+ end
56
+ }
57
+ end
58
+ end
59
+ end
60
+
61
+ def self.base_url=(val)
62
+ @@base_url = val
63
+ end
64
+
65
+ def self.base_url
66
+ @@base_url
67
+ end
68
+
69
+ def self.accessor
70
+ @@accessor
71
+ end
72
+
73
+ def self.accessor=(val)
74
+ @@accessor = val
75
+ end
76
+ def self.expected_element(element_type,identifier)
77
+ self.expected_elements = {} if self.expected_elements.nil?
78
+ self.expected_elements[element_type] = identifier
79
+ end
80
+
81
+ def form(target_page,*args)
82
+ Form.new(self.class,target_page,@@accessor,*args)
83
+ end
84
+
85
+ def table(*args)
86
+ Table.new(@@accessor,*args)
87
+ end
88
+
89
+ def paginate(div_args)
90
+ Pagination.new(self,div_args)
91
+ end
92
+
93
+ def has_warning?(text)
94
+ @@accessor.text.include?(text)
95
+ end
96
+
97
+ alias :has_text? :has_warning?
98
+ end
6
99
  end