napybara 0.4.1 → 0.5.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 53a5710df7b6badb61d443588bec50cd7d179618
4
- data.tar.gz: 61e611ff8fa988a70190860db4e0b8800cb010ce
3
+ metadata.gz: c7b2cbbf480b100b3a1adc606cfa57b05868f860
4
+ data.tar.gz: 2a4ec7daa20873ffb807f49eba6302d4aa9171d1
5
5
  SHA512:
6
- metadata.gz: 7e25b434912b12dc7175089a32433d62a24ec4b1d8a533e80e4a86c46c98d6e04b157528aa37a7462dbaf930f51cd7e2f6725297db3366fc9ef0901f47f37503
7
- data.tar.gz: 81beacfbd669927f9798c7c4ecec8333f88bbb16fe285aee98d0836f6ba7c6d3f87b5fa62ee744a8e44719bd9c41c055ae0a1879e48f509c44e24d523af92a22
6
+ metadata.gz: b5661e2643515c2fa34eacef4702e1aa577f17f84ee4f02a9d0cf7d7929f544613ad183cc6c1ecf1ef6b78a584958376d634997d415819aa3b85a89794901e5f
7
+ data.tar.gz: 7eff003cfac47e53c8f476679e123630913f7eb289dc59bf71fbe48063bee022b049b0ddfa805ac35eeaaa05b2ec7d3f72b56735a512eddec629dce7842ca2f6
@@ -3,5 +3,4 @@ rvm:
3
3
  - 1.9.3
4
4
  - 2.0.0
5
5
  - 2.1.0
6
- - rbx
7
6
  cache: bundler
@@ -1,5 +1,11 @@
1
1
  # Changelog
2
2
 
3
+ ## master
4
+
5
+ Rename `#get` as #node. `#get` may become deprecated soon.
6
+
7
+ Add `#selector`.
8
+
3
9
  ## 0.4.1
4
10
 
5
11
  Update README.
data/README.md CHANGED
@@ -1,5 +1,7 @@
1
1
  # Napybara
2
2
 
3
+ [![Build Status](https://api.travis-ci.org/gsmendoza/napybara.svg)](https://travis-ci.org/gsmendoza/napybara)
4
+
3
5
  So you're writing an integration test for the following page:
4
6
 
5
7
  ```html
@@ -19,12 +21,13 @@ So you're writing an integration test for the following page:
19
21
  </html>
20
22
  ```
21
23
 
22
- Wouldn't it be nice if your test helpers followed the page's structure?
24
+ Wouldn't it be nice if you can write test helpers that followed the page's
25
+ structure?
23
26
 
24
27
  ```ruby
25
28
  messages_page.visit!
26
29
 
27
- messages_page.form.message_row.text_field.get.set 'Hello World!'
30
+ messages_page.form.message_row.text_field.node.set 'Hello World!'
28
31
  messages_page.form.submit!
29
32
 
30
33
  expect(messages_page.message(Message.find(1))).to have_content('Hello world!')
@@ -36,7 +39,7 @@ expect(messages_page.messages[1]).to have_content('Kamusta mundo!')
36
39
 
37
40
  With Napybara, now you can!
38
41
 
39
- ## Napybara::Element.new and #get
42
+ ## Napybara::Element.new and #node
40
43
 
41
44
  First off, let's wrap the Capybara session in a Napybara element:
42
45
 
@@ -49,10 +52,10 @@ end
49
52
  In Rails integration tests which use Capybara, `self` is usually the Capybara session.
50
53
 
51
54
  You can get the Capybara element wrapped by the Napybara element with
52
- `Napybara::Element#get`:
55
+ `Napybara::Element#node`:
53
56
 
54
57
  ```ruby
55
- expect(messages_page.get).to eq(self)
58
+ expect(messages_page.node).to eq(self)
56
59
  ```
57
60
 
58
61
  ## Finding by selector
@@ -68,7 +71,7 @@ end
68
71
 
69
72
  # ...
70
73
 
71
- expect(messages_page.form.get['class']).to eq('new-message')
74
+ expect(messages_page.form.node['class']).to eq('new-message')
72
75
  ```
73
76
 
74
77
  ## Finding by object
@@ -89,7 +92,7 @@ end
89
92
 
90
93
  # ...
91
94
 
92
- expect(messages_page.message(some_message).get['id'])
95
+ expect(messages_page.message(some_message).node['id'])
93
96
  .to eq("message-#{some_message.id}")
94
97
 
95
98
  ```
@@ -106,7 +109,7 @@ If the ruby object is identified by a method other than the object's id, you can
106
109
  `Napybara::Element#finder` also adds `has_` and `has_no_` methods to the element.
107
110
  With the Napybara elements above, you can call:
108
111
 
109
- ```
112
+ ```ruby
110
113
  expect(messages_page.has_form?).to be_true
111
114
  expect(messages_page).to have_form
112
115
 
@@ -136,8 +139,8 @@ end
136
139
 
137
140
  # ...
138
141
 
139
- expect(messages_page.messages[0].get.text).to eq("Hello world!")
140
- expect(messages_page.messages[1].get.text).to eq("Kamusta mundo!")
142
+ expect(messages_page.messages[0].node.text).to eq("Hello world!")
143
+ expect(messages_page.messages[1].node.text).to eq("Kamusta mundo!")
141
144
  ```
142
145
 
143
146
  Napybara uses ActiveSupport to get the plural version of the finder name.
@@ -150,7 +153,7 @@ You can add new methods to a Napybara element with plain Ruby:
150
153
  let(:messages_page) do
151
154
  Napybara::Element.new(self) do |page|
152
155
  def page.visit!
153
- get.visit get.messages_path
156
+ node.visit node.messages_path
154
157
  end
155
158
  end
156
159
  end
@@ -167,7 +170,7 @@ Adding the same methods to multiple Napybara elements? You can share the methods
167
170
  ```ruby
168
171
  module PageExtensions
169
172
  def visit!
170
- get.visit get.messages_path
173
+ node.visit node.messages_path
171
174
  @visited = true
172
175
  end
173
176
 
@@ -192,10 +195,10 @@ expect(messages_page).to be_visited
192
195
 
193
196
  And what if you want to share a module with finders? Again, with plain Ruby:
194
197
 
195
- ```
198
+ ```ruby
196
199
  module IsAForm
197
200
  def submit!
198
- submit_button.get.click
201
+ submit_button.node.click
199
202
  end
200
203
 
201
204
  def self.add_to(form)
@@ -222,7 +225,7 @@ helpers at the start of this README:
222
225
 
223
226
  module PageExtensions
224
227
  def visit!
225
- get.visit get.messages_path
228
+ node.visit node.messages_path
226
229
  @visited = true
227
230
  end
228
231
 
@@ -233,7 +236,7 @@ end
233
236
 
234
237
  module IsAForm
235
238
  def submit!
236
- submit_button.get.click
239
+ submit_button.node.click
237
240
  end
238
241
 
239
242
  def self.add_to(form)
@@ -243,7 +246,7 @@ module IsAForm
243
246
  end
244
247
 
245
248
  let(:messages_page) do
246
- Napybara::Element.new(capybara_page) do |page|
249
+ Napybara::Element.new(self) do |page|
247
250
  page.extend PageExtensions
248
251
 
249
252
  page.finder :form, 'form.new-message' do |form|
@@ -259,6 +262,27 @@ let(:messages_page) do
259
262
  end
260
263
  ```
261
264
 
265
+ ## And a few more things: getting the selector of a finder
266
+
267
+ `Napybara::Element#selector` returns a selector that can be used to find the element:
268
+
269
+ ```ruby
270
+ expect(messages_page.form.message_row.text_field.selector)
271
+ .to eq('form.new-message .message-row input[type=text]')
272
+
273
+ expect(messages_page.message(Message.find(2)).selector)
274
+ .to eq('#message-2')
275
+
276
+ expect(messages_page.messages.selector)
277
+ .to eq('.message-list .message')
278
+
279
+ expect(messages_page.messages[1].selector)
280
+ .to eq('.message-list .message')
281
+
282
+ ```
283
+
284
+ Take note that with `messages_page.messages[1]`, it's currently not possible to get the ith match of a selector. We'll have to wait until [`nth-match`](http://www.w3.org/TR/selectors4/#nth-match-pseudo) becomes mainstream.
285
+
262
286
  ## Installation
263
287
 
264
288
  ```
@@ -4,4 +4,6 @@ module Napybara
4
4
  end
5
5
 
6
6
  require "napybara/element"
7
+ require "napybara/element_array"
8
+ require "napybara/selector"
7
9
  require "napybara/version"
@@ -2,18 +2,24 @@ require 'napybara'
2
2
 
3
3
  module Napybara
4
4
  class Element
5
- attr_reader :capybara_element
6
- alias_method :get, :capybara_element
5
+ attr_reader :node, :parent, :selector_string
6
+
7
+ alias_method :get, :node
8
+
9
+ def initialize(node, parent = nil, selector_string = nil, &block)
10
+ @node = node
11
+ @parent = parent
12
+ @selector_string = selector_string
7
13
 
8
- def initialize(capybara_element, &block)
9
- @capybara_element = capybara_element
10
14
  block.call(self) if block_given?
11
15
  end
12
16
 
13
17
  def finder(child_element_name, child_element_selector, record_selector = nil, &block)
14
18
  self.define_singleton_method(child_element_name) do |record = nil|
15
19
  selector = Selector.new(child_element_selector, record_selector, record)
16
- self.class.new(self.get.find(selector.to_s), &block)
20
+ selector_string = selector.to_s
21
+
22
+ self.class.new(self.get.find(selector_string), self, selector_string, &block)
17
23
  end
18
24
 
19
25
  self.define_singleton_method("has_#{child_element_name}?") do |record = nil|
@@ -27,29 +33,19 @@ module Napybara
27
33
  end
28
34
 
29
35
  self.define_singleton_method(child_element_name.to_s.pluralize) do
30
- self.get.all(child_element_selector).map do |child_element|
31
- self.class.new(child_element, &block)
32
- end
33
- end
34
- end
36
+ elements = self.get.all(child_element_selector)
37
+ .map.with_index do |child_element, i|
35
38
 
36
- class Selector < Struct.new(:child_element_selector, :record_selector, :record)
37
- METHOD_NAME_REGEX = /\{(\w+)\}/
38
- def method_name
39
- record_selector.match(METHOD_NAME_REGEX)[1]
40
- end
39
+ self.class.new(child_element, self, child_element_selector, &block)
40
+ end
41
41
 
42
- def record_id
43
- record && record.public_send(method_name)
42
+ ElementArray.new(elements, self, child_element_selector)
44
43
  end
44
+ end
45
45
 
46
- def to_s
47
- if record
48
- record_selector.gsub(METHOD_NAME_REGEX, record_id.to_s)
49
- else
50
- child_element_selector
51
- end
52
- end
46
+ def selector
47
+ parent_selector = parent.try(:selector)
48
+ parent_selector ? "#{parent_selector} #{selector_string}" : selector_string
53
49
  end
54
50
  end
55
51
  end
@@ -0,0 +1,14 @@
1
+ module Napybara
2
+ class ElementArray < Array
3
+ def initialize(elements, parent, selector_string = '')
4
+ @parent = parent
5
+ @selector_string = selector_string
6
+ super(elements)
7
+ end
8
+
9
+ def selector
10
+ parent_selector = @parent.try(:selector)
11
+ parent_selector ? "#{@parent.selector} #{@selector_string}" : @selector_string
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,20 @@
1
+ module Napybara
2
+ class Selector < Struct.new(:child_element_selector, :record_selector, :record)
3
+ METHOD_NAME_REGEX = /\{(\w+)\}/
4
+ def method_name
5
+ record_selector.match(METHOD_NAME_REGEX)[1]
6
+ end
7
+
8
+ def record_id
9
+ record && record.public_send(method_name)
10
+ end
11
+
12
+ def to_s
13
+ if record
14
+ record_selector.gsub(METHOD_NAME_REGEX, record_id.to_s)
15
+ else
16
+ child_element_selector
17
+ end
18
+ end
19
+ end
20
+ end
@@ -1,3 +1,3 @@
1
1
  module Napybara
2
- VERSION = "0.4.1"
2
+ VERSION = "0.5.0"
3
3
  end
@@ -11,7 +11,7 @@ describe 'Readme example:' do
11
11
  <li class="message" id="message-2">Kamusta mundo!</li>
12
12
  </ul>
13
13
  <form class='new-message'>
14
- <div class="message-row" />
14
+ <div class="message-row">
15
15
  <label for='message'>Message</label>
16
16
  <input id='message' type='text' name='message'>
17
17
  </div>
@@ -30,8 +30,8 @@ describe 'Readme example:' do
30
30
  @messages_page = Napybara::Element.new(capybara_page)
31
31
  end
32
32
 
33
- And "I call #get on the Napybara page" do
34
- @get_result = @messages_page.get
33
+ And "I call #node on the Napybara page" do
34
+ @get_result = @messages_page.node
35
35
  end
36
36
 
37
37
  Then "I should get the capybara page" do
@@ -52,7 +52,7 @@ describe 'Readme example:' do
52
52
 
53
53
  Then "the finder should be able to find the element matching the selector" do
54
54
 
55
- expect(@messages_page.form.get['class']).to eq('new-message')
55
+ expect(@messages_page.form.node['class']).to eq('new-message')
56
56
  end
57
57
  end
58
58
 
@@ -70,7 +70,7 @@ describe 'Readme example:' do
70
70
  Then "the finder should be able to find the element matching a given object" do
71
71
  id = 1
72
72
  message = OpenStruct.new(id: id)
73
- expect(@messages_page.message(message).get['id']).to eq("message-#{id}")
73
+ expect(@messages_page.message(message).node['id']).to eq("message-#{id}")
74
74
  end
75
75
  end
76
76
 
@@ -114,8 +114,8 @@ describe 'Readme example:' do
114
114
  Then "I should be able to find all the elements matching the selector with
115
115
  a plural version of the finder name" do
116
116
 
117
- expect(@messages_page.message_items[0].get.text).to eq("Hello world!")
118
- expect(@messages_page.message_items[1].get.text).to eq("Kamusta mundo!")
117
+ expect(@messages_page.message_items[0].node.text).to eq("Hello world!")
118
+ expect(@messages_page.message_items[1].node.text).to eq("Kamusta mundo!")
119
119
  end
120
120
  end
121
121
 
@@ -169,4 +169,37 @@ describe 'Readme example:' do
169
169
  expect(@messages_page).to be_visited
170
170
  end
171
171
  end
172
+
173
+ Steps "Getting the selector of a finder" do
174
+ Given "I have a a capybara page" do
175
+ capybara_page
176
+ end
177
+
178
+ When "I wrap the page in a Napybara element" do
179
+ @messages_page = Napybara::Element.new(capybara_page) do |page|
180
+ page.finder :form, 'form.new-message' do |form|
181
+
182
+ form.finder :message_row, '.message-row' do |row|
183
+ row.finder :text_field, 'input[type=text]'
184
+ end
185
+ end
186
+
187
+ page.finder :message, '.messages-list .message', '#message-{id}'
188
+ end
189
+ end
190
+
191
+ Then "I can get the selectors of the Napybara finder results" do
192
+ expect(@messages_page.form.message_row.text_field.selector)
193
+ .to eq('form.new-message .message-row input[type=text]')
194
+
195
+ expect(@messages_page.message(OpenStruct.new(id: 2)).selector)
196
+ .to eq('#message-2')
197
+
198
+ expect(@messages_page.messages.selector)
199
+ .to eq('.messages-list .message')
200
+
201
+ expect(@messages_page.messages[1].selector)
202
+ .to eq('.messages-list .message')
203
+ end
204
+ end
172
205
  end
@@ -104,4 +104,80 @@ describe Napybara::Element do
104
104
  expect(page.has_no_form?(object)).to be_false
105
105
  end
106
106
  end
107
+
108
+ describe "#selector" do
109
+ it "can return the selector for a single element" do
110
+ napybara_page = described_class.new(capybara_page) do |page|
111
+ page.finder :form, '.some-form'
112
+ end
113
+
114
+ expect(napybara_page.form.selector).to eq('.some-form')
115
+ end
116
+
117
+ it "can return the selector for an element nested one layer" do
118
+ napybara_page = described_class.new(capybara_page) do |page|
119
+ page.finder :form, '.some-form' do |form|
120
+ form.finder :some_button, '.some-button'
121
+ end
122
+ end
123
+
124
+ expect(napybara_page.form.some_button.selector).to eq('.some-form .some-button')
125
+ end
126
+
127
+ it "can return the selector for an element nested more than one layer" do
128
+ napybara_page = described_class.new(capybara_page) do |page|
129
+ page.finder :form, '.some-form' do |form|
130
+ form.finder :some_button, '.some-button' do |button|
131
+ button.finder :img, 'img'
132
+ end
133
+ end
134
+ end
135
+
136
+ expect(napybara_page.form.some_button.img.selector)
137
+ .to eq('.some-form .some-button img')
138
+ end
139
+
140
+ it "can return the selector for an element array" do
141
+ napybara_page = described_class.new(capybara_page) do |page|
142
+ page.finder :button, 'button'
143
+ end
144
+
145
+ expect(napybara_page.buttons.selector).to eq('button')
146
+ end
147
+
148
+ context "where the items of the element array are not adjacent" do
149
+ let(:capybara_page) do
150
+ Capybara.string <<-HTML
151
+ <form class='some-form', id='form-1'>
152
+ <button class='recognized-button some-button' />
153
+ <button class='ignored-button' />
154
+ <button class='recognized-button another-button' />
155
+ </form>
156
+ HTML
157
+ end
158
+
159
+ it "can return the selector of the ith item of an element array" do
160
+ napybara_page = described_class.new(capybara_page) do |page|
161
+ page.finder :button, '.recognized-button'
162
+ end
163
+
164
+ first_button = napybara_page.buttons[1]
165
+
166
+ expect(first_button.selector).to eq('.recognized-button')
167
+
168
+ expect(napybara_page.node.all(first_button.selector)[1]['class'])
169
+ .to eq('recognized-button another-button')
170
+ end
171
+ end
172
+
173
+ it "can return the selector of an child of an element array item" do
174
+ napybara_page = described_class.new(capybara_page) do |page|
175
+ page.finder :button, 'button' do |button|
176
+ button.finder :image, 'img'
177
+ end
178
+ end
179
+
180
+ expect(napybara_page.buttons[0].image.selector).to eq('button img')
181
+ end
182
+ end
107
183
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: napybara
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.1
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - George Mendoza
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-05-18 00:00:00.000000000 Z
11
+ date: 2014-06-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -198,6 +198,8 @@ files:
198
198
  - Rakefile
199
199
  - lib/napybara.rb
200
200
  - lib/napybara/element.rb
201
+ - lib/napybara/element_array.rb
202
+ - lib/napybara/selector.rb
201
203
  - lib/napybara/version.rb
202
204
  - napybara.gemspec
203
205
  - spec/dummy_app/config.ru