napybara 0.3.0 → 0.3.1

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: 1acb0ab3b95532810db2654efd6a23ff89d23a58
4
- data.tar.gz: 8d24168fbf6adc727fdd89afe2ecf8d1c6c1d714
3
+ metadata.gz: c60bfd33a34b3c9225ede612cd2ceaecb644b235
4
+ data.tar.gz: ed872c87a98a39850a887a9f66e5fdcf5884e143
5
5
  SHA512:
6
- metadata.gz: d3f4c003ac74d14684fcff69c18e06d571ae68d43f00df59738581af6b4711127eaf8657d7adb07e2c3ea9f46a25738b224a5949ec0165738011f43ac300d571
7
- data.tar.gz: 0a46fea43e3df63a71780a4691894d4cb61efbe380e02f2185442d590cf9af67c4c4b14a0f47529b17671b5d07679986f57cc1b8d82221fd470482d3f16fbd4c
6
+ metadata.gz: 745db690753460d0e8b058f176463fac216f5a335b3abf4409e2229f3f6c3f8c75ea79b5b84f6d8ce204b2134cf7172f6dfc0caef95ad11207df7b1dfdbe245f
7
+ data.tar.gz: dcde1d036cedd78c9894b01110d6536db00e66a954cd82cd977ac8bcdd4961b535810e5ffb7b51b40c159bacffe8619412266289c486193c19468807d299248c
data/README.md CHANGED
@@ -5,12 +5,12 @@ So you're writing an integration test for the following page:
5
5
  ```html
6
6
  <html>
7
7
  <body>
8
- <ul class='messages-list'>
9
- <li class="message">Hello world!</li>
10
- <li class="message">Kamusta mundo!</li>
8
+ <ul class='message-list'>
9
+ <li class="message" id="message-1">Hello world!</li>
10
+ <li class="message" id="message-2">Kamusta mundo!</li>
11
11
  </ul>
12
12
  <form class='new-message'>
13
- <div class="message" />
13
+ <div class="message-row" />
14
14
  <label for='message'>Message</label>
15
15
  <input id='message' type='text' name='message'>
16
16
  </div>
@@ -19,87 +19,221 @@ So you're writing an integration test for the following page:
19
19
  </html>
20
20
  ```
21
21
 
22
- Wouldn't it be nice if your test helpers followed the structure of the page?
22
+ Wouldn't it be nice if you can write test helpers so that they followed the page structure?
23
23
 
24
24
  ```ruby
25
25
  messages_page.visit!
26
- messages_page.form.message.text_field.get.set 'Hello World!'
26
+
27
+ messages_page.form.message_row.text_field.get.set 'Hello World!'
27
28
  messages_page.form.submit!
28
- expect(messages_page.messages[0]).to have_content('Hello world!')
29
- expect(messages_page.messages[1]).to have_content('Kamusta mundo!')
29
+
30
+ expect(messages_page.message(Message.find(1))).to have_content('Hello world!')
31
+ expect(messages_page.message(Message.find(2))).to have_content('Kamusta mundo!')
32
+
33
+ expect(messages_page.message_items[0]).to have_content('Hello world!')
34
+ expect(messages_page.message_items[1]).to have_content('Kamusta mundo!')
35
+ ```
36
+
37
+ With Napybara, now you can!
38
+
39
+ ## Napybara::Element.new and #get
40
+
41
+ First off, let's wrap the Capybara session in a Napybara element:
42
+
43
+ ```ruby
44
+ let(:messages_page) do
45
+ Napybara::Element.new(self)
46
+ end
30
47
  ```
31
48
 
32
- With Napybara, now they can! All you need is to define the structure of the page with Napybara's DSL:
49
+ In Rails integration tests which use Capybara, `self` usually is the Capybara session.
50
+
51
+ You can get the capybara element wrapped by the Napybara element with
52
+ `Napybara::Element#get`:
33
53
 
34
54
  ```ruby
35
- # spec/features/messages_spec.rb
55
+ expect(messages_page.get).to eq(self)
56
+ ```
57
+
58
+ ## Finding by selector
36
59
 
