capybara_test_helpers 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/CHANGELOG.md +3 -0
- data/README.md +401 -0
- data/lib/capybara_test_helpers.rb +6 -0
- data/lib/capybara_test_helpers/actions.rb +116 -0
- data/lib/capybara_test_helpers/assertions.rb +124 -0
- data/lib/capybara_test_helpers/benchmark_helpers.rb +94 -0
- data/lib/capybara_test_helpers/config.rb +56 -0
- data/lib/capybara_test_helpers/cucumber.rb +12 -0
- data/lib/capybara_test_helpers/dependency_injection.rb +44 -0
- data/lib/capybara_test_helpers/finders.rb +40 -0
- data/lib/capybara_test_helpers/matchers.rb +55 -0
- data/lib/capybara_test_helpers/rspec.rb +33 -0
- data/lib/capybara_test_helpers/selectors.rb +174 -0
- data/lib/capybara_test_helpers/synchronization.rb +41 -0
- data/lib/capybara_test_helpers/test_helper.rb +182 -0
- data/lib/capybara_test_helpers/to_or_expectation_handler.rb +27 -0
- data/lib/capybara_test_helpers/version.rb +6 -0
- data/lib/generators/test_helper/test_helper_generator.rb +26 -0
- metadata +92 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: f491ad2f4d94ecd7e159466955e97b5e87117a5bb3fdb8eb907139e25fcb7ef1
|
4
|
+
data.tar.gz: 0f2d79cf1b201ffc6f4a2b7601b2550c85e626f2ebe32f367538e49a5adfcde2
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: c323a983bc4b02cde81006a986388c8cb1a5c88c4db8a8c4b9a2bc746765c8b6b46487593b25ce2a46628865b6b2bb54cbb6c1afeeaea7965667778e60044e2b
|
7
|
+
data.tar.gz: 7b77a14b74c33d4a934071014a43db8ed63c184fea3e5ef8fc91a1ed4439f7e3a40398b87cd763249771b6a813e3a608fcd1caff93c941d4baa97db60f711b7e
|
data/CHANGELOG.md
ADDED
data/README.md
ADDED
@@ -0,0 +1,401 @@
|
|
1
|
+
<h1 align="center">
|
2
|
+
Capybara Test Helpers
|
3
|
+
<p align="center">
|
4
|
+
<a href="https://github.com/ElMassimo/capybara_test_helpers/actions"><img alt="Build Status" src="https://github.com/ElMassimo/capybara_test_helpers/workflows/build/badge.svg"/></a>
|
5
|
+
<a href="https://inch-ci.org/github/ElMassimo/capybara_test_helpers"><img alt="Inline docs" src="https://inch-ci.org/github/ElMassimo/capybara_test_helpers.svg"/></a>
|
6
|
+
<a href="https://codeclimate.com/github/ElMassimo/capybara_test_helpers"><img alt="Maintainability" src="https://codeclimate.com/github/ElMassimo/capybara_test_helpers/badges/gpa.svg"/></a>
|
7
|
+
<a href="https://codeclimate.com/github/ElMassimo/capybara_test_helpers"><img alt="Test Coverage" src="https://codeclimate.com/github/ElMassimo/capybara_test_helpers/badges/coverage.svg"/></a>
|
8
|
+
<a href="https://rubygems.org/gems/capybara_test_helpers"><img alt="Gem Version" src="https://img.shields.io/gem/v/capybara_test_helpers.svg?colorB=e9573f"/></a>
|
9
|
+
<a href="https://github.com/ElMassimo/capybara_test_helpers/blob/master/LICENSE.txt"><img alt="License" src="https://img.shields.io/badge/license-MIT-428F7E.svg"/></a>
|
10
|
+
</p>
|
11
|
+
</h1>
|
12
|
+
|
13
|
+
[__Capybara Test Helpers__](https://github.com/ElMassimo/capybara_test_helpers) is
|
14
|
+
an opinionated library built on top of [capybara], that encourages good testing
|
15
|
+
practices based on encapsulation and reuse.
|
16
|
+
|
17
|
+
Write tests that everyone can understand, and leverage your Ruby skills to keep tests __easy to read and easy to change__.
|
18
|
+
|
19
|
+
[capybara]: https://github.com/teamcapybara/capybara
|
20
|
+
[capybara dsl]: https://github.com/teamcapybara/capybara#the-dsl
|
21
|
+
[capybara querying]: https://github.com/teamcapybara/capybara#querying
|
22
|
+
[cucumber]: https://github.com/cucumber/cucumber-ruby
|
23
|
+
[rspec]: https://github.com/rspec/rspec
|
24
|
+
[rspec matchers]: https://relishapp.com/rspec/rspec-expectations/docs/built-in-matchers
|
25
|
+
[rspec-rails]: https://github.com/rspec/rspec-rails#installation
|
26
|
+
[trailing_commas]: https://maximomussini.com/posts/trailing-commas/
|
27
|
+
[testing_robots]: https://jakewharton.com/testing-robots/
|
28
|
+
[page_objects]: https://martinfowler.com/bliki/PageObject.html
|
29
|
+
[rspec_injection]: https://github.com/ElMassimo/capybara_test_helpers/blob/master/examples/rails_app/spec/system/cities_spec.rb#L7
|
30
|
+
[rspec_global_injection]: https://github.com/ElMassimo/capybara_test_helpers/blob/master/examples/rails_app/spec/support/default_test_helpers.rb#L8
|
31
|
+
[cucumber_injection]: https://github.com/ElMassimo/capybara_test_helpers/blob/master/examples/rails_app/features/step_definitions/city_steps.rb#L3
|
32
|
+
[example app]: https://github.com/ElMassimo/capybara_test_helpers/blob/master/examples/rails_app
|
33
|
+
[capybara_test_helpers_tests]: https://github.com/ElMassimo/capybara_test_helpers/blob/master/spec
|
34
|
+
[positive and negative assertions]: https://maximomussini.com/posts/cucumber-to_or_not_to/
|
35
|
+
[should]: https://github.com/ElMassimo/capybara_test_helpers/blob/master/lib/capybara_test_helpers/assertions.rb#L10-L15
|
36
|
+
[should_not]: https://github.com/ElMassimo/capybara_test_helpers/blob/master/lib/capybara_test_helpers/assertions.rb#L17-L22
|
37
|
+
[rails_integration]: https://github.com/ElMassimo/capybara_test_helpers/commit/c512e39987215e30227dad45e775480bc1348325
|
38
|
+
[cucumber_integration]: https://github.com/ElMassimo/capybara_test_helpers/commit/68e20cb40ba409c50f88f8b745eb908fb067a0aa
|
39
|
+
|
40
|
+
## Why? 🤔
|
41
|
+
|
42
|
+
[`capybara`][capybara] is a great library for integration tests in Ruby,
|
43
|
+
commonly used in combination with [RSpec] or [cucumber].
|
44
|
+
|
45
|
+
Although [cucumber] encourages good practices such as writing steps at a high
|
46
|
+
level, thinking in terms of the user rather than the interactions required, it
|
47
|
+
__doesn't scale well__ in a large project. Steps are available for all tests,
|
48
|
+
and there's no way to partition or isolate them.
|
49
|
+
|
50
|
+
At the same time, Gherkin is very limited as a language, it can be very awkward
|
51
|
+
to use when steps require parameters, and it's hard to find and detect duplicate
|
52
|
+
steps, and very __time consuming__ to refactor them.
|
53
|
+
|
54
|
+
In contrast, writing tests in [RSpec] has a very low barrier since Ruby is a joy
|
55
|
+
to work with, but you are on your own to encapsulate code to avoid coupling
|
56
|
+
tests to the current UI. Small changes to the UI should not require rewriting
|
57
|
+
dozens of tests, but __without clear guidelines__ it's hard to achieve good tests.
|
58
|
+
|
59
|
+
This library provides __a solid foundation__ of simple and repeatable patterns
|
60
|
+
that can be used to write better tests.
|
61
|
+
|
62
|
+
## Features ⚡️
|
63
|
+
|
64
|
+
- Leverage your __Ruby__ skills for keeping tests in good shape
|
65
|
+
- Powerful syntax for __assertions__ (without monkey patching)
|
66
|
+
- __Aliases__ for element locators to avoid repetition
|
67
|
+
- __Composability__: define interactions with your UI once, and [focus on the tests][testing robots] many times
|
68
|
+
- Dependency injection to make tests __predictable and robust__
|
69
|
+
- Full access to the __[Capybara DSL]__
|
70
|
+
|
71
|
+
## Installation 💿
|
72
|
+
|
73
|
+
Add this line to your application's Gemfile:
|
74
|
+
|
75
|
+
```ruby
|
76
|
+
gem 'capybara_test_helpers'
|
77
|
+
```
|
78
|
+
|
79
|
+
And then run:
|
80
|
+
|
81
|
+
$ bundle install
|
82
|
+
|
83
|
+
### RSpec
|
84
|
+
|
85
|
+
To use with [RSpec], require the following in `spec_helper.rb`:
|
86
|
+
|
87
|
+
```ruby
|
88
|
+
require 'capybara_test_helpers/rspec'
|
89
|
+
```
|
90
|
+
|
91
|
+
#### In Rails
|
92
|
+
|
93
|
+
If using Rails, make sure you [follow the setup in `rspec-rails`][rspec-rails] first.
|
94
|
+
|
95
|
+
You can run `rails g test_helper base` to create a base test helper and require
|
96
|
+
it as well so that other test helpers can extend it without manually requiring.
|
97
|
+
|
98
|
+
```ruby
|
99
|
+
# spec/rails_helper.rb
|
100
|
+
require 'capybara_test_helpers/rspec'
|
101
|
+
require Rails.root.join('test_helpers/base_test_helper')
|
102
|
+
```
|
103
|
+
|
104
|
+
[Check this example][rails_integration] to see how you can get started.
|
105
|
+
|
106
|
+
### Cucumber
|
107
|
+
|
108
|
+
To use with [Cucumber], require the following in `env.rb`:
|
109
|
+
|
110
|
+
```ruby
|
111
|
+
require 'capybara_test_helpers/cucumber'
|
112
|
+
require Rails.root.join('test_helpers/base_test_helper')
|
113
|
+
```
|
114
|
+
|
115
|
+
Have in mind that RSpec is a much better fit, as Gherkin is very limited.
|
116
|
+
|
117
|
+
That said, test helpers do provide [a nice way to share code](https://github.com/ElMassimo/capybara_test_helpers/blob/master/examples/rails_app/features/step_definitions/city_steps.rb) if you are migrating
|
118
|
+
from Cucumber to RSpec.
|
119
|
+
|
120
|
+
[Check this example][cucumber_integration] to see how you can get started.
|
121
|
+
|
122
|
+
## Usage 🚀
|
123
|
+
|
124
|
+
You can define a test helper by subclassing `Capybara::TestHelper`, which has
|
125
|
+
full access to the Capybara DSL.
|
126
|
+
|
127
|
+
When using Rails, you can generate a test helper by running:
|
128
|
+
|
129
|
+
rails g test_helper users
|
130
|
+
|
131
|
+
```ruby
|
132
|
+
class UsersTestHelper < Capybara::TestHelper
|
133
|
+
# Selectors: Semantic aliases for elements, a useful abstraction.
|
134
|
+
SELECTORS = {
|
135
|
+
el: 'table.users',
|
136
|
+
form: '.user-form',
|
137
|
+
submit_button: [:button, type: 'submit'],
|
138
|
+
}
|
139
|
+
|
140
|
+
# Getters: A convenient way to get related data or nested elements.
|
141
|
+
def row_for(user)
|
142
|
+
within { find(:table_row, { 'Name' => user.name }) }
|
143
|
+
end
|
144
|
+
|
145
|
+
# Actions: Encapsulate complex actions to provide a cleaner interface.
|
146
|
+
def add(attrs)
|
147
|
+
click_on('Add User')
|
148
|
+
save_user(**attrs)
|
149
|
+
end
|
150
|
+
|
151
|
+
def edit(user, with:)
|
152
|
+
row_for(user).click_on('Edit')
|
153
|
+
save_user(**with)
|
154
|
+
end
|
155
|
+
|
156
|
+
def delete(user)
|
157
|
+
row_for(user).click_on('Delete')
|
158
|
+
accept_confirm
|
159
|
+
end
|
160
|
+
|
161
|
+
private \
|
162
|
+
def save_user(name:, language:)
|
163
|
+
within(:form) {
|
164
|
+
fill_in('Name', with: name)
|
165
|
+
choose('Language', option: language)
|
166
|
+
submit_button.click
|
167
|
+
}
|
168
|
+
end
|
169
|
+
|
170
|
+
# Assertions: Allow to check on element properties while keeping it DRY.
|
171
|
+
def have_user(name:, language:)
|
172
|
+
columns = { 'Name' => name, 'Language' => language }
|
173
|
+
within { have(:table_row, columns) }
|
174
|
+
end
|
175
|
+
end
|
176
|
+
```
|
177
|
+
|
178
|
+
To make the test helper available you can [use the `test_helpers` option in RSpec][rspec_injection],
|
179
|
+
or [call `use_test_helpers` in Cucumber step definitions][cucumber_injection].
|
180
|
+
|
181
|
+
For test helpers that you expect to use very often, [`use_test_helpers` allows you to make them available globally][rspec_global_injection].
|
182
|
+
|
183
|
+
### Writing a Test with Helpers ✅
|
184
|
+
|
185
|
+
You can find [this working example](https://github.com/ElMassimo/capybara_test_helpers/blob/master/examples/rails_app/spec/features/cities_spec.rb) and more in the [example app] and the [Capybara tests][capybara_test_helpers_tests].
|
186
|
+
|
187
|
+
```ruby
|
188
|
+
require 'rails_helper'
|
189
|
+
|
190
|
+
RSpec.describe 'Cities', test_helpers: [:cities] do
|
191
|
+
let!(:nyc) { cities.given_there_is_a_city('NYC') }
|
192
|
+
|
193
|
+
before { cities.visit_page }
|
194
|
+
|
195
|
+
scenario 'valid inputs' do
|
196
|
+
cities.add(name: 'Minneapolis')
|
197
|
+
cities.should.have_city('Minneapolis')
|
198
|
+
end
|
199
|
+
|
200
|
+
scenario 'invalid inputs' do
|
201
|
+
cities.add(name: '') { |form|
|
202
|
+
form.should.have_error("Name can't be blank")
|
203
|
+
}
|
204
|
+
end
|
205
|
+
|
206
|
+
scenario 'editing a city' do
|
207
|
+
cities.edit(nyc, with: { name: 'New York City' })
|
208
|
+
cities.should_no_longer.have_city('NYC')
|
209
|
+
cities.should_now.have_city('New York City')
|
210
|
+
end
|
211
|
+
|
212
|
+
scenario 'deleting a city', screen_size: :phone do
|
213
|
+
cities.delete(nyc)
|
214
|
+
cities.should_no_longer.have_city('NYC')
|
215
|
+
end
|
216
|
+
end
|
217
|
+
```
|
218
|
+
|
219
|
+
## DSL 🛠
|
220
|
+
|
221
|
+
A documentation website with the full API and examples is coming soon.
|
222
|
+
|
223
|
+
Every single method in the [Capybara DSL] is available inside test helpers, as
|
224
|
+
well as the [built-in RSpec matchers][rspec matchers].
|
225
|
+
|
226
|
+
### Selectors 🔍
|
227
|
+
|
228
|
+
You can encapsulate locators for commonly used elements to avoid hardcoding them
|
229
|
+
in different tests.
|
230
|
+
|
231
|
+
As a result, if the implementation changes, there are less places that need to
|
232
|
+
be updated, making it faster to update tests after UI changes.
|
233
|
+
|
234
|
+
```ruby
|
235
|
+
class FormTestHelper < BaseTestHelper
|
236
|
+
SELECTORS = {
|
237
|
+
el: '.form',
|
238
|
+
error_summary: ['#error_explanation', visible: true],
|
239
|
+
name_input: [:fillable_field, 'Name'],
|
240
|
+
save_button: [:button, type: 'submit'],
|
241
|
+
}
|
242
|
+
```
|
243
|
+
|
244
|
+
You can then leverage these aliases on any Capybara method:
|
245
|
+
|
246
|
+
```ruby
|
247
|
+
# Finding an element
|
248
|
+
form.find(:save_button, visible: false)
|
249
|
+
|
250
|
+
# Interacting with an element
|
251
|
+
form.fill_in(:name_input, with: 'Jane')
|
252
|
+
|
253
|
+
# Making an assertion
|
254
|
+
form.has_selector?(:error_summary, text: "Can't be blank")
|
255
|
+
```
|
256
|
+
|
257
|
+
#### Syntax Sugar
|
258
|
+
|
259
|
+
To avoid repetition, getters are available for every selector alias:
|
260
|
+
|
261
|
+
```ruby
|
262
|
+
form.find(:name_input)
|
263
|
+
# same as
|
264
|
+
form.name_input
|
265
|
+
|
266
|
+
form.find(:error_summary, text: "Can't be blank")
|
267
|
+
# same as
|
268
|
+
form.error_summary(text: "Can't be blank")
|
269
|
+
```
|
270
|
+
|
271
|
+
#### `:el` convention
|
272
|
+
|
273
|
+
By convention, `:el` is the top-level element of the component or page the test
|
274
|
+
helper is encapsulating, which will be used automatically when calling a
|
275
|
+
Capybara operation that requires a node, such as `click` or `value`.
|
276
|
+
|
277
|
+
```ruby
|
278
|
+
form.within { save_button.click }
|
279
|
+
# same as
|
280
|
+
form.within(:el) { save_button.click }
|
281
|
+
# same as
|
282
|
+
form.el.within { save_button.click }
|
283
|
+
```
|
284
|
+
|
285
|
+
### Assertions ☑️
|
286
|
+
|
287
|
+
You can use any of the [RSpec matchers provided by Capybara][capybara querying],
|
288
|
+
but the way to use them in test helpers is slightly different.
|
289
|
+
|
290
|
+
Before using an assertion, you must call [`should`][should] or [`should_not`][should_not], and then
|
291
|
+
chain the RSpec matcher or your own custom assertion.
|
292
|
+
|
293
|
+
```ruby
|
294
|
+
users.find(:table)
|
295
|
+
.should.have_selector(:table_row, ['Jane', 'Doe']
|
296
|
+
.should_not.have_selector(:table_row, ['John', 'Doe'])
|
297
|
+
```
|
298
|
+
|
299
|
+
#### Custom Assertions 🎩
|
300
|
+
|
301
|
+
The example above becomes a lot nicer if we define a more semantic assertion,
|
302
|
+
which can be easily done by leveraging an existing assertion:
|
303
|
+
|
304
|
+
```ruby
|
305
|
+
class UsersTestHelper < BaseTestHelper
|
306
|
+
SELECTORS = {
|
307
|
+
list: 'table.users',
|
308
|
+
}
|
309
|
+
|
310
|
+
# Assertions: Check on element properties, used with `should` and `should_not`.
|
311
|
+
def have_user(*names)
|
312
|
+
have(:table_row, names)
|
313
|
+
end
|
314
|
+
```
|
315
|
+
|
316
|
+
and then use it as:
|
317
|
+
|
318
|
+
```ruby
|
319
|
+
users.list
|
320
|
+
.should.have_user('Jane', 'Doe')
|
321
|
+
.should_not.have_user('John', 'Doe')
|
322
|
+
```
|
323
|
+
|
324
|
+
Notice that you don't need to define both the [positive and negative assertions],
|
325
|
+
they are both available because we are using an existing assertion.
|
326
|
+
|
327
|
+
#### Advanced Assertions ⚙️
|
328
|
+
|
329
|
+
Sometimes built-in assertions are not enough, and you need to use an expectation
|
330
|
+
directly. Test helpers provide a `to_or` and `not_to` method, similar to [the
|
331
|
+
technique described in this post][positive and negative assertions] that you
|
332
|
+
can use to implement an assertion that you can use with `should` or `should_not`.
|
333
|
+
|
334
|
+
```ruby
|
335
|
+
# frozen_string_literal: true
|
336
|
+
|
337
|
+
class CurrentPageTestHelper < BaseTestHelper
|
338
|
+
# Getters: A convenient way to get related data or nested elements.
|
339
|
+
def fullscreen?
|
340
|
+
evaluate_script('!!(document.mozFullScreenElement || document.webkitFullscreenElement)')
|
341
|
+
end
|
342
|
+
|
343
|
+
# Assertions: Allow to check on element properties while keeping it DRY.
|
344
|
+
def be_fullscreen
|
345
|
+
expect(fullscreen?).to_or not_to, eq(true)
|
346
|
+
end
|
347
|
+
end
|
348
|
+
|
349
|
+
current_page.should.be_fullscreen
|
350
|
+
current_page.should_not.be_fullscreen
|
351
|
+
```
|
352
|
+
|
353
|
+
You can make the assertion retry automatically until the Capybara timeout by
|
354
|
+
using `synchronize_expectation`:
|
355
|
+
|
356
|
+
```ruby
|
357
|
+
def be_fullscreen
|
358
|
+
synchronize_expectation {
|
359
|
+
expect(fullscreen?).to_or not_to, eq(true)
|
360
|
+
}
|
361
|
+
end
|
362
|
+
```
|
363
|
+
|
364
|
+
## Design 📐
|
365
|
+
|
366
|
+
This library is loosely based on the concepts of [Page Objects][page_objects] and [Testing Robots][testing_robots], with a healthy dose of [dependency injection](https://martinfowler.com/articles/injection.html).
|
367
|
+
|
368
|
+
Capybara has a great DSL, so the focus of this library is to build upon it, by
|
369
|
+
allowing you to create your own actions and assertions and call them just as
|
370
|
+
fluidly as you would call `find` or `has_content?`.
|
371
|
+
|
372
|
+
This library works best when encapsulating common UI patterns in separate helpers,
|
373
|
+
such as a `FormTestHelper` or a `DropdownTestHelper`, and then reusing them in
|
374
|
+
page-specific test helpers to make the test read more semantically.
|
375
|
+
|
376
|
+
## Formatting 📏
|
377
|
+
|
378
|
+
Regarding selectors, I highly recommend writing one attribute per line, sorting
|
379
|
+
them alphabetically (most editors can do it for you), and
|
380
|
+
[always using a trailing comma][trailing_commas].
|
381
|
+
|
382
|
+
```ruby
|
383
|
+
class DropdownTestHelper < BaseTestHelper
|
384
|
+
# Selectors: Semantic aliases for elements, a useful abstraction.
|
385
|
+
SELECTORS = {
|
386
|
+
el: '.dropdown',
|
387
|
+
toggle: '.dropdown-toggle',
|
388
|
+
}
|
389
|
+
```
|
390
|
+
|
391
|
+
It will minimize the amount of git conflicts, and keep the history a lot cleaner and more meaningful when using `git blame`.
|
392
|
+
|
393
|
+
## Special Thanks 🙏
|
394
|
+
|
395
|
+
This library wouldn't be the same without the early validation from my colleagues, and numerous improvements and bugfixes they contributed to it. Thanks for the support 😃
|
396
|
+
|
397
|
+
- [capybara]: Solid library to write integration tests in Ruby.
|
398
|
+
|
399
|
+
## License
|
400
|
+
|
401
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
@@ -0,0 +1,116 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Internal: Allows to pass test helpers as arguments to `evaluate_script`.
|
4
|
+
Capybara::Session.prepend(Module.new {
|
5
|
+
private
|
6
|
+
|
7
|
+
# Override: To ensure test helpers are sent to the driver as native elements.
|
8
|
+
def driver_args(args)
|
9
|
+
super(args.map { |arg| arg.is_a?(CapybaraTestHelpers::TestHelper) ? arg.to_capybara_node : arg })
|
10
|
+
end
|
11
|
+
})
|
12
|
+
|
13
|
+
# Internal: Allows to pass a test helper to `scroll_to`.
|
14
|
+
Capybara::Node::Element.prepend(Module.new {
|
15
|
+
# Override: Unwrap capybara test helpers into a node.
|
16
|
+
def scroll_to(pos_or_x_or_el, *args, **kwargs)
|
17
|
+
pos_or_x_or_el = pos_or_x_or_el.to_capybara_node if pos_or_x_or_el.is_a?(CapybaraTestHelpers::TestHelper)
|
18
|
+
super
|
19
|
+
end
|
20
|
+
})
|
21
|
+
|
22
|
+
# Internal: Wraps Capybara actions to enable locator aliases, and to wrap the
|
23
|
+
# result with a test helper so that methods can be chained in a fluent style.
|
24
|
+
module CapybaraTestHelpers::Actions
|
25
|
+
delegate(
|
26
|
+
:==, # Allows to make comparisons more transparent.
|
27
|
+
:===, # Allows to ensure case statements inside Capybara work as expected.
|
28
|
+
to: :to_capybara_node,
|
29
|
+
)
|
30
|
+
|
31
|
+
delegate(
|
32
|
+
:[],
|
33
|
+
:all_text,
|
34
|
+
:checked?,
|
35
|
+
:disabled?,
|
36
|
+
:multiple?,
|
37
|
+
:obscured?,
|
38
|
+
:readonly?,
|
39
|
+
:selected?,
|
40
|
+
:base,
|
41
|
+
:native,
|
42
|
+
:path,
|
43
|
+
:rect,
|
44
|
+
:style,
|
45
|
+
:tag_name,
|
46
|
+
:text,
|
47
|
+
:value,
|
48
|
+
:visible?,
|
49
|
+
:visible_text,
|
50
|
+
to: :to_capybara_node,
|
51
|
+
)
|
52
|
+
|
53
|
+
delegate(
|
54
|
+
:evaluate_script,
|
55
|
+
:evaluate_async_script,
|
56
|
+
to: :current_context,
|
57
|
+
)
|
58
|
+
|
59
|
+
%i[
|
60
|
+
execute_script
|
61
|
+
scroll_to
|
62
|
+
].each do |method_name|
|
63
|
+
CapybaraTestHelpers.define_helper_method(self, method_name, return_self: true, inject_test_helper: false)
|
64
|
+
end
|
65
|
+
|
66
|
+
%i[
|
67
|
+
click
|
68
|
+
double_click
|
69
|
+
drag_to
|
70
|
+
drop
|
71
|
+
flash
|
72
|
+
hover
|
73
|
+
reload
|
74
|
+
right_click
|
75
|
+
select_option
|
76
|
+
send_keys
|
77
|
+
set
|
78
|
+
trigger
|
79
|
+
unselect_option
|
80
|
+
].each do |method_name|
|
81
|
+
CapybaraTestHelpers.define_helper_method(self, method_name, target: :to_capybara_node, return_self: true, inject_test_helper: false)
|
82
|
+
end
|
83
|
+
|
84
|
+
%i[
|
85
|
+
click_on
|
86
|
+
click_link_or_button
|
87
|
+
click_button
|
88
|
+
click_link
|
89
|
+
choose
|
90
|
+
check
|
91
|
+
uncheck
|
92
|
+
fill_in
|
93
|
+
attach_file
|
94
|
+
select
|
95
|
+
unselect
|
96
|
+
].each do |method_name|
|
97
|
+
CapybaraTestHelpers.define_helper_method(self, method_name, wrap: true)
|
98
|
+
end
|
99
|
+
|
100
|
+
# Public: Sets the value for the input, or presses the specified keys, one at a time.
|
101
|
+
def type_in(*text, typing: text.size > 1 || text.first.is_a?(Symbol) || text.first.is_a?(Array), **options)
|
102
|
+
typing ? send_keys(*text) : set(text.first, **options)
|
103
|
+
end
|
104
|
+
|
105
|
+
# Public: Useful to natively give focus to an element.
|
106
|
+
def focus
|
107
|
+
to_capybara_node.execute_script('this.focus()')
|
108
|
+
self
|
109
|
+
end
|
110
|
+
|
111
|
+
# Public: Useful to natively blur an element.
|
112
|
+
def blur
|
113
|
+
to_capybara_node.execute_script('this.blur()')
|
114
|
+
self
|
115
|
+
end
|
116
|
+
end
|