marekj-watirloo 0.0.3 → 0.0.5

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 (67) hide show
  1. data/History.txt +12 -0
  2. data/Manifest.txt +59 -34
  3. data/README.rdoc +63 -80
  4. data/Rakefile.rb +32 -39
  5. data/config/locker.yml +0 -0
  6. data/lib/watirloo.rb +9 -162
  7. data/lib/watirloo/browsers.rb +73 -0
  8. data/lib/watirloo/desktop.rb +44 -0
  9. data/lib/watirloo/{firewatir_ducktape.rb → extension/firewatir_ducktape.rb} +0 -0
  10. data/lib/watirloo/extension/object.rb +26 -0
  11. data/lib/watirloo/{watir_ducktape.rb → extension/watir_ducktape.rb} +181 -16
  12. data/lib/watirloo/extension/watir_reflector.rb +83 -0
  13. data/lib/watirloo/locker.rb +84 -0
  14. data/lib/watirloo/page.rb +105 -0
  15. data/spec/browser_spec.rb +38 -0
  16. data/spec/browser_threads_spec.rb +45 -0
  17. data/spec/checkbox_group_spec.rb +136 -0
  18. data/spec/checkbox_groups_spec.rb +55 -0
  19. data/spec/checkboxes_value_spec.rb +35 -0
  20. data/spec/desktop_spec.rb +54 -0
  21. data/spec/extra/browser_events_spec.rb +76 -0
  22. data/spec/extra/page_objects_metrics.rb +139 -0
  23. data/spec/face_mixing_spec.rb +55 -0
  24. data/{test → spec}/firewatir/attach_instance_test.rb +0 -0
  25. data/spec/firewatir/spec_results.html +263 -0
  26. data/spec/firewatir/spec_results.txt +23 -0
  27. data/spec/firewatir/spec_results_failed.txt +3 -0
  28. data/{test → spec}/html/census.html +0 -0
  29. data/spec/html/checkbox_group1.html +33 -0
  30. data/spec/html/labels.html +53 -0
  31. data/spec/html/no_title.html +13 -0
  32. data/{test → spec}/html/person.html +0 -0
  33. data/spec/html/radio_group.html +35 -0
  34. data/{test → spec}/html/select_lists.html +0 -0
  35. data/spec/input_element_spec.rb +51 -0
  36. data/spec/label_spec.rb +65 -0
  37. data/spec/locker_spec.rb +49 -0
  38. data/spec/page_spec.rb +53 -0
  39. data/spec/person_def_wrappers_spec.rb +40 -0
  40. data/spec/radio_group_spec.rb +95 -0
  41. data/spec/radio_groups_spec.rb +55 -0
  42. data/spec/reflector_spec.rb +82 -0
  43. data/spec/select_list_options_spec.rb +40 -0
  44. data/spec/select_lists_spec.rb +151 -0
  45. data/{test/test_helper.rb → spec/spec_helper.rb} +6 -4
  46. data/spec/spec_helper_ff.rb +5 -0
  47. data/spec/spec_helper_runner.rb +13 -0
  48. data/spec/spec_results.html +566 -0
  49. data/spec/spec_results.txt +179 -0
  50. data/spec/spec_results_failed.txt +1 -0
  51. data/spec/text_fields_spec.rb +56 -0
  52. data/watirloo.gemspec +44 -44
  53. metadata +80 -39
  54. data/lib/watirloo/reflector.rb +0 -137
  55. data/test/checkbox_group_test.rb +0 -83
  56. data/test/checkboxes_value_test.rb +0 -50
  57. data/test/html/checkbox_group1.html +0 -20
  58. data/test/html/labels.html +0 -32
  59. data/test/html/radio_group.html +0 -41
  60. data/test/interfaces_test.rb +0 -79
  61. data/test/label_test.rb +0 -64
  62. data/test/person_def_wrappers_test.rb +0 -55
  63. data/test/radio_group_test.rb +0 -97
  64. data/test/select_list_in_class_test.rb +0 -39
  65. data/test/select_list_options_test.rb +0 -39
  66. data/test/select_lists_test.rb +0 -145
  67. data/test/text_fields_test.rb +0 -68
@@ -0,0 +1,84 @@
1
+ module Watirloo
2
+
3
+
4
+ # manages references to browsers we care about to run tests agains.
5
+ # Saves references to window handles internall to yaml file so we can reuse the browser for tests by reattaching to it between tests.
6
+ # you put reference to a browser in storage. Next time you run a test you can restore the browser's reference instead fo staring a new one.
7
+ module Locker
8
+
9
+ @@locker_file = File.join(File.dirname(__FILE__), "..", "..", "config", "locker.yml")
10
+
11
+ class << self
12
+
13
+ # hash of {key => IE.hwnd} to attach and reuse browsers
14
+ # example: mapping = {:default=> 234567, :bla => 234234}
15
+ def mapping
16
+ @mapping ||= read_mapping
17
+ end
18
+
19
+ def locker
20
+ @@locker_file
21
+ end
22
+
23
+ def locker=( locker )
24
+ @@locker_file = locker
25
+ end
26
+
27
+ # returns IE reference to a browser with a given key
28
+ def browser(key='default')
29
+ if key == 'default'
30
+ (@browser && @browser.exists?) ? @browser : @browser = attach_browser
31
+ else
32
+ attach_browser(key)
33
+ end
34
+ end
35
+
36
+ # add browser to storage for later reuse. by convention if you don't have any browsers it
37
+ # so you can later restore it and continue working with it.
38
+ # pass either browser referene or the hwnd Fixnum
39
+ def add(browser, key='default')
40
+ mapping[key] = browser.kind_of?(Watir::IE) ? browser.hwnd : browser
41
+ save_mapping
42
+ end
43
+
44
+ # remove browser from storage and from further reusing
45
+ def remove(key='default')
46
+ @browser = nil if key == 'default'
47
+ mapping.delete(key) if mapping[key]
48
+ save_mapping
49
+ end
50
+
51
+ # clear Storage
52
+ def clear
53
+ @browser = nil
54
+ mapping.clear
55
+ save_mapping
56
+ end
57
+
58
+ private
59
+
60
+ def read_mapping
61
+ if FileTest.exists?(locker)
62
+ loaded = YAML::load_file(locker)
63
+ #if file is empty or not well formed yaml
64
+ #or not a hash then return empty hash
65
+ loaded.kind_of?(Hash) ? loaded : {}
66
+ else
67
+ #empty hash if locker.yaml not there
68
+ #or malformed loaded not created yet
69
+ {}
70
+ end
71
+ end
72
+
73
+ def save_mapping
74
+ File.open(locker,'w') {|f| YAML.dump(mapping, f)}
75
+ end
76
+
77
+ # throws exception if can't attach to the known handle.
78
+ def attach_browser(key='default')
79
+ Watir::IE.attach(:hwnd, mapping[key])
80
+ end
81
+
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,105 @@
1
+ module Watirloo
2
+
3
+ # Semantic Page Objects Container
4
+ # include it in your ClientClass that manages Test. Your client class must provide an instance of browser.
5
+ # If you don't want an explicit browser the Watirloo.browser will be used.
6
+ # example
7
+ # class UsageScenarioOfSomeFeature
8
+ # include Watirloo::Page
9
+ # end
10
+ # now the client GoogleSearch can access browser and elements defined
11
+ # instead of including it directly in classes that you instantiate to keep track of state you can build modules of pages
12
+ # that you can later include into your client
13
+ module Page
14
+
15
+ # provides access to the browser for a client
16
+ def browser
17
+ ::Watirloo.browser
18
+ end
19
+
20
+ # container that delimits the scope of elements.
21
+ # in a frameless DOM the browser is the doc
22
+ # however if page with frames you can setup a doc destination to be a frame as the
23
+ # base container for face accessors
24
+ def doc
25
+ browser
26
+ end
27
+
28
+ module ClassMethods
29
+
30
+ # "anything which is the forward or world facing part of a system
31
+ # which has internal structure is considered its 'face', like the facade of a building"
32
+ # ~ http://en.wikipedia.org/wiki/Face
33
+ #
34
+ # Declares Semantic Interface to the DOM elements on the Page (facade) binds a symbol to a block of code that accesses the DOM.
35
+ # When the user speaks of filling in the last name the are usually entering data in a text_field
36
+ # we can create a semantic accessor interface like this:
37
+ # face(:last_name) {doc.text_field(:name, 'last_nm'}
38
+ # what matters to the user is on the left (:last_name) and what matters to the programmer is on the right
39
+ # The face method provides an adapter and insolates the tests form the changes in GUI.
40
+ # face(:friendlyname) { watircode } where watircode is actuall way of accessing the element on the page.
41
+ # Each interface or face is an object of interest that we want to access by its interface name
42
+ # example:
43
+ #
44
+ # class GoogleSearch
45
+ # include Watirloo::Page
46
+ # face(:query) { doc.text_field(:name, 'q') }
47
+ # face(:search) { doc.button(:name, 'btnG') }
48
+ # end
49
+ #
50
+ def face(name, *args, &definition)
51
+ module_eval do
52
+ define_method(name) do |*args|
53
+ instance_exec(*args, &definition)
54
+ end
55
+ end
56
+ end
57
+ end
58
+
59
+ # metahook by which ClassMethods become singleton methods of an including module
60
+ # Perhaps the proper way is to do this
61
+ # class SomeClass
62
+ # include PageHelper
63
+ # extend PageHelper::ClassMethods
64
+ # end
65
+ # but we are just learning this metaprogramming
66
+ def self.included(klass)
67
+ klass.extend(ClassMethods)
68
+ end
69
+
70
+ # enter values on controls idenfied by keys on the page.
71
+ # data map is a hash, key represents the page objects that can be filled or set with values,
72
+ # value represents its value to be set, either text, array or boolean
73
+ # exmaple:
74
+ # spray :first => "Johnny", :last => 'Begood'
75
+ #
76
+ # # Given the faces defined
77
+ # face(:first) {doc.text_field(:name, 'lst_nm')}
78
+ # face(:last) {doc.text_field(:name, 'fst_nm')}
79
+ def spray(hash)
80
+ hash.each_pair do |facename, value|
81
+ send(facename).set value #make every control element in watir respond to set
82
+ end
83
+ end
84
+
85
+ # set values on the page given the interface keys
86
+ alias set spray
87
+
88
+
89
+ def scrape(field_keys)
90
+ data = {}
91
+ field_keys.each do |k|
92
+ watir_control = send("#{k}")
93
+ method_name = case watir_control.class.to_s.split("::").last
94
+ when "SelectList", "CheckboxGroup", "RadioGroup" then :selected
95
+ else
96
+ :value
97
+ end
98
+ data.update k => watir_control.send(method_name)
99
+ end
100
+ data
101
+ end
102
+
103
+
104
+ end
105
+ end
@@ -0,0 +1,38 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+
3
+ describe "Watirloo browser when no browsers on desktop nor in locker" do
4
+
5
+ before(:all) do
6
+ Watirloo::Desktop.clear
7
+ Watirloo::Locker.clear
8
+ end
9
+
10
+ it "should start a default new browser and load a testfile" do
11
+ browser = Watirloo.browser
12
+ browser.should be_kind_of(Watir::IE)
13
+ browser.goto testfile('person.html')
14
+ end
15
+
16
+ it 'should attach to a default browser with loaded testfile and return its title' do
17
+ browser = Watirloo.browser
18
+ browser.should be_kind_of(Watir::IE)
19
+ browser.title.should == 'Person'
20
+ end
21
+
22
+ it "should start second browser with a named keyword" do
23
+ Watirloo.browser 'second'
24
+ end
25
+
26
+ it 'should attach to second browser with keyword and navigate to a testfile' do
27
+ browser2 = Watirloo.browser 'second'
28
+ browser2.goto testfile('census.html')
29
+ end
30
+
31
+ it 'should attach to two distinct browsers by key values by kewords used to start them' do
32
+ b2 = Watirloo.browser 'second'
33
+ b1 = Watirloo.browser 'default'
34
+ b2.title.should == 'Census'
35
+ b1.title.should == 'Person'
36
+ end
37
+
38
+ end
@@ -0,0 +1,45 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+ require 'thread'
3
+
4
+ # This is more of an example of using Watirloo::browser() and Watirloo::Locker with threads
5
+ # for multibrowser testing possiblilities
6
+ describe "Watirloo multiple browsers and threads" do
7
+
8
+ before(:all) do
9
+ Watirloo::Desktop.clear
10
+ Watirloo::Locker.clear
11
+ end
12
+
13
+
14
+ it "open 5 new browsers in threads and add them to locker" do
15
+ threads = []
16
+ 1.upto(5) do |i|
17
+ threads << Thread.new { Watirloo.browser(i) }
18
+ end
19
+ threads.each {|x| x.join}
20
+ end
21
+
22
+ it 'use locker to reattach to 5 browsers and load 5 diff pages at once' do
23
+ threads = []
24
+ files = ['census.html', 'labels.html', 'person.html', 'select_lists.html', 'radio_group.html']
25
+ titles = ['Census', 'Labels', 'Person', 'select lists', "radio_groups"]
26
+ 1.upto(5) do |i|
27
+ threads << Thread.new do
28
+ Watirloo.browser(i).goto testfile(files[i-1])
29
+ sleep 5 #add safety
30
+ Watirloo.browser(i).title.should == titles[i-1]
31
+ end
32
+ end
33
+ threads.each {|x| x.join}
34
+ end
35
+
36
+ it "reattach and close all 5 browsers" do
37
+ hwnds = Watirloo::Desktop.hwnds
38
+ threads =[]
39
+ 1.upto(5) { |i| threads << Thread.new { Watirloo.browser(i).close } }
40
+ threads.each {|x| x.join}
41
+ sleep 5 #Ensure browsers close
42
+ Watirloo::Desktop.deletions(hwnds).size.should == 5
43
+ end
44
+ end
45
+
@@ -0,0 +1,136 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+
3
+ describe 'browser checkbox_group accesses a group of checkboxes sharing the same name on a page' do
4
+
5
+ before :each do
6
+ @browser = Watirloo::browser
7
+ @browser.goto testfile('checkbox_group1.html')
8
+ end
9
+
10
+ it 'browser responds to checkbox_group' do
11
+ @browser.should respond_to(:checkbox_group)
12
+ end
13
+
14
+ it 'access by name as default returns CheckboxGroup' do
15
+ if @browser.kind_of?(FireWatir::Firefox)
16
+ @browser.checkbox_group('pets').should be_kind_of(FireWatir::CheckboxGroup)
17
+ elsif @browser.kind_of?(Watir::IE)
18
+ @browser.checkbox_group('pets').should be_kind_of(Watir::CheckboxGroup)
19
+ end
20
+ end
21
+
22
+ it 'size retuns checkboxes as items count in a group' do
23
+ @browser.checkbox_group(:name, 'pets').size.should == 5
24
+ end
25
+
26
+ it 'values returns array of value attributes for each checkbox in a group' do
27
+ @browser.checkbox_group('pets').values.should == ["cat", "dog", "zook", "zebra", "wumpa"]
28
+ end
29
+
30
+ end
31
+
32
+ describe "checkbox_group values when no checkbox is checked in a group" do
33
+
34
+ before :each do
35
+ @browser = Watirloo::browser
36
+ @browser.goto testfile('checkbox_group1.html')
37
+ end
38
+
39
+
40
+ it 'selected should return nil' do
41
+ @browser.checkbox_group('pets').selected.should be_nil
42
+ end
43
+ it 'selected_value should return nil' do
44
+ @browser.checkbox_group('pets').selected_value.should be_nil
45
+ end
46
+ it 'selected_values should return empty array' do
47
+ @browser.checkbox_group('pets').selected_values.should be_empty
48
+ end
49
+
50
+ it "set? should return false when no checkbox is checked in a group" do
51
+ @browser.checkbox_group("pets").should_not be_set
52
+ end
53
+
54
+ end
55
+
56
+ describe "checkbox_group values when set string selecs one item only" do
57
+
58
+ before :each do
59
+ @browser = Watirloo::browser
60
+ @browser.goto testfile('checkbox_group1.html')
61
+ end
62
+
63
+
64
+ it "selected should return the string used to select it" do
65
+ @browser.checkbox_group('pets').set 'dog'
66
+ @browser.checkbox_group('pets').selected.should == 'dog'
67
+ end
68
+
69
+ it "selected_value should return the string when one item is selected" do
70
+ @browser.checkbox_group('pets').set 'dog'
71
+ @browser.checkbox_group('pets').selected_value.should == 'dog'
72
+ end
73
+
74
+ it 'selected values returns array with one element' do
75
+ @browser.checkbox_group('pets').set 'dog'
76
+ @browser.checkbox_group('pets').selected_values.should == ['dog']
77
+ end
78
+
79
+ it "set? should return truee when 1 checkbox is checked in a group" do
80
+ @browser.checkbox_group('pets').set 'dog'
81
+ @browser.checkbox_group("pets").should be_set
82
+ end
83
+
84
+ end
85
+
86
+
87
+ describe "checkbox_group set array of strings selects multiple values in a group" do
88
+
89
+ before :each do
90
+ @browser = Watirloo::browser
91
+ @browser.goto testfile('checkbox_group1.html')
92
+ end
93
+
94
+
95
+ it "selected returns array of strings when multiple values are selected" do
96
+ @browser.checkbox_group('pets').set ['dog', 'zebra', 'cat'] # not in order
97
+ @browser.checkbox_group('pets').selected.should == ['cat', 'dog', 'zebra']
98
+ end
99
+
100
+ it 'selected_value returns the same array of strings by position in a group' do
101
+ @browser.checkbox_group('pets').set ['zebra', 'dog', 'cat'] # not in order
102
+ @browser.checkbox_group('pets').selected_value.should == ['cat', 'dog', 'zebra'] # bypass filter
103
+ end
104
+
105
+ it "selected_values returns the same array of strings by position in a group" do
106
+ @browser.checkbox_group('pets').set ['cat', 'zebra', 'dog'] # not in order
107
+ @browser.checkbox_group('pets').selected_values.should == ['cat', 'dog', 'zebra']
108
+ end
109
+
110
+ it "set? should return truee when more than 1 checkbox is checked in a group" do
111
+ @browser.checkbox_group('pets').set ['cat', 'zebra', 'dog'] # not in order
112
+ @browser.checkbox_group("pets").should be_set
113
+ end
114
+
115
+ end
116
+
117
+ describe "checkbox_group set by numberical position" do
118
+
119
+ before :each do
120
+ @browser = Watirloo::browser
121
+ @browser.goto testfile('checkbox_group1.html')
122
+ end
123
+
124
+
125
+ it 'set Fixnum checks checkbox by position in a group. Position is 1 based.' do
126
+ #Behaves like select by single value
127
+ @browser.checkbox_group('pets').set 3
128
+ @browser.checkbox_group('pets').selected_value.should == 'zook'
129
+ end
130
+
131
+ it 'set array of Fixnums checks each checkbox by position' do
132
+ #behaves like select multiple strings
133
+ @browser.checkbox_group('pets').set [4,1,2] # not in order
134
+ @browser.checkbox_group('pets').selected.should == ["cat", "dog", "zebra"]
135
+ end
136
+ end
@@ -0,0 +1,55 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+
3
+ describe 'checkbox_groups access for browser' do
4
+
5
+ before :each do
6
+ @browser = Watirloo::browser
7
+ @browser.goto testfile('checkbox_group1.html')
8
+ end
9
+
10
+ it 'browser responds to checkbox_group' do
11
+ @browser.should respond_to(:checkbox_groups)
12
+ end
13
+
14
+ it 'returns group object and its values from the page' do
15
+ @browser.checkbox_groups.should be_kind_of(Watir::CheckboxGroups)
16
+ end
17
+
18
+ it 'lenght returns integer count of groups' do
19
+ @browser.checkbox_groups.length.should == 4
20
+ end
21
+
22
+ it 'each iterator returns CheckboxGroup' do
23
+ @browser.checkbox_groups.each do |cbg|
24
+ cbg.should be_kind_of( Watir::CheckboxGroup )
25
+ end
26
+ end
27
+
28
+ it 'each accesses the group and returns name' do
29
+ names =[]
30
+ @browser.checkbox_groups.each do |cg|
31
+ names << cg.name
32
+ end
33
+ names.should == ['pets', 'singleIndicator', 'petsa', 'singleIndicatora']
34
+ end
35
+
36
+ it 'bracket access[] returns 1-based indexed group' do
37
+ @browser.checkbox_groups[1].values.should == %w[cat dog zook zebra wumpa]
38
+ @browser.checkbox_groups[3].name.should == 'petsa'
39
+ end
40
+
41
+ it 'if checkbox group does not exists it returns size 0 or name nil (or should it blow up? or respond to exists? method' do
42
+ @browser.checkbox_groups[6].size.should == 0 # does not exist. let's not blow up. suggestions?
43
+ @browser.checkbox_groups[6].name.should == nil #suggestions?
44
+ end
45
+
46
+ it 'return checkbox groups contained by the form element' do
47
+ @browser.forms[2].checkbox_groups.length.should == 2
48
+ names =[]
49
+ @browser.forms[2].checkbox_groups.each do |cbg|
50
+ names << cbg.name
51
+ end
52
+ names.should == ['petsa', 'singleIndicatora']
53
+ end
54
+
55
+ end