page_object_wrapper 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
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