domkey 0.1.0

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