capybara_test_helpers 1.0.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 +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
|