37
- let(:new_message_page) do
60
+ You can add finders to the Napybara page with `Napybara::Element#finder`:
61
+
62
+ ```ruby
63
+ let(:messages_page) do
38
64
  Napybara::Element.new(self) do |page|
39
- page.finder :message, '.messages-list .message'
65
+ page.finder :form, 'form.new-message'
66
+ end
67
+ end
40
68
 
41
- page.finder :form, 'form.new-message' do |form|
42
- form.finder :message, '.message' do |row|
43
- row.finder :text_field, 'input#message'
44
- end
69
+ # ...
45
70
 
46
- form.finder :submit_button, 'input[type=submit]'
47
- end
71
+ expect(messages_page.form.get['class']).to eq('new-message')
72
+ ```
73
+
74
+ ## Finding by object
75
+
76
+ In Rails, dom elements usually have ids which end with object ids, the objects
77
+ usually being active records. The method generated by `Napybara::Element#finder`
78
+ can also accept an object when searching for the object's matching element:
79
+
80
+ ```ruby
81
+ let(:messages_page) do
82
+ Napybara::Element.new(self) do |page|
83
+ page.finder :message, '#message-'
48
84
  end
49
85
  end
86
+
87
+ let(:some_message) do
88
+ Message.find(1)
89
+ end
90
+
91
+ # ...
92
+
93
+ expect(messages_page.message(some_message).get['id'])
94
+ .to eq("messages-#{some_message.id}")
95
+
96
+ ```
97
+
98
+ In the above example, the `message` finder looks for an element matching the
99
+ given selector (`#message-`) with `some_message`'s id (`1`). So it ends up
100
+ looking for "#message-1".
101
+
102
+ ## Calling the finder with or without an object argument
103
+
104
+ As you may have observed, the finder added by `Napybara::Element#finder`
105
+ can be called with or without an object argument. Usually, you only want to use
106
+ just one of these two options; the selector you declare will determine what
107
+ option you want to use. For example, `#message-` only makes sense with an object
108
+ id at the end of the selector, so you want to call the `messages_page.message()`
109
+ finder with an object. On the other hand, `form.new-message` does not make sense
110
+ with an object id at the end of the selector, so you want to call the
111
+ `messages_page.form()` finder without an object argument.
112
+
113
+ ## Checking if an element exists
114
+
115
+ `Napybara::Element#finder` also adds `has_` and `has_no_` methods to the element.
116
+ With the Napybara elements above, you can call:
117
+
50
118
  ```
119
+ expect(messages_page.has_form?).to be_true
120
+ expect(messages_page).to have_form
51
121
 
52
- In the integration test above, the `self` in `Napybara::Element.new(self)` points to the current test session. In Rails integration tests which include `Capybara::DSL`, `self` would already have access to `Capybara::DSL`'s methods.
122
+ expect(messages_page.has_message?(some_message).to be_true
123
+ expect(messages_page).to have_message(some_message)
53
124
 
54
- What about the custom `messages_page.visit!` and `form.submit!` methods? With Napybara, you can extend each element in the structure. So if you want to add a `visit!` method to the `messages_page` element, you can write
125
+ non_existent_message = Message.find(3)
126
+ expect(messages_page.has_no_message?(non_existent_message)).to be_true
127
+ expect(messages_page).to have_no_message(non_existent_message)
128
+ ```
129
+
130
+ Due to the magic that Capybara does when finding elements in a Ajaxified page,
131
+ it's recommended to call `expect(element).to have_no_...` instead of
132
+ `expect(element).to_not have...`, since the former relies on Capybara's Ajax-
133
+ friendly `has_no_css?` method.
134
+
135
+ ## Finding all elements matching a selector
136
+
137
+ Finally, `Napybara::Element#finder` adds a pluralized version of the finder. For example,
55
138
 
