napybara 0.3.0 → 0.3.1

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