pouch 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Pouch
2
2
 
3
- TODO: Write a gem description
3
+ Pouch is a flexible page object DSL for responsive UI testing and written with expressive scripting in mind. It currently works with watir-webdriver.
4
4
 
5
5
  ## Installation
6
6
 
@@ -20,12 +20,71 @@ Or install it yourself as:
20
20
 
21
21
  ## Usage
22
22
 
23
- TODO: Write usage instructions here
23
+ Include Pouch in your page object classes, which will give them access to the element definition DSL.
24
+
25
+ ```ruby
26
+ class Page
27
+ include Pouch
28
+ link(:home, id: 'go-home')
29
+ text_field(:search, id: 'search-term')
30
+ button(:submit, id: 'search-submit')
31
+ end
32
+ ```
33
+
34
+ Scripting is meant to be expressive, so calling the name of your element method returns the HTML object and forces you to write out your actions.
35
+
36
+ ```ruby
37
+ page = Page.new browser_instance
38
+ page.home.click
39
+ page.search.value = 'search term'
40
+ page.submit.click
41
+ ```
42
+
43
+ Element method definitions are flexible. You can engineer more useful definitions with block arguments.
44
+
45
+ ```ruby
46
+ class Page
47
+ include Pouch
48
+ list_item(:phone_number, id: 'phone-num')
49
+ list_item(:area_code, id: 'phone-num'){ |li| span.text[0..2] }
50
+ end
51
+ ```
52
+
53
+ This lets your scripting be more expressive too. For example, compare these two RSpec expectations using the page object definition above:
54
+
55
+ ```ruby
56
+ expect(page.phone_number[0..2]).to eq '555'
57
+ expect(page.area_code).to eq '555'
58
+ ```
59
+
60
+ Pouch page objects can be created with contexts, allowing a single method call to execute two different element definitions based on that context. This is useful for responsive UI testing, when DOM elements change but the functionality is basically the same.
61
+
62
+ ```ruby
63
+ class Page
64
+ include Pouch
65
+ link(:sign_in, id: 'desktop-login')
66
+ link(:mobile_sign_in, id: 'mobile-login')
67
+ ```
68
+
69
+ ```ruby
70
+ # script.rb
71
+ page = Page.new browser_instance, context: ENV['CONTEXT']
72
+ page.sign_in.attribute_value 'id' == 'desktop-login'
73
+ ```
74
+
75
+ ```
76
+ $ ruby script.rb
77
+ #=> true
78
+ $ CONTEXT=mobile ruby script.rb
79
+ #=> false
80
+ ```
24
81
 
25
82
  ## Contributing
26
83
 