56
139
  ```ruby
57
- Napybara::Element.new(self) do |page|
58
- def page.visit!
59
- get.visit '/messages/index'
140
+ let(:messages_page) do
141
+ Napybara::Element.new(self) do |page|
142
+ page.finder :message_item, '.message'
60
143
  end
144
+ end
145
+
146
+ # ...
147
+
148
+ expect(messages_page.message_items[0].get.text).to eq("Hello world!")
149
+ expect(messages_page.message_items[1].get.text).to eq("Kamusta mundo!")
150
+ ```
151
+
152
+ Napybara uses ActiveSupport to get the plural version of the finder name.
153
+
154
+ ## Adding custom methods to a Napybara element
61
155
 
62
- # ...
156
+ We can add new methods to a Napybara element with plain Ruby:
157
+
158
+ ```ruby
159
+ let(:messages_page) do
160
+ Napybara::Element.new(self) do |page|
161
+ def page.visit!
162
+ get.visit get.messages_path
163
+ end
164
+ end
63
165
  end
166
+
167
+ # ...
168
+
169
+ messages_page.visit!
64
170
  ```
65
171
 
66
- `get` here points to the Capybara element that the Napybara element is wrapping.
172
+ ## Extending a Napybara element with a module
67
173
 
68
- You can also reuse helpers by extend the Napybara element with a module. For example, with `form.submit!`:
174
+ Adding the same methods to multiple Napybara elements? You can share the methods in a module:
69
175
 
70
176
  ```ruby
71
- module FormExtensions
72
- def submit!
73
- submit_button.get.click
177
+ module PageExtensions
178
+ def visit!
179
+ get.visit get.messages_path
180
+ @visited = true
181
+ end
182
+
183
+ def visited?
184
+ !! @visited
74
185
  end
75
186
  end
76
187
 
77
- Napybara::Element.new(self) do |page|
78
- page.finder :form, 'form.new-message' do |form|
79
- form.extend FormExtensions
80
- # ...
188
+ let(:messages_page) do
189
+ Napybara::Element.new(capybara_page) do |page|
190
+ page.extend PageExtensions
81
191
  end
82
192
  end
193
+
194
+ # ...
195
+
196
+ messages_page.visit!
197
+ expect(messages_page).to be_visited
83
198
  ```
84
199
 
85
- ## Installation
200
+ ## Putting it all together
86
201
 
87
- Add this line to your application's Gemfile:
202
+ Oh yeah, the "N" in Napybara stands for nesting. Here's how you can define the
203
+ helpers at the start of this README:
88
204
 
89
- gem 'Napybara'
205
+ ```ruby
206
+ let(:messages_page) do
207
+ Napybara::Element.new(capybara_page) do |page|
208
+ def page.visit!
209
+ get.visit get.messages_path
210
+ end
90
211
 
91
- And then execute:
212
+ page.finder :form, 'form.new-message' do |form|
213
+ def form.submit!
214
+ submit_button.get.click
215
+ end
92
216
 
93
- $ bundle
217
+ form.finder :message_row, '.message-row' do |row|
218
+ row.finder :text_field, 'input[type=text]'
219
+ end
94
220
 
95
- Or install it yourself as:
221
+ form.finder :submit_button, 'input[type=submit]'
222
+ end
223
+
224
+ page.finder :message, '.message-list #message-'
225
+ page.finder :message_item, '.message-list .message'
226
+ end
227
+ end
228
+ ```
96
229
 
97
- $ gem install Napybara
230
+ ## Installation
231
+
232
+ ```
233
+ $ gem install Napybara
234
+ ```
98
235
 
99
236
  ## Contributing
100
237
 
101
- 1. Fork it ( http://github.com/<my-github-username>/Napybara/fork )
102
- 2. Create your feature branch (`git checkout -b my-new-feature`)
103
- 3. Commit your changes (`git commit -am 'Add some feature'`)
104
- 4. Push to the branch (`git push origin my-new-feature`)
105
- 5. Create new Pull Request
238
+ I'm still looking for ways to improve Napybara's DSL. If you have an idea, a
239
+ pull request would be awesome :)
@@ -16,12 +16,12 @@ module Napybara
16
16
  self.class.new(self.get.find(selector.to_s), &block)
17
17
  end
18
18
 
19
- self.define_singleton_method("has_#{child_element_name}?") do |record|
19
+ self.define_singleton_method("has_#{child_element_name}?") do |record = nil|
20
20
  selector = Selector.new(child_element_selector, method_name, record)
21
21
  self.get.has_css?(selector.to_s)
22
22
  end
23
23
 
24
- self.define_singleton_method("has_no_#{child_element_name}?") do |record|
24
+ self.define_singleton_method("has_no_#{child_element_name}?") do |record = nil|
25
25
  selector = Selector.new(child_element_selector, method_name, record)
26
26
  self.get.has_no_css?(selector.to_s)
27
27
  end
@@ -1,3 +1,3 @@
1
1
  module Napybara
2
- VERSION = "0.3.0"
2
+ VERSION = "0.3.1"
3
3
  end
data/napybara.gemspec CHANGED
@@ -10,7 +10,7 @@ Gem::Specification.new do |spec|
10
10
  spec.email = ["gsmendoza@gmail.com"]
11
11
  spec.summary = %q{napybara == nested capybara}
12
12
  spec.description = %q{DSL for nesting capybara helpers}
13
- spec.homepage = ""
13
+ spec.homepage = "https://github.com/gsmendoza/napybara"
14
14
  spec.license = "MIT"
15
15
 
16
16
  spec.files = `git ls-files -z`.split("\x0")
@@ -0,0 +1,172 @@
1
+ require 'spec_helper'
2
+ require 'dummy_app/dummy_app'
3
+
4
+ describe 'Readme example:' do
5
+ let(:capybara_page) do
6
+ Capybara.string <<-HTML
7
+ <html>
8
+ <body>
9
+ <ul class='messages-list'>
10
+ <li class="message" id="message-1">Hello world!</li>
11
+ <li class="message" id="message-2">Kamusta mundo!</li>
12
+ </ul>
13
+ <form class='new-message'>
14
+ <div class="message-row" />
15
+ <label for='message'>Message</label>
16
+ <input id='message' type='text' name='message'>
17
+ </div>
18
+ <input type='submit' value='Send'/>
19
+ </form>
20
+ </html>
21
+ HTML
22
+ end
23
+
24
+ Steps "Wrapping a page in a Napybara element" do
25
+ Given "I have a capybara page" do
26
+ capybara_page
27
+ end
28
+
29
+ When "I wrap that capybara page in a Napybara page" do
30
+ @messages_page = Napybara::Element.new(capybara_page)
31
+ end
32
+
33
+ And "I call #get on the Napybara page" do
34
+ @get_result = @messages_page.get
35
+ end
36
+
37
+ Then "I should get the capybara page" do
38
+ expect(@get_result).to eq(capybara_page)
39
+ end
40
+ end
41
+
42
+ Steps 'Find by selector' do
43
+ Given "I have a capybara page" do
44
+ capybara_page
45
+ end
46
+
47
+ When "I add a finder to the Napybara page wrapping the capybara page" do
48
+ @messages_page = Napybara::Element.new(capybara_page) do |page|
49
+ page.finder :form, 'form.new-message'
50
+ end
51
+ end
52
+
53
+ Then "the finder should be able to find the element matching the selector" do
54
+
55
+ expect(@messages_page.form.get['class']).to eq('new-message')
56
+ end
57
+ end
58
+
59
+ Steps 'Find by object' do
60
+ Given "I have a capybara page" do
61
+ capybara_page
62
+ end
63
+
64
+ When "I add an object finder to the Napybara page wrapping the capybara page" do
65
+ @messages_page = Napybara::Element.new(capybara_page) do |page|
66
+ page.finder :message, '#message-'
67
+ end
68
+ end
69
+
70
+ Then "the finder should be able to find the element matching a given object" do
71
+ id = 1
72
+ message = OpenStruct.new(id: id)
73
+ expect(@messages_page.message(message).get['id']).to eq("message-#{id}")
74
+ end
75
+ end
76
+
77
+ Steps 'Existence finders' do
78
+ Given "I have a capybara page" do
79
+ capybara_page
80
+ end
81
+
82
+ When "I add finders to the Napybara page wrapping the capybara page" do
83
+ @messages_page = Napybara::Element.new(capybara_page) do |page|
84
+ page.finder :form, 'form.new-message'
85
+ page.finder :message, '#message-'
86
+ end
87
+ end
88
+
89
+ Then "I can check for the existence of elements" do
90
+ expect(@messages_page.has_form?).to be_true
91
+ expect(@messages_page).to have_form
92
+
93
+ some_message = OpenStruct.new(id: 1)
94
+ expect(@messages_page.has_message?(some_message)).to be_true
95
+ expect(@messages_page).to have_message(some_message)
96
+
97
+ non_existent_message = OpenStruct.new(id: 3)
98
+ expect(@messages_page.has_no_message?(non_existent_message)).to be_true
99
+ expect(@messages_page).to have_no_message(non_existent_message)
100
+ end
101
+ end
102
+
103
+ Steps 'Find all by selector' do
104
+ Given "I have a capybara page" do
105
+ capybara_page
106
+ end
107
+
108
+ When "I add a plain finder to the Napybara page wrapping the capybara page" do
109
+ @messages_page = Napybara::Element.new(capybara_page) do |page|
110
+ page.finder :message_item, '.message'
111
+ end
112
+ end
113
+
114
+ Then "I should be able to find all the elements matching the selector with
115
+ a plural version of the finder name" do
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!")
119
+ end
120
+ end
121
+
122
+ Steps "Adding a custom method to the Napybara element" do
123
+ Given "I have a capybara page" do
124
+ capybara_page
125
+ end
126
+
127
+ When "I add a custom method to the Napybara element wrapping the capybara
128
+ element" do
129
+ @messages_page = Napybara::Element.new(capybara_page) do |page|
130
+ def page.visit!
131
+ @visited = true
132
+ end
133
+
134
+ def page.visited?
135
+ !! @visited
136
+ end
137
+ end
138
+ end
139
+
140
+ Then "I can call the custom method on the Napybara element" do
141
+ @messages_page.visit!
142
+ expect(@messages_page).to be_visited
143
+ end
144
+ end
145
+
146
+ Steps "Extending the Napybara element with a module" do
147
+ Given "I have a capybara page" do
148
+ capybara_page
149
+ end
150
+
151
+ When "I extend the Napybara element with a module" do
152
+ module PageExtensions
153
+ def visit!
154
+ @visited = true
155
+ end
156
+
157
+ def visited?
158
+ !! @visited
159
+ end
160
+ end
161
+
162
+ @messages_page = Napybara::Element.new(capybara_page) do |page|
163
+ page.extend PageExtensions
164
+ end
165
+ end
166
+
167
+ Then "I can call the custom methods in the module on the Napybara element" do
168
+ @messages_page.visit!
169
+ expect(@messages_page).to be_visited
170
+ end
171
+ end
172
+ 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.3.0
4
+ version: 0.3.1
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-04-02 00:00:00.000000000 Z
11
+ date: 2014-04-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -205,9 +205,10 @@ files:
205
205
  - spec/dummy_app/public/new_content.html
206
206
  - spec/dummy_app/public/test.html
207
207
  - spec/integration/napybara_spec.rb
208
+ - spec/integration/readme_spec.rb
208
209
  - spec/napybara/element_spec.rb
209
210
  - spec/spec_helper.rb
210
- homepage: ''
211
+ homepage: https://github.com/gsmendoza/napybara
211
212
  licenses:
212
213
  - MIT
213
214
  metadata: {}
@@ -238,5 +239,6 @@ test_files:
238
239
  - spec/dummy_app/public/new_content.html
239
240
  - spec/dummy_app/public/test.html
240
241
  - spec/integration/napybara_spec.rb
242
+ - spec/integration/readme_spec.rb
241
243
  - spec/napybara/element_spec.rb
242
244
  - spec/spec_helper.rb