domkey 0.1.0

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,53 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>TestView</title>
5
+ </head>
6
+ <body>
7
+ <div class='pageobject'>
8
+ <p>pageobject with many elements</p>
9
+ <input type='text' id="street1" class="street1"/>
10
+ <input type='text' id="city1" class="city" value="id city class city"/>
11
+ </div>
12
+
13
+ <div class='pageobject' id="container">
14
+ <input type='text' id="street2" class="street1"/>
15
+ <input type='text' id="city2" class="city" value="class city but div id container"/>
16
+ </div>
17
+ <br/>
18
+
19
+ <div id='feature_1' class='pageobject'>
20
+ <label for='feature_checkbox1'>Nude Beach</label>
21
+ <input id="feature_checkbox1" type="checkbox" class="check" onclick="featureEnabler('feature_checkbox1','feature_textarea1');"/><br/>
22
+ <textarea id='feature_textarea1' readonly disabled>CheckboxTextField 1</textarea>
23
+ </div>
24
+
25
+ <div id='feature_2' class='pageobject'>
26
+ <label for='feature_checkbox2'>Golf Course</label>
27
+ <input id='feature_checkbox2' type='checkbox' class="check" onclick="featureEnabler('feature_checkbox2','feature_textarea2');"/><br/>
28
+ <textarea id='feature_textarea2' readonly disabled>CheckboxTextField 2</textarea>
29
+ </div>
30
+
31
+ <script type="text/javascript">
32
+ function featureEnabler(cbe, txte) {
33
+ var cb = document.getElementById(cbe);
34
+ var txt = document.getElementById(txte);
35
+ if (cb.checked == true) {
36
+ txt.readOnly = "";
37
+ txt.disabled = "";
38
+ } else {
39
+ txt.readOnly = 'readonly';
40
+ txt.disabled = 'disabled';
41
+ }
42
+ }
43
+ </script>
44
+
45
+ <div>
46
+ <p>DateSelector</p>
47
+ <input type='text' id="month_field" class="street1"/>
48
+ <input type='text' id="day_field" class="city"/>
49
+ <input type='text' id="year_field" class="city"/>
50
+ </div>
51
+
52
+ </body>
53
+ </html>
@@ -0,0 +1,130 @@
1
+ require 'spec_helper'
2
+
3
+ describe Domkey::View::PageObjectCollection do
4
+
5
+ before :all do
6
+ Domkey.browser.goto("file://" + __dir__ + "/html/test.html")
7
+ end
8
+
9
+ it 'init error' do
10
+ # TODO. tighter scope what can be a watirproc
11
+ expect { Domkey::View::PageObjectCollection.new 'foo' }.to raise_error(Domkey::Exception::Error)
12
+ end
13
+
14
+ context 'when container is browser by default' do
15
+
16
+ context 'watirproc is watirproc defining collection' do
17
+
18
+ before :each do
19
+ # watirproc is definition of watir collection
20
+ # watirproc when instantiated must respond to :each
21
+ # test sample:
22
+ # we have 3 text_fields with class that begins with street
23
+ watirproc = lambda { text_fields(class: /^street/) }
24
+
25
+ @cbs = Domkey::View::PageObjectCollection.new watirproc
26
+ end
27
+
28
+ it 'count or size' do
29
+ @cbs.count.should == 3
30
+ end
31
+
32
+ it 'each returns PageObject' do
33
+ @cbs.each do |e|
34
+ e.should be_kind_of(Domkey::View::PageObject)
35
+ end
36
+ end
37
+
38
+ it 'by index returns PageObject' do
39
+ @cbs[0].should be_kind_of(Domkey::View::PageObject)
40
+ @cbs[1].should be_kind_of(Domkey::View::PageObject)
41
+ end
42
+
43
+ it 'find_all example' do
44
+ # find_all of some condition
45
+ @cbs.find_all { |e| e.value == 'hello pageobject' }.should be_empty
46
+ @cbs.first.set 'hello pageobject'
47
+
48
+ # find_all returns the one we just set
49
+ @cbs.find_all { |e| e.value == 'hello pageobject' }.count.should eql(1)
50
+ end
51
+
52
+ it 'set one and map all example' do
53
+ # set value to later return
54
+ @cbs[1].set 'bye bye'
55
+
56
+ # map iterates and harvests value
57
+ @cbs.map { |e| e.value }.should eql ["hello pageobject", "bye bye", ""]
58
+ end
59
+
60
+ it 'element reaches to widgetry' do
61
+ @cbs.element.should be_kind_of(Watir::TextFieldCollection)
62
+ end
63
+
64
+ end
65
+
66
+ context 'watirproc is hash' do
67
+
68
+ before :all do
69
+ # would we do that? give me all text_fields :street and all text_fields :city ? in one collection?
70
+ # it becomes a keyed collection?
71
+ # secondary usage
72
+ # given I have city 4 and street 3 textfields
73
+ Domkey.browser.text_fields(class: /^street/).count.should == 3
74
+ Domkey.browser.text_fields(class: /^city/).count.should == 4
75
+
76
+ # when I define my keyed collection
77
+ watirproc = {street: lambda { text_fields(class: /^street/) },
78
+ city: lambda { text_fields(class: /^city/) }}
79
+
80
+ @cbs = Domkey::View::PageObjectCollection.new watirproc
81
+ end
82
+
83
+ it 'count' do
84
+ @cbs.count.should == 2
85
+ end
86
+
87
+ it 'to_a returns array of hashes' do
88
+ @cbs.to_a.should have(2).items
89
+ end
90
+
91
+ it 'each returns hash where value is a PageObjectCollection' do
92
+ @cbs.each do |hash|
93
+ hash.each_pair { |k, v| v.should be_kind_of(Domkey::View::PageObjectCollection) }
94
+ end
95
+ end
96
+
97
+ it 'by index returns hash' do
98
+ @cbs.to_a[0].should be_kind_of(Hash)
99
+ end
100
+
101
+ it 'each in key returns PageObject' do
102
+ collection = @cbs.to_a.find { |e| e[:street] }
103
+ collection[:street].should be_kind_of(Domkey::View::PageObjectCollection)
104
+ collection[:street].each { |e| e.should be_kind_of(Domkey::View::PageObject) }
105
+ end
106
+
107
+ it 'element' do
108
+ @cbs.element(:street).should be_kind_of(Watir::TextFieldCollection)
109
+ @cbs.element.should be_kind_of(Hash)
110
+ @cbs.element.each_pair do |k, v|
111
+ k.should be_a(Symbol)
112
+ v.should be_a(Watir::TextFieldCollection)
113
+ end
114
+ end
115
+
116
+ end
117
+
118
+ context 'watirproc is pageobjectcollection' do
119
+
120
+ it 'initialize' do
121
+ watirproc = lambda { text_fields(class: /^street/) }
122
+ pageobjectcollection = Domkey::View::PageObjectCollection.new watirproc
123
+
124
+ @cbs = Domkey::View::PageObjectCollection.new pageobjectcollection
125
+ end
126
+
127
+ end
128
+ end
129
+
130
+ end
@@ -0,0 +1,211 @@
1
+ require 'spec_helper'
2
+
3
+ # domain specific page objects composed from regular page object
4
+ # PageObject is a type of object that responds to set and value.
5
+ # it is the Role it plays
6
+ # DateSelector is a type of decoration for domain specific pageobject
7
+ module Domkey
8
+
9
+ module View
10
+
11
+ #example of specialized domain specific pageobject.
12
+ # behavior of set and value
13
+ class DateSelectorPageObject < PageObject
14
+
15
+ def set value
16
+ watirproc.each_pair { |k, po| po.set(value.send(k)) }
17
+ end
18
+
19
+ def value
20
+ h = {}
21
+ watirproc.each_pair { |k, po| h[k] = po.value }
22
+ Date.parse "%s/%s/%s" % [h[:year], h[:month], h[:day]]
23
+ end
24
+ end
25
+ end
26
+ end
27
+
28
+
29
+ module DomkeySpecHelper
30
+
31
+ class CheckboxTextField
32
+
33
+ attr_reader :pageobject
34
+
35
+ def initialize(pageobject)
36
+ @pageobject = pageobject
37
+ end
38
+
39
+ def label
40
+ pageobject.element(:label).text
41
+ end
42
+
43
+ def set value
44
+ return pageobject.set switch: false unless value
45
+ if value.kind_of? String
46
+ pageobject.set switch: true, blurb: value
47
+ else
48
+ pageobject.set switch: true
49
+ end
50
+ end
51
+
52
+ def value
53
+ if pageobject.element(:switch).set?
54
+ v = pageobject.element(:blurb).value
55
+ v == '' ? true : v
56
+ else
57
+ false
58
+ end
59
+ end
60
+ end
61
+
62
+
63
+ class DateSelector
64
+
65
+ attr_reader :pageobject
66
+
67
+ def initialize(pageobject)
68
+ @pageobject = pageobject
69
+ end
70
+
71
+
72
+ def set value
73
+ pageobject.set day: value.day, month: value.month, year: value.year
74
+ end
75
+
76
+ def value
77
+ h = pageobject.value
78
+ Date.parse "%s/%s/%s" % [h[:year], h[:month], h[:day]]
79
+ end
80
+
81
+ end
82
+
83
+ end
84
+
85
+ describe 'PageObject Decorators' do
86
+
87
+ before :all do
88
+ Domkey.browser.goto("file://" + __dir__ + "/html/test.html")
89
+ end
90
+
91
+ context 'DateSelector' do
92
+
93
+ it 'as pageobject component wrapped by decorator' do
94
+
95
+ watir_object = {day: lambda { text_field(id: 'day_field') },
96
+ month: lambda { text_field(id: 'month_field') },
97
+ year: lambda { text_field(id: 'year_field') }}
98
+
99
+ foo = Domkey::View::PageObject.new watir_object
100
+ dmy = DomkeySpecHelper::DateSelector.new foo
101
+
102
+ dmy.set Date.today
103
+ dmy.value.should eql Date.today
104
+ end
105
+
106
+ it 'inherits from pageobject and overrides set and value' do
107
+
108
+ watir_object = {day: lambda { text_field(id: 'day_field') },
109
+ month: lambda { text_field(id: 'month_field') },
110
+ year: lambda { text_field(id: 'year_field') }}
111
+
112
+ #foo = Domkey::Page::PageObject.new watir_object, @container
113
+ dmy = Domkey::View::DateSelectorPageObject.new watir_object
114
+
115
+ dmy.set Date.today
116
+ dmy.value.should eql Date.today
117
+ end
118
+
119
+ end
120
+
121
+
122
+ context 'CheckboxTextField' do
123
+
124
+
125
+ it 'as pageobject component wrapped by decorator' do
126
+
127
+ watir_object = {switch: lambda { checkbox(id: 'feature_checkbox1') },
128
+ blurb: lambda { text_field(id: 'feature_textarea1') }}
129
+
130
+ #pageobject as component
131
+ foo = Domkey::View::PageObject.new watir_object
132
+
133
+ foo.set switch: true, blurb: 'I am a blurb'
134
+ foo.set switch: false
135
+ foo.set switch: true
136
+
137
+ # decorator add specific behavior to set and value methods
138
+ tbcf = DomkeySpecHelper::CheckboxTextField.new foo
139
+
140
+ tbcf.set true
141
+ tbcf.set false
142
+ tbcf.set 'hhkhkjhj'
143
+
144
+ end
145
+
146
+ context 'building array of CheckboxTextFields in the view' do
147
+
148
+ it 'algorithm from predictable pattern' do
149
+
150
+ #given predictable pattern that singals the presence of pageobjects
151
+ divs = Domkey::View::PageObjectCollection.new lambda { divs(:id, /^feature_/) }
152
+
153
+ features = divs.map do |div|
154
+
155
+ #the unique identifier shared by all elements composing a PageObject
156
+ id = div.element.id.split("_").last
157
+
158
+ #definiton for each PageObject
159
+ watir_object = {switch: lambda { checkbox(id: "feature_checkbox#{id}") },
160
+ blurb: lambda { text_field(id: "feature_textarea#{id}") },
161
+ label: lambda { label(for: "feature_checkbox#{id}") }}
162
+
163
+ pageobject = Domkey::View::PageObject.new watir_object
164
+ #domain specific pageobject
165
+ DomkeySpecHelper::CheckboxTextField.new(pageobject)
166
+ end
167
+
168
+ # array of Domain Specific PageObjects
169
+ features.first.set 'bla'
170
+ features.map { |e| e.value }.should eql ["bla", false]
171
+ features.map { |e| e.pageobject.element(:label).text }.should eql ["Nude Beach", "Golf Course"]
172
+ features.find { |e| e.label == 'Golf Course' }.value.should be_false
173
+ end
174
+
175
+ # example of building Domain Specific PageObject
176
+ # from a predictable pattern of element collection on the page
177
+ module CheckboxTextFieldViewFactory
178
+
179
+ include Domkey::View
180
+
181
+ doms(:feature_divs) { divs(:id, /^feature_/) }
182
+
183
+ # returns array of CheckboxTextField pageobjects
184
+ def features
185
+ ids = feature_divs.map { |e| e.element.id.split("_").last }
186
+ ids.map do |i|
187
+ pageobject = PageObject.new switch: -> { checkbox(id: "feature_checkbox#{i}") },
188
+ blurb: -> { text_field(id: "feature_textarea#{i}") },
189
+ label: -> { label(for: "feature_checkbox#{i}") }
190
+ DomkeySpecHelper::CheckboxTextField.new(pageobject)
191
+ end
192
+ end
193
+
194
+ end
195
+
196
+ # final client view that gets what the factory for pageobjects
197
+ class DomainSpecificPageObjectView
198
+ include CheckboxTextFieldViewFactory
199
+
200
+ end
201
+
202
+ it 'view factory' do
203
+ view = DomainSpecificPageObjectView.new
204
+ view.features.should have(2).items
205
+ view.features.each { |f| f.set true }
206
+ view.features.each { |f| f.set false }
207
+ view.features.each { |f| f.set "Hello From Feature View" }
208
+ end
209
+ end
210
+ end
211
+ end
@@ -0,0 +1,130 @@
1
+ require 'spec_helper'
2
+
3
+ # methods each pageobject should have
4
+ # set value options elements
5
+
6
+ describe Domkey::View::PageObject do
7
+
8
+ before :all do
9
+ Domkey.browser.goto("file://" + __dir__ + "/html/test.html")
10
+ end
11
+
12
+ context 'exceptions' do
13
+
14
+ it 'bad proc for watirproc argument' do
15
+ expect { Domkey::View::PageObject.new lambda { 'foo' } }.to raise_error(Domkey::Exception::Error)
16
+ end
17
+
18
+ it 'bad object for watirproc argument' do
19
+ expect { Domkey::View::PageObject.new(Object.new) }.to raise_error(Domkey::Exception::Error)
20
+ end
21
+ end
22
+
23
+ context 'when container is browser by default and' do
24
+
25
+ it 'watirproc is watirproc' do
26
+ watirproc = lambda { text_field(id: 'street1') }
27
+ street = Domkey::View::PageObject.new watirproc
28
+
29
+ street.watirproc.should be_kind_of(Proc)
30
+ street.element.should be_kind_of(Watir::TextField) #one default element
31
+
32
+ # talk to browser
33
+ street.set 'Lamar'
34
+ street.value.should eql 'Lamar'
35
+ end
36
+
37
+ it 'watirproc is pageobject' do
38
+ # setup
39
+ watir_object = lambda { text_field(id: 'street1') }
40
+ pageobject = Domkey::View::PageObject.new watir_object
41
+
42
+ # test
43
+ street = Domkey::View::PageObject.new pageobject
44
+
45
+ street.watirproc.should be_kind_of(Proc)
46
+ street.element.should be_kind_of(Watir::TextField)
47
+
48
+
49
+ # talk to browser
50
+ street.set 'zooom' #sending string here so no hash like in composed object
51
+ street.value.should eql 'zooom'
52
+ end
53
+
54
+ it 'watirproc is proc hash where values are watirprocs' do
55
+ hash = {street1: lambda { text_field(id: 'street1') }, city: lambda { text_field(id: 'city1') }}
56
+ watirproc = lambda { hash }
57
+ address = Domkey::View::PageObject.new watirproc
58
+
59
+ address.watirproc.should respond_to(:each_pair)
60
+ address.watirproc.each_pair do |k, v|
61
+ k.should be_kind_of(Symbol)
62
+ v.should be_kind_of(Domkey::View::PageObject) #should respond to set and value
63
+ end
64
+
65
+ address.element.should respond_to(:each_pair)
66
+ address.element.each_pair do |k, v|
67
+ v.should be_kind_of(Watir::TextField) #resolve suitecase
68
+ end
69
+
70
+ end
71
+
72
+ it 'watirproc is hash where values are watirprocs' do
73
+
74
+ hash = {street1: lambda { text_field(id: 'street1') }, city: lambda { text_field(id: 'city1') }}
75
+
76
+ address = Domkey::View::PageObject.new hash
77
+
78
+ address.watirproc.should respond_to(:each_pair)
79
+ address.watirproc.each_pair do |k, v|
80
+ k.should be_kind_of(Symbol)
81
+ v.should be_kind_of(Domkey::View::PageObject) #should respond to set and value
82
+ end
83
+
84
+ address.element.should respond_to(:each_pair)
85
+ address.element.each_pair do |k, v|
86
+ v.should be_kind_of(Watir::TextField) #resolve suitecase
87
+ end
88
+
89
+
90
+ # talk to browser
91
+ address.element[:street1].set 'helloworld'
92
+ address.element[:street1].value.should eql 'helloworld'
93
+
94
+ # pageobject.set value
95
+ # sends values to each element.set value
96
+ value = {city: 'Berlin', street1: 'Fredrichstrasse'}
97
+ address.set value
98
+
99
+ ## pageobject.value => returns value from the page
100
+ # asks each element for its value and aggregates value for entire pageobject
101
+ expected_value = address.value
102
+
103
+ # compare to value we sent earlier
104
+ expected_value.should eql(value)
105
+
106
+ # element by element
107
+ address.element(:city).value.should eql 'Berlin'
108
+ address.element(:city).set 'Austin'
109
+ address.element(:city).value.should eql 'Austin'
110
+
111
+ end
112
+ end
113
+
114
+ context 'when container is pageobject' do
115
+
116
+ it 'pageobject.dom becomes container' do
117
+ browser = lambda { Domkey.browser }
118
+ container = Domkey::View::PageObject.new Proc.new { div(:id, 'container') }, browser
119
+
120
+ e = lambda { text_field(class: 'city') }
121
+ city = Domkey::View::PageObject.new e, container
122
+ city.set 'Hellocontainer'
123
+
124
+ #verify
125
+ Domkey.browser.div(:id, 'container').text_field(:class, 'city').value.should == 'Hellocontainer'
126
+ end
127
+ end
128
+
129
+
130
+ end