27
84
  1. Fork it ( https://github.com/[my-github-username]/pouch/fork )
28
85
  2. Create your feature branch (`git checkout -b my-new-feature`)
29
- 3. Commit your changes (`git commit -am 'Add some feature'`)
30
- 4. Push to the branch (`git push origin my-new-feature`)
31
- 5. Create a new Pull Request
86
+ 3. Write tests
87
+ 4. Code until all tests pass
88
+ 5. Commit your changes (`git commit -am 'Add some feature'`)
89
+ 6. Push to the branch (`git push origin my-new-feature`)
90
+ 7. Create a new Pull Request
@@ -0,0 +1,119 @@
1
+ module Pouch
2
+ module Elements
3
+
4
+ def element tag, name, identifier, *args, &block
5
+ define_method name do
6
+ return browser.element tag, identifier unless block_given?
7
+ block.call browser.send(:element, tag, identifier), *args
8
+ end
9
+ end
10
+
11
+ def button name, identifier, *args, &block
12
+ element :button, name, identifier, args, &block
13
+ end
14
+
15
+ def checkbox name, identifier, *args, &block
16
+ identifier.merge! type: 'checkbox'
17
+ element :input, name, identifier, args, &block
18
+ end
19
+
20
+ def div name, identifier, *args, &block
21
+ element :div, name, identifier, args, &block
22
+ end
23
+
24
+ def file_field name, identifier, *args, &block
25
+ identifier.merge! type: 'file'
26
+ element :input, name, identifier, args, &block
27
+ end
28
+
29
+ def form name, identifier, *args, &block
30
+ element :form, name, identifier, args, &block
31
+ end
32
+
33
+ def h1 name, identifier, *args, &block
34
+ element :h1, name, identifier, args, &block
35
+ end
36
+
37
+ def h2 name, identifier, *args, &block
38
+ element :h2, name, identifier, args, &block
39
+ end
40
+
41
+ def h3 name, identifier, *args, &block
42
+ element :h3, name, identifier, args, &block
43
+ end
44
+
45
+ def h4 name, identifier, *args, &block
46
+ element :h4, name, identifier, args, &block
47
+ end
48
+
49
+ def h5 name, identifier, *args, &block
50
+ element :h5, name, identifier, args, &block
51
+ end
52
+
53
+ def h6 name, identifier, *args, &block
54
+ element :h6, name, identifier, args, &block
55
+ end
56
+
57
+ def image name, identifier, *args, &block
58
+ element :img, name, identifier, args, &block
59
+ end
60
+
61
+ def link name, identifier, *args, &block
62
+ element :a, name, identifier, args, &block
63
+ end
64
+
65
+ def list_item name, identifier, *args, &block
66
+ element :li, name, identifier, args, &block
67
+ end
68
+
69
+ def ordered_list name, identifier, *args, &block
70
+ element :ol, name, identifier, args, &block
71
+ end
72
+
73
+ def paragraph name, identifier, *args, &block
74
+ element :p, name, identifier, args, &block
75
+ end
76
+
77
+ def radio_button name, identifier, *args, &block
78
+ identifier.merge! type: 'radio'
79
+ element :input, name, identifier, args, &block
80
+ end
81
+
82
+ def select_list name, identifier, *args, &block
83
+ element :select, name, identifier, args, &block
84
+ end
85
+
86
+ def span name, identifier, *args, &block
87
+ element :span, name, identifier, args, &block
88
+ end
89
+
90
+ def table name, identifier, *args, &block
91
+ element :table, name, identifier, args, &block
92
+ end
93
+
94
+ def table_cell name, identifier, *args, &block
95
+ element :td, name, identifier, args, &block
96
+ end
97
+
98
+ def table_header name, identifier, *args, &block
99
+ element :th, name, identifier, args, &block
100
+ end
101
+
102
+ def table_row name, identifier, *args, &block
103
+ element :tr, name, identifier, args, &block
104
+ end
105
+
106
+ def text_area name, identifier, *args, &block
107
+ element :textarea, name, identifier, args, &block
108
+ end
109
+
110
+ def text_field name, identifier, *args, &block
111
+ element :input, name, identifier, args, &block
112
+ end
113
+
114
+ def unordered_list name, identifier, *args, &block
115
+ element :ul, name, identifier, args, &block
116
+ end
117
+
118
+ end
119
+ end
data/lib/pouch/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Pouch
2
- VERSION = "0.1.0"
2
+ VERSION = "0.2.0"
3
3
  end
data/lib/pouch.rb CHANGED
@@ -1,6 +1,8 @@
1
1
  require "pouch/version"
2
+ require "pouch/elements"
2
3
 
3
4
  module Pouch
5
+ include Elements
4
6
 
5
7
  class ContextualReplacementError < StandardError; end
6
8
 
@@ -34,13 +36,6 @@ module Pouch
34
36
  end
35
37
  end
36
38
 
37
- def element tag, name, identifier, *args, &block
38
- define_method name do
39
- return browser.element_for tag, identifier unless block_given?
40
- block.call browser.send('element_for', tag, identifier), *args
41
- end
42
- end
43
-
44
39
  private
45
40
 
46
41
  def contextualize_methods
data/pouch.gemspec CHANGED
@@ -9,7 +9,7 @@ Gem::Specification.new do |spec|
9
9
  spec.authors = ["Johnson Denen"]
10
10
  spec.email = ["jdenen@manta.com"]
11
11
  spec.summary = %q{A flexible page object DSL for responsive UI testing}
12
- spec.description = %q{A flexible page object DSL for responsive UI testing via automated browsers and devices}
12
+ spec.description = %q{A flexible page object DSL for responsive UI testing}
13
13
  spec.homepage = "https://github.com/jdenen/pouch"
14
14
  spec.license = "MIT"
15
15
 
@@ -0,0 +1,244 @@
1
+ require 'spec_helper'
2
+ require './lib/pouch/elements'
3
+
4
+ describe Pouch::Elements do
5
+
6
+ class Page
7
+ include Pouch
8
+ element(:a, :generic, id: 'generic')
9
+ element(:a, :blocked, id: 'blocked'){ |link| link.href }
10
+ element(:a, :different_generic, id: 'generic-diff')
11
+ element(:a, :different_blocked, id: 'blocked-diff'){ |link| link.href }
12
+ element(:a, :what_replacement, id: 'no-match')
13
+ end
14
+
15
+ let(:browser){ double 'webdriver' }
16
+ let(:element){ double 'html_link' }
17
+ let(:page){ Page.new browser }
18
+ let(:diff){ Page.new browser, context: 'different' }
19
+ let(:what){ Page.new browser, context: 'what' }
20
+
21
+ describe "#element" do
22
+ it "returns the link element by default" do
23
+ expect(browser).to receive(:element).with(:a, id:'generic').and_return(element)
24
+ expect(page.generic).to eq element
25
+ end
26
+
27
+ it "returns an element that can be clicked" do
28
+ expect(browser).to receive(:element).with(:a, id:'generic').and_return(element)
29
+ expect(element).to receive(:click)
30
+ page.generic.click
31
+ end
32
+
33
+ it "returns the result of the definition block" do
34
+ expect(browser).to receive(:element).with(:a, id:'blocked').and_return(element)
35
+ expect(element).to receive(:href).and_return("www.test.com")
36
+ expect(page.blocked).to eq "www.test.com"
37
+ end
38
+
39
+ context "with context" do
40
+ it "uses the replacement method" do
41
+ expect(browser).to receive(:element).with(:a, id:'generic-diff').and_return(element)
42
+ expect(diff.generic).to eq element
43
+ end
44
+
45
+ it "uses the replacement method with definition block" do
46
+ expect(browser).to receive(:element).with(:a, id:'blocked-diff').and_return(element)
47
+ expect(element).to receive(:href).and_return("www.diff.com")
48
+ expect(diff.blocked).to eq "www.diff.com"
49
+ end
50
+
51
+ it "uses the standard method when context matches no replacement" do
52
+ expect(browser).to receive(:element).with(:a, id:'generic').and_return(element)
53
+ expect(Page.new(browser, context: 'test').generic).to eq element
54
+ end
55
+
56
+ it "throws an error with replacement but no standard method" do
57
+ expect{ what.replacement }.to raise_error Pouch::ContextualReplacementError, /Page defined no standard method for replacement/
58
+ end
59
+ end
60
+ end
61
+
62
+ describe "#button" do
63
+ it "calls :element with :button tag" do
64
+ expect(page).to receive(:element).with(:button, :button_name, {id: 'id'}, [])
65
+ page.send(:button, :button_name, id: 'id')
66
+ end
67
+ end
68
+
69
+ describe "#checkbox" do
70
+ it "calls :element with :checkbox tag" do
71
+ expect(page).to receive(:element).with(:input, :checkbox_name, {id: 'id', type: 'checkbox'}, [])
72
+ page.send(:checkbox, :checkbox_name, id: 'id')
73
+ end
74
+ end
75
+
76
+ describe "#div" do
77
+ it "calls :element with :div tag" do
78
+ expect(page).to receive(:element).with(:div, :div_name, {id: 'id'}, [])
79
+ page.send(:div, :div_name, id: 'id')
80
+ end
81
+ end
82
+
83
+ describe "#file_field" do
84
+ it "calls :element with :file_field tag" do
85
+ expect(page).to receive(:element).with(:input, :ff_name, {id: 'id', type: 'file'}, [])
86
+ page.send(:file_field, :ff_name, id: 'id')
87
+ end
88
+ end
89
+
90
+ describe "#form" do
91
+ it "calls :element with :form tag" do
92
+ expect(page).to receive(:element).with(:form, :form_name, {id: 'id'}, [])
93
+ page.send(:form, :form_name, id: 'id')
94
+ end
95
+ end
96
+
97
+ describe "#h1" do
98
+ it "calls :element with :h1 tag" do
99
+ expect(page).to receive(:element).with(:h1, :h1_name, {id: 'id'}, [])
100
+ page.send(:h1, :h1_name, id: 'id')
101
+ end
102
+ end
103
+
104
+ describe "#h2" do
105
+ it "calls :element with :h2 tag" do
106
+ expect(page).to receive(:element).with(:h2, :h2_name, {id: 'id'}, [])
107
+ page.send(:h2, :h2_name, id: 'id')
108
+ end
109
+ end
110
+
111
+ describe "#h3" do
112
+ it "calls :element with :h3 tag" do
113
+ expect(page).to receive(:element).with(:h3, :h3_name, {id: 'id'}, [])
114
+ page.send(:h3, :h3_name, id: 'id')
115
+ end
116
+ end
117
+
118
+ describe "#h4" do
119
+ it "calls :element with :h4 tag" do
120
+ expect(page).to receive(:element).with(:h4, :h4_name, {id: 'id'}, [])
121
+ page.send(:h4, :h4_name, id: 'id')
122
+ end
123
+ end
124
+
125
+ describe "#h5" do
126
+ it "calls :element with :h5 tag" do
127
+ expect(page).to receive(:element).with(:h5, :h5_name, {id: 'id'}, [])
128
+ page.send(:h5, :h5_name, id: 'id')
129
+ end
130
+ end
131
+
132
+ describe "#h6" do
133
+ it "calls :element with :h6 tag" do
134
+ expect(page).to receive(:element).with(:h6, :h6_name, {id: 'id'}, [])
135
+ page.send(:h6, :h6_name, id: 'id')
136
+ end
137
+ end
138
+
139
+ describe "#image" do
140
+ it "calls :element with :img tag" do
141
+ expect(page).to receive(:element).with(:img, :image_name, {id: 'id'}, [])
142
+ page.send(:image, :image_name, id: 'id')
143
+ end
144
+ end
145
+
146
+ describe "#link" do
147
+ it "calls :element with :a tag" do
148
+ expect(page).to receive(:element).with(:a, :link_name, {id: 'id'}, [])
149
+ page.send(:link, :link_name, id: 'id')
150
+ end
151
+ end
152
+
153
+ describe "#list_item" do
154
+ it "calls :element with :li tag" do
155
+ expect(page).to receive(:element).with(:li, :li_name, {id: 'id'}, [])
156
+ page.send(:list_item, :li_name, id: 'id')
157
+ end
158
+ end
159
+
160
+ describe "#ordered_list" do
161
+ it "calls :element with :ol tag" do
162
+ expect(page).to receive(:element).with(:ol, :ol_name, {id: 'id'}, [])
163
+ page.send(:ordered_list, :ol_name, id: 'id')
164
+ end
165
+ end
166
+
167
+ describe "#paragraph" do
168
+ it "calls :element with :p tag" do
169
+ expect(page).to receive(:element).with(:p, :paragraph_name, {id: 'id'}, [])
170
+ page.send(:paragraph, :paragraph_name, id: 'id')
171
+ end
172
+ end
173
+
174
+ describe "#radio_button" do
175
+ it "calls :element with :radio tag" do
176
+ expect(page).to receive(:element).with(:input, :radio_name, {id: 'id', type: 'radio'}, [])
177
+ page.send(:radio_button, :radio_name, id: 'id')
178
+ end
179
+ end
180
+
181
+ describe "#select_list" do
182
+ it "calls :element with :select tag" do
183
+ expect(page).to receive(:element).with(:select, :select_name, {id: 'id'}, [])
184
+ page.send(:select_list, :select_name, id: 'id')
185
+ end
186
+ end
187
+
188
+ describe "#span" do
189
+ it "calls :element with :span tag" do
190
+ expect(page).to receive(:element).with(:span, :span_name, {id: 'id'}, [])
191
+ page.send(:span, :span_name, id: 'id')
192
+ end
193
+ end
194
+
195
+ describe "#table" do
196
+ it "calls :element with :table tag" do
197
+ expect(page).to receive(:element).with(:table, :table_name, {id: 'id'}, [])
198
+ page.send(:table, :table_name, id: 'id')
199
+ end
200
+ end
201
+
202
+ describe "#table_cell" do
203
+ it "calls :element with :td tag" do
204
+ expect(page).to receive(:element).with(:td, :cell_name, {id: 'id'}, [])
205
+ page.send(:table_cell, :cell_name, id: 'id')
206
+ end
207
+ end
208
+
209
+ describe "#table_header" do
210
+ it "calls :element with :th tag" do
211
+ expect(page).to receive(:element).with(:th, :header_name, {id: 'id'}, [])
212
+ page.send(:table_header, :header_name, id: 'id')
213
+ end
214
+ end
215
+
216
+ describe "#table_row" do
217
+ it "calls :element with :tr tag" do
218
+ expect(page).to receive(:element).with(:tr, :row_name, {id: 'id'}, [])
219
+ page.send(:table_row, :row_name, id: 'id')
220
+ end
221
+ end
222
+
223
+ describe "#text_area" do
224
+ it "calls :element with :input tag" do
225
+ expect(page).to receive(:element).with(:textarea, :text_area_name, {id: 'id'}, [])
226
+ page.send(:text_area, :text_area_name, id: 'id')
227
+ end
228
+ end
229
+
230
+ describe "#text_field" do
231
+ it "calls :element with :input tag" do
232
+ expect(page).to receive(:element).with(:input, :text_field_name, {id: 'id'}, [])
233
+ page.send(:text_field, :text_field_name, id: 'id')
234
+ end
235
+ end
236
+
237
+ describe "#unordered_list" do
238
+ it "calls :element with :ul tag" do
239
+ expect(page).to receive(:element).with(:ul, :ul_name, {id: 'id'}, [])
240
+ page.send(:unordered_list, :ul_name, id: 'id')
241
+ end
242
+ end
243
+
244
+ end
data/spec/pouch_spec.rb CHANGED
@@ -95,74 +95,18 @@ describe Pouch do
95
95
  end
96
96
  end
97
97
 
98
- class Page3
99
- include Pouch
100
- element(:a, :generic, id: 'generic')
101
- element(:a, :blocked, id: 'blocked'){ |link| link.href }
102
- element(:a, :different_generic, id: 'generic-diff')
103
- element(:a, :different_blocked, id: 'blocked-diff'){ |link| link.href }
104
- element(:a, :what_replacement, id: 'no-match')
105
- end
106
-
107
98
  describe "#browser" do
108
99
  it "returns the browser instance" do
109
- obj = Page3.new 'webdriver'
100
+ obj = Page.new 'webdriver'
110
101
  expect(obj.browser).to eq 'webdriver'
111
102
  end
112
103
  end
113
104
 
114
105
  describe "#context" do
115
106
  it "returns the page object context" do
116
- obj = Page3.new 'webdriver', context: ['one', :two, ['three']]
107
+ obj = Page.new 'webdriver', context: ['one', :two, ['three']]
117
108
  expect(obj.context).to eq ['one', 'two', 'three']
118
109
  end
119
110
  end
120
-
121
- describe "#element" do
122
- let(:browser){ double 'webdriver' }
123
- let(:element){ double 'html_link' }
124
- let(:page){ Page3.new browser }
125
- let(:diff){ Page3.new browser, context: 'different' }
126
- let(:what){ Page3.new browser, context: 'what' }
127
-
128
- it "returns the link element by default" do
129
- expect(browser).to receive(:element_for).with(:a, id:'generic').and_return(element)
130
- expect(page.generic).to eq element
131
- end
132
-
133
- it "returns an element that can be clicked" do
134
- expect(browser).to receive(:element_for).with(:a, id:'generic').and_return(element)
135
- expect(element).to receive(:click)
136
- page.generic.click
137
- end
138
-
139
- it "returns the result of the definition block" do
140
- expect(browser).to receive(:element_for).with(:a, id:'blocked').and_return(element)
141
- expect(element).to receive(:href).and_return("www.test.com")
142
- expect(page.blocked).to eq "www.test.com"
143
- end
144
-
145
- context "with context" do
146
- it "uses the replacement method" do
147
- expect(browser).to receive(:element_for).with(:a, id:'generic-diff').and_return(element)
148
- expect(diff.generic).to eq element
149
- end
150
-
151
- it "uses the replacement method with definition block" do
152
- expect(browser).to receive(:element_for).with(:a, id:'blocked-diff').and_return(element)
153
- expect(element).to receive(:href).and_return("www.diff.com")
154
- expect(diff.blocked).to eq "www.diff.com"
155
- end
156
-
157
- it "uses the standard method when context matches no replacement" do
158
- expect(browser).to receive(:element_for).with(:a, id:'generic').and_return(element)
159
- expect(Page3.new(browser, context: 'test').generic).to eq element
160
- end
161
-
162
- it "throws an error with replacement but no standard method" do
163
- expect{ what.replacement }.to raise_error Pouch::ContextualReplacementError, /Page3 defined no standard method for replacement/
164
- end
165
- end
166
- end
167
111
 
168
112
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pouch
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-11-26 00:00:00.000000000 Z
12
+ date: 2014-11-27 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: watir-webdriver
@@ -75,8 +75,7 @@ dependencies:
75
75
  - - ~>
76
76
  - !ruby/object:Gem::Version
77
77
  version: 3.0.0
78
- description: A flexible page object DSL for responsive UI testing via automated browsers
79
- and devices
78
+ description: A flexible page object DSL for responsive UI testing
80
79
  email:
81
80
  - jdenen@manta.com
82
81
  executables: []
@@ -89,8 +88,10 @@ files:
89
88
  - README.md
90
89
  - Rakefile
91
90
  - lib/pouch.rb
91
+ - lib/pouch/elements.rb
92
92
  - lib/pouch/version.rb
93
93
  - pouch.gemspec
94
+ - spec/elements_spec.rb
94
95
  - spec/pouch_spec.rb
95
96
  - spec/spec_helper.rb
96
97
  homepage: https://github.com/jdenen/pouch
@@ -119,6 +120,7 @@ signing_key:
119
120
  specification_version: 3
120
121
  summary: A flexible page object DSL for responsive UI testing
121
122
  test_files:
123
+ - spec/elements_spec.rb
122
124
  - spec/pouch_spec.rb
123
125
  - spec/spec_helper.rb
124
126
  has_rdoc: