web4cucumber 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.
@@ -0,0 +1,26 @@
1
+ :login:
2
+ :pages:
3
+ - 'login_page'
4
+ :final_checkpoints:
5
+ :a:
6
+ :type: a
7
+ :selector:
8
+ :href: "/app/account"
9
+
10
+ :login_page:
11
+ :url: '/app/login'
12
+ :sleep: 1
13
+ :commit:
14
+ :type: input
15
+ :selector:
16
+ :class: 'create'
17
+ :expected_fields:
18
+ :login:
19
+ :type: textfield
20
+ :selector:
21
+ :id: 'web_user_rhlogin'
22
+ :password:
23
+ :type: textfield
24
+ :selector:
25
+ :id: 'web_user_password'
26
+
@@ -0,0 +1,641 @@
1
+ # Copyright 2015 Red Hat, Inc. and/or its affiliates.
2
+ #
3
+ # This program is free software: you can redistribute it and/or modify
4
+ # it under the terms of the GNU General Public License as published by
5
+ # the Free Software Foundation, either version 3 of the License, or
6
+ # (at your option) any later version.
7
+ #
8
+ # This program is distributed in the hope that it will be useful,
9
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
+ # GNU General Public License for more details.
12
+ #
13
+ # You should have received a copy of the GNU General Public License
14
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
15
+
16
+ require 'watir-webdriver'
17
+ require 'headless'
18
+
19
+ class Web4Cucumber
20
+ def positive_checkpoint_lookup(checkpoints, result, options=nil)
21
+ # checkpoints should be a hash
22
+ checkpoints.each_pair { |key, value|
23
+ if options
24
+ begin
25
+ value[:selector].each_pair do |how, what|
26
+ options.keys.each do |optkey|
27
+ if what.match Regexp.new("<#{optkey.to_s}>")
28
+ what.gsub!("<#{optkey.to_s}>", options[optkey])
29
+ end
30
+ end
31
+ end
32
+ rescue NoMethodError
33
+ raise "Please provide :selector: keyword in your checkpoint"
34
+ end
35
+ else
36
+ @@logger.info "No options provided to checkpoint lookup"
37
+ end
38
+ if value.has_key? :sleep
39
+ sleep value[:sleep]
40
+ end
41
+ secs = 0
42
+ if value.has_key? :type
43
+ myhash = {
44
+ :a => @@b.a(value[:selector]),
45
+ :text => @@b.element(value[:selector]),
46
+ :input => @@b.input(value[:selector]),
47
+ :select => @@b.select(value[:selector])
48
+ }
49
+ element = myhash[value[:type].to_sym]
50
+ else
51
+ element = @@b.element(value[:selector])
52
+ end
53
+ until element.exists? or secs == 10 do
54
+ sleep 1
55
+ secs +=1
56
+ end
57
+ unless element.exists?
58
+ @@logger.warn "#{key} with #{value[:selector]} can not found in #{@@b.url}"
59
+ result[:failed_positive_checkpoints] << value[:selector]
60
+ result[:result] = false
61
+ end
62
+ }
63
+ return result
64
+ end
65
+
66
+ def negative_checkpoint_lookup(checkpoints, result, options=nil)
67
+ # checkpoints should be a hash
68
+ sleep 7
69
+ checkpoints.each_pair { |key, value|
70
+ if options
71
+ value[:selector].each_pair do |how, what|
72
+ options.keys.each do |optkey|
73
+ if what.match Regexp.new("<#{optkey.to_s}>")
74
+ what.gsub!("<#{optkey.to_s}>", options[optkey])
75
+ end
76
+ end
77
+ end
78
+ else
79
+ @@logger.info "No options provided to checkpoint lookup"
80
+ end
81
+ if @@b.element(value[:selector]).exists?
82
+ @@logger.warn("#{key} with #{value} should not be display on the #{@@b.url}")
83
+ result[:result] = false
84
+ result[:failed_negative_checkpoints] << value[:selector]
85
+ end
86
+ }
87
+ return result
88
+ end
89
+
90
+ def screenshot_save
91
+ FileUtils.mkdir_p("screenshots")
92
+ screenshot = File.join("screenshots", "error.png")
93
+ @@b.driver.save_screenshot(screenshot)
94
+ File::open("screenshots/output.html", 'w') {
95
+ |f| f.puts(@@b.html)
96
+ }
97
+ end
98
+
99
+
100
+ def check_iframe(page_rules)
101
+ if page_rules.has_key? :iframe
102
+ return @@b.iframe(page_rules[:iframe][:selector])
103
+ else
104
+ return @@b
105
+ end
106
+ end
107
+
108
+ def wait_for_element(element, may_absent)
109
+ if @counter == 20
110
+ screenshot_save
111
+ unless may_absent # Sometimes not finding an element is OK, by design
112
+ @result[:failed_positive_checkpoints] << element
113
+ raise "Failed to find the #{element.to_s} element"
114
+ end
115
+ end
116
+ sleep 1
117
+ @counter += 1
118
+ end
119
+
120
+ def run_action(key, options)
121
+ @result = {:result=>true, :failed_positive_checkpoints=>[], :failed_negative_checkpoints=>[], :errors => []}
122
+ @@rules.freeze
123
+ rules = Marshal.load(Marshal.dump(@@rules))
124
+ action_rules = rules[key.to_sym]
125
+ # loop over all pages...
126
+ unless action_rules[:pages]
127
+ @@logger.warn("No pages defined in the #{key} action")
128
+ end
129
+ action_rules[:pages].each { |page|
130
+ # sometimes you need to stop the execution at some point to test whether
131
+ # partial form data gets into the database, for example. In this case you
132
+ # can provide :stop_at key with the name of the page for a value and the
133
+ # action will be aborted once it gets into this page
134
+ if options.has_key?(:stop_at) and options[:stop_at] == page
135
+ @result[:result] = false
136
+ @result[:errors] << "Execution stopped at page #{page}"
137
+ return @result
138
+ end
139
+ # sometimes also it is pretty handy to be able to stick the debugger at
140
+ # some point to have a human control over the webdriver instance. Then
141
+ # in the same way stick the :debug_at keyword with the page name as a value
142
+ # into the options hash. The webdriver is available via @@b clas variable
143
+ if options.has_key?(:debug_at) and options[:stop_at] == page
144
+ require "byebug"
145
+ byebug
146
+ end
147
+ page_rules = rules[page.to_sym]
148
+ unless page_rules
149
+ @@logger.warn("The page #{page} not found in #{key} yaml file, maybe you have wrong yaml format...")
150
+ end
151
+ if page_rules.has_key? :url
152
+ options.keys.each do |key|
153
+ if page_rules[:url].match Regexp.new("<#{key.to_s}>")
154
+ page_rules[:url].gsub!("<#{key.to_s}>", options[key])
155
+ end
156
+ end
157
+ elsif page_rules.has_key? :base_url
158
+ options.keys.each do |key|
159
+ if page_rules[:base_url].match Regexp.new("<#{key.to_s}>")
160
+ page_rules[:base_url].gsub!("<#{key.to_s}>", options[key])
161
+ end
162
+ end
163
+ else
164
+ @@logger.warn("#{page} has no url, trying default base_url")
165
+ end
166
+ if page_rules.has_key?(:url) or page_rules.has_key?(:base_url) or options.has_key?(:base_url)
167
+ if options.has_key? :base_url
168
+ url = options[:base_url]
169
+ elsif page_rules.has_key? :base_url
170
+ url = page_rules[:base_url]
171
+ else
172
+ # extract the host part from the current url. Makes it more flexible
173
+ # than to use fixed @@base_url
174
+ url = @@b.url.match(/(https?:\/\/.*?\/)/).captures[0]
175
+ end
176
+ if page_rules[:url].match /^\:\d+/
177
+ if url.match /\:\d+/
178
+ url.gsub!(/\:\d+\//, "")
179
+ else
180
+ url.gsub!(/\/$/, "")
181
+ end
182
+ end
183
+ if page_rules[:url]
184
+ url = url + page_rules[:url]
185
+ end
186
+ @@b.goto url
187
+ end
188
+ unless page_rules[:expected_forms]
189
+ @@logger.warn("No expected_forms defined in the #{page} page")
190
+ end
191
+ if page_rules.has_key? :sleep
192
+ sleep page_rules[:sleep]
193
+ end
194
+ driver = check_iframe(page_rules) # substitute browser operating with main html
195
+ # with the one operating with internal iframe
196
+ unless page_rules[:expected_fields]
197
+ @@logger.warn("No expected fields in #{page} page")
198
+ end
199
+ if page_rules.has_key? :expected_fields
200
+ page_rules[:expected_fields].each_pair { |name, prop|
201
+ # Beginning of page fields
202
+ possible_elements = {
203
+ # There could be more than one element with the same
204
+ # properties and only one would be visible. As an example:
205
+ # try adding more than one member to the same domain
206
+ 'select' => driver.select_lists(prop[:selector]),
207
+ 'checkbox' => driver.checkboxes(prop[:selector]),
208
+ 'radio' => driver.radios(prop[:selector]),
209
+ 'text_field' => driver.text_fields(prop[:selector]),
210
+ 'textfield' => driver.text_fields(prop[:selector]),
211
+ 'text_area' => driver.textareas(prop[:selector]),
212
+ 'textarea' => driver.textareas(prop[:selector]),
213
+ 'filefield' => driver.file_fields(prop[:selector]),
214
+ 'file_field' => driver.file_fields(prop[:selector]),
215
+ 'a' => driver.as(prop[:selector]),
216
+ 'element' => driver.elements(prop[:selector])
217
+ }
218
+ if prop.has_key?(:type) and not possible_elements.keys.include? prop[:type]
219
+ @@logger.error("Unsupported element #{prop[:type]} for cucushift, so type error?")
220
+ end
221
+ result ||= true
222
+ @counter = 0
223
+ prop[:type] ||= 'element' # default to 'element' unless declared explicitly
224
+ if prop[:type] == 'alert'
225
+ begin
226
+ @@b.alert.wait_until_present(3)
227
+ @@b.alert.ok
228
+ rescue Watir::Wait::TimeoutError => e
229
+ @result[:result] = false
230
+ @result[:errors] << "e.message"
231
+ end
232
+ end
233
+ options.each do |key,value|
234
+ if value.is_a? String and prop[:selector].values[0].match Regexp.new("<#{key.to_s}>")
235
+ prop[:selector].values[0].gsub!("<#{key.to_s}>", options[key])
236
+ end
237
+ end
238
+ elements = possible_elements[prop[:type]]
239
+ element = nil
240
+ elements.each do |elem|
241
+ if elem.visible?
242
+ element = elem
243
+ end
244
+ end
245
+ if (options.has_key? name and options[name]) or prop.has_key? :def_value
246
+ options.keys.each do |key|
247
+ if prop[:selector].values[0].match Regexp.new("<#{key.to_s}>")
248
+ prop[:selector].values[0].gsub!("<#{key.to_s}>", options[key])
249
+ end
250
+ end
251
+ if prop[:selector].values[0].size == 0
252
+ tmphash = prop[:selector].clone
253
+ # if no default value provided, put the value from options
254
+ tmphash.each_pair do |key, value|
255
+ prop[:selector][key] = options[name.to_sym]
256
+ end
257
+ end
258
+ if not element
259
+ if not prop[:may_absent]
260
+ @result[:result] = false
261
+ @result[:errors] << "Unable to find element #{name.to_s} by the following #{prop[:selector].keys[0].to_s}: #{prop[:selector].values[0]}"
262
+ end
263
+ else
264
+ until element.exists? do
265
+ begin
266
+ wait_for_element(prop[:selector], prop[:may_absent])
267
+ rescue Exception => e
268
+ result = false
269
+ break
270
+ end
271
+ end
272
+ if result # continue if nothing failed
273
+ if prop[:type] == 'select'
274
+ if options[name.to_sym]
275
+ driver.select_list(prop[:selector]).select_value options[name.to_sym].to_s
276
+ elsif prop[:def_value]
277
+ driver.select_list(prop[:selector]).select_value prop[:def_value]
278
+ else
279
+ @@logger.error("Please, provide a value for this element: #{prop}")
280
+ end
281
+ elsif ['filefield', 'file-field', 'file_field'].include? prop[:type]
282
+ element.set options[name]
283
+ elsif ['checkbox', 'radio', 'a', 'element'].include? prop[:type]
284
+ element.click
285
+ elsif ['textfield', 'text_field', 'text_area', 'textarea'].include? prop[:type]
286
+ element.clear
287
+ if options.has_key? name.to_sym
288
+ options[name.to_sym].each_char do |c|
289
+ element.append c
290
+ end
291
+ elsif prop.has_key? :def_value
292
+ element.send_keys prop[:def_value]
293
+ else
294
+ @@logger.error("Please provide the value for this element: #{prop}")
295
+ end
296
+ end
297
+ end
298
+ end
299
+ end
300
+ } # End of page fields
301
+ end
302
+ # each form ends with commit button
303
+ if page_rules.has_key? :checkpoints
304
+ @result = positive_checkpoint_lookup(page_rules[:checkpoints], @result)
305
+ else
306
+ @@logger.info "No positive checkpoints defined..."
307
+ end
308
+ if page_rules.has_key? :negative_checkpoints
309
+ @result = negative_checkpoint_lookup(page_rules[:negative_checkpoints], @result)
310
+ else
311
+ @@logger.info "No negative checkpoints defined..."
312
+ end
313
+ unless page_rules[:links]
314
+ @@logger.warn("No links defined in the #{page} page")
315
+ end
316
+ if page_rules.has_key? :links
317
+ page_rules[:links].each_pair do |key, value|
318
+ @@b.a(value[:selector]).click
319
+ if value.has_key? :checkpoints
320
+ @result = positive_checkpoint_lookup(value[:checkpoints], @result)
321
+ end
322
+ @@b.back
323
+ end
324
+ end
325
+ if page_rules.has_key? :commit
326
+ if page_rules[:commit].has_key?(:selector)
327
+ options.keys.each do |optkey|
328
+ if page_rules[:commit][:selector].values[0].include? "<#{optkey}>"
329
+ page_rules[:commit][:selector].values[0].gsub!("<#{optkey}>", options[optkey])
330
+ end
331
+ end
332
+ myhash = {
333
+ :input => @@b.input(page_rules[:commit][:selector]),
334
+ :a => @@b.a(page_rules[:commit][:selector]),
335
+ :button => @@b.button(page_rules[:commit][:selector])
336
+ }
337
+ begin
338
+ if page_rules[:commit].has_key? :type
339
+ button = myhash[page_rules[:commit][:type].to_sym]
340
+ else
341
+ button = @@b.element(page_rules[:commit][:selector])
342
+ end
343
+ begin
344
+ button.exists?
345
+ rescue Watir::Exception::MissingWayOfFindingObjectException
346
+ button = @@b.input(page_rules[:commit][:selector])
347
+ end
348
+ if options[:scroll] or page_rules[:commit][:scroll]
349
+ @@b.execute_script('arguments[0].scrollIntoView();', button)
350
+ sleep 1 # This scroll sometimes takes up to a second
351
+ end
352
+ button.click
353
+ rescue Exception => e
354
+ @result[:result]=false
355
+ @result[:error_message] = e.message
356
+ screenshot_save
357
+ end
358
+ elsif page_rules[:commit].has_key?(:type) and page_rules[:commit][:type] == 'alert'
359
+ @@b.alert.ok
360
+ else
361
+ raise "Please provide selector for #{page} page commit"
362
+ end
363
+ else
364
+ @@logger.warn("No commit defined in the #{page} page")
365
+ end
366
+ } # end of pages
367
+ if action_rules.has_key? :final_checkpoints
368
+ @result = positive_checkpoint_lookup(action_rules[:final_checkpoints], @result, options=options)
369
+ end
370
+ if action_rules.has_key? :negative_final_checkpoints
371
+ @result = negative_checkpoint_lookup(action_rules[:negative_final_checkpoints], @result, options=options)
372
+ end
373
+ unless @result[:failed_positive_checkpoints].empty? and @result[:failed_negative_checkpoints].empty?
374
+ @result[:result] = false
375
+ end
376
+ return @result
377
+ end
378
+
379
+ def web_to_load(options)
380
+ #returns an array of yaml files
381
+ if options.has_key? :version
382
+ return Dir.glob(File.join(options[:rules_path], options[:version], "*"))
383
+ else
384
+ return Dir.glob(File.join(options[:rules_path], "*"))
385
+ end
386
+ end
387
+
388
+ def initialize(options)
389
+ # Let's make sure, that we get all necessary options in the proper format
390
+ obligatory_options = [:base_url, :rules_path, :logger]
391
+ # :logger should be a Logger class instance with at least the following
392
+ # methods implemented, taking a string as an argument:
393
+ # - info
394
+ # - warn
395
+ # - error
396
+ unless options.is_a? Hash
397
+ raise "Please provide a hash of options. Valid option keys are: :base_url, :browser, rules_path and :version
398
+ The initialize method needs to know at least the base_url you want to test against and the :rules_path - path
399
+ to the folder where you store your yaml files with action descriptions. Other keys are optional"
400
+ end
401
+ if options.keys & obligatory_options == obligatory_options
402
+ @@base_url = options[:base_url]
403
+ @@rules_path = options[:rules_path]
404
+ @@logger = options[:logger]
405
+ else
406
+ raise "Please provide #{obligatory_options.join(', ')} in the passed options"
407
+ end
408
+ if options.has_key? :browser
409
+ browser = options[:browser].to_sym
410
+ else
411
+ browser = :firefox
412
+ end
413
+ # OK, now all info from the options is processed, let's rock-n-roll!
414
+ unless ENV.has_key? "DEBUG_WEB"
415
+ @@headless = Headless.new
416
+ @@headless.start
417
+ end
418
+ file_names = web_to_load(options)
419
+ @@rules = {}
420
+ file_names.each do |filename|
421
+ tmphash = YAML.load_file(filename)
422
+ tmphash.each_pair do |key, value|
423
+ if @@rules[key]
424
+ raise "Duplicate entries detected in yaml file #{filename}: #{key}"
425
+ else
426
+ @@rules[key] = value
427
+ end
428
+ end
429
+ end
430
+ firefox_profile = Selenium::WebDriver::Firefox::Profile.new
431
+ chrome_profile = Selenium::WebDriver::Remote::Capabilities.chrome()
432
+ if ENV.has_key? "http_proxy"
433
+ proxy = ENV["http_proxy"].scan(/[\w\.\d\_\-]+\:\d+/)[0] # to get rid of the heading "http://" that breaks the profile
434
+ firefox_profile.proxy = chrome_profile.proxy = Selenium::WebDriver::Proxy.new({:http => proxy, :ssl => proxy})
435
+ firefox_profile['network.proxy.no_proxies_on'] = "localhost, 127.0.0.1"
436
+ ENV['no_proxy'] = '127.0.0.1'
437
+ end
438
+ client = Selenium::WebDriver::Remote::Http::Default.new
439
+ client.timeout = 180
440
+ if browser == :firefox
441
+ @@b = Watir::Browser.new browser, :profile => firefox_profile, :http_client=>client
442
+ elsif browser == :chrome
443
+ @@b = Watir::Browser.new browser, desired_capabilities: chrome_profile
444
+ else
445
+ raise "Not implemented yet"
446
+ end
447
+ # @@b.window.resize_to(1920, 1080)
448
+ @@b.goto @@base_url
449
+ end
450
+
451
+ def goto(params) # params should be a hash
452
+ if params[:relative]
453
+ # if provided relative url and current url contain port nuumbers - take
454
+ # the explicitly provided one
455
+ if params[:url].match /^:\d+/
456
+ base_url.gsub!(/\/$/, "")
457
+ end
458
+ @@b.goto base_url + params[:url]
459
+ else
460
+ @@b.goto params[:url]
461
+ end
462
+ hash = {:result => true, :response => @@b.html}
463
+ end
464
+
465
+ def get_url
466
+ return @@b.url
467
+ end
468
+
469
+ def cookie_option(cookies,opt = nil)
470
+ @result = {:result => true, :failed_positive_checkpoints => nil,:message => nil}
471
+ @cookies= @@b.cookies
472
+ if opt == 'show'
473
+ return @cookies.to_a
474
+ end
475
+ if opt == 'select'
476
+ new_cookies = []
477
+ cookies.each do |cookie|
478
+ if @cookies[cookie[:name].to_sym]
479
+ cookie[:value] = @cookies[cookie[:name].to_sym][:value]
480
+ new_cookies << cookie
481
+ else
482
+ @result[:result]=false
483
+ @result[:falied_negative_checkpoints] =[cookie]
484
+ return @result
485
+ end
486
+ end
487
+ return new_cookies
488
+ end
489
+ if opt == 'delete_all'
490
+ unless @cookies.clear
491
+ @result[:result]=false
492
+ @result[:falied_negative_checkpoints] =[cookie]
493
+ end
494
+ end
495
+ cookies.each do |cookie|
496
+ if opt == 'add'
497
+ if @cookies.add cookie[:name],cookie[:value]
498
+ @result[:result]=true
499
+ else
500
+ @result[:result]=false
501
+ @result[:falied_negative_checkpoints] = [cookie]
502
+ end
503
+ end
504
+ if opt == 'delete'
505
+ unless @cookies.delete cookie[:name]
506
+ @result[:result]=false
507
+ @result[:falied_negative_checkpoints] = [cookie]
508
+ end
509
+ end
510
+ end
511
+ return @result
512
+ end
513
+
514
+ def check_elements(elements, negate=nil, click=nil)
515
+ # elements should be an array of hashes, for example:
516
+ # [{:a=>{:class=>"block"}}, {:a=>{:href=>"/products"}}, {:a=>{:text=>"Log In"}}]
517
+ @counter = 0
518
+ @result = {:result=>true, :failed_positive_checkpoints => [], :failed_negative_checkpoints => [], :error_messages => []}
519
+ elements.each do |element|
520
+ myhash = {
521
+ :a=>@@b.a(element.values[0]),
522
+ :textfield=>@@b.text_field(element.values[0]),
523
+ :filefield=>@@b.file_field(element.values[0]),
524
+ :input=>@@b.input(element.values[0]),
525
+ :element=>@@b.element(element.values[0]),
526
+ :pre=>@@b.element(element.values[0]),
527
+ :select=>@@b.select(element.values[0]),
528
+ :option=>@@b.element(element.values[0])
529
+ }
530
+ if negate
531
+ if myhash[element.keys[0]].exists? and myhash[element.keys[0]].visible?
532
+ @result[:result] = false
533
+ @result[:failed_negative_checkpoints] << [element]
534
+ # must be an array for consistency
535
+ end
536
+ else
537
+ unless myhash[element.keys[0]].exists?
538
+ @result[:result] = false
539
+ @result[:failed_positive_checkpoints] << element
540
+ end
541
+ if click
542
+ begin
543
+ myhash[element.keys[0]].click
544
+ rescue => e
545
+ @result[:result] = false
546
+ @result[:failed_positive_checkpoints] << element
547
+ @result[:error_messages] << e.message
548
+ end
549
+ end
550
+ end
551
+ end
552
+ return @result
553
+ end
554
+
555
+ def element_click(element)
556
+ check_elements([element], negate = nil, click=true)
557
+ end
558
+
559
+ def value_select(element_selector, value)
560
+ result = {
561
+ :result => true,
562
+ :failed_positive_checkpoints => [],
563
+ :failed_negative_checkpoints => [],
564
+ :error_messages => []
565
+ }
566
+ until @@b.select_list(element_selector).exists? do
567
+ begin
568
+ wait_for_element(element_selector)
569
+ rescue => e
570
+ result[:result] = false
571
+ result[:error_messages] << e.message
572
+ break
573
+ end
574
+ end
575
+ @@b.select_list(element_selector).select_value(value)
576
+ return result
577
+ end
578
+
579
+ def finalize
580
+ @@b.close
581
+ @@headless.destroy if defined?(@@headless)
582
+ end
583
+
584
+ def is_element_present?(how, what)
585
+ return @@b.element(how=>what).exists?
586
+ end
587
+
588
+ def browser_title_contains?(string)
589
+ if @@b.title.match(string)
590
+ return true
591
+ else
592
+ return false
593
+ end
594
+ end
595
+
596
+ def dropdown_value(selector)
597
+ return @@b.select(selector).value
598
+ end
599
+
600
+ def element_text(selector)
601
+ return @@b.element(selector).text
602
+ end
603
+
604
+ def refresh_page
605
+ @@b.refresh
606
+ end
607
+
608
+ def send_keys(element, text)
609
+ result = {:result=>true}
610
+ begin
611
+ @@b.text_field(element).clear
612
+ @@b.text_field(element).send_keys text
613
+ rescue => e
614
+ result[:result] = false
615
+ result[:response] = e.message
616
+ end
617
+ end
618
+
619
+ def check_textfield_content(selector, text=nil)
620
+ result = {}
621
+ if @@b.text_field(selector).exists?
622
+ result[:text] = @@b.text_field(selector).value
623
+ result[:result] = true
624
+ else
625
+ result[:result] = false
626
+ end
627
+ return result
628
+ end
629
+
630
+ def page_html
631
+ return @@b.html
632
+ end
633
+
634
+ def rules
635
+ return @@rules
636
+ end
637
+
638
+ def action_rules(action)
639
+ return @@rules[action.to_sym]
640
+ end
641
+ end