rspec-rails 3.7.0 → 4.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.
Files changed (81) hide show
  1. checksums.yaml +5 -5
  2. checksums.yaml.gz.sig +0 -0
  3. data/Capybara.md +5 -54
  4. data/Changelog.md +259 -70
  5. data/README.md +265 -496
  6. data/lib/generators/rspec/channel/channel_generator.rb +12 -0
  7. data/lib/generators/rspec/{observer/templates/observer_spec.rb → channel/templates/channel_spec.rb.erb} +1 -1
  8. data/lib/generators/rspec/controller/controller_generator.rb +21 -4
  9. data/lib/generators/rspec/controller/templates/request_spec.rb +14 -0
  10. data/lib/generators/rspec/controller/templates/routing_spec.rb +13 -0
  11. data/lib/generators/rspec/feature/feature_generator.rb +4 -4
  12. data/lib/generators/rspec/generator/generator_generator.rb +24 -0
  13. data/lib/generators/rspec/generator/templates/generator_spec.rb +6 -0
  14. data/lib/generators/rspec/helper/helper_generator.rb +1 -1
  15. data/lib/generators/rspec/install/install_generator.rb +4 -4
  16. data/lib/generators/rspec/install/templates/spec/rails_helper.rb +25 -12
  17. data/lib/generators/rspec/integration/integration_generator.rb +4 -4
  18. data/lib/generators/rspec/integration/templates/request_spec.rb +1 -1
  19. data/lib/generators/rspec/mailbox/mailbox_generator.rb +14 -0
  20. data/lib/generators/rspec/mailbox/templates/mailbox_spec.rb.erb +7 -0
  21. data/lib/generators/rspec/mailer/mailer_generator.rb +2 -1
  22. data/lib/generators/rspec/mailer/templates/preview.rb +1 -1
  23. data/lib/generators/rspec/model/model_generator.rb +6 -5
  24. data/lib/generators/rspec/model/templates/fixtures.yml +1 -1
  25. data/lib/generators/rspec/request/request_generator.rb +1 -1
  26. data/lib/generators/rspec/scaffold/scaffold_generator.rb +43 -23
  27. data/lib/generators/rspec/scaffold/templates/api_controller_spec.rb +2 -38
  28. data/lib/generators/rspec/scaffold/templates/api_request_spec.rb +131 -0
  29. data/lib/generators/rspec/scaffold/templates/controller_spec.rb +17 -17
  30. data/lib/generators/rspec/scaffold/templates/edit_spec.rb +1 -1
  31. data/lib/generators/rspec/scaffold/templates/index_spec.rb +2 -2
  32. data/lib/generators/rspec/scaffold/templates/new_spec.rb +1 -1
  33. data/lib/generators/rspec/scaffold/templates/request_spec.rb +133 -0
  34. data/lib/generators/rspec/scaffold/templates/routing_spec.rb +10 -13
  35. data/lib/generators/rspec/scaffold/templates/show_spec.rb +1 -1
  36. data/lib/generators/rspec/system/system_generator.rb +26 -0
  37. data/lib/generators/rspec/system/templates/system_spec.rb +9 -0
  38. data/lib/generators/rspec/view/view_generator.rb +2 -2
  39. data/lib/generators/rspec.rb +0 -6
  40. data/lib/rspec/rails/adapters.rb +11 -76
  41. data/lib/rspec/rails/configuration.rb +47 -36
  42. data/lib/rspec/rails/example/channel_example_group.rb +93 -0
  43. data/lib/rspec/rails/example/controller_example_group.rb +4 -4
  44. data/lib/rspec/rails/example/feature_example_group.rb +6 -26
  45. data/lib/rspec/rails/example/helper_example_group.rb +2 -9
  46. data/lib/rspec/rails/example/mailbox_example_group.rb +80 -0
  47. data/lib/rspec/rails/example/mailer_example_group.rb +1 -1
  48. data/lib/rspec/rails/example/rails_example_group.rb +1 -1
  49. data/lib/rspec/rails/example/system_example_group.rb +96 -60
  50. data/lib/rspec/rails/example/view_example_group.rb +47 -28
  51. data/lib/rspec/rails/example.rb +3 -3
  52. data/lib/rspec/rails/extensions/active_record/proxy.rb +1 -9
  53. data/lib/rspec/rails/feature_check.rb +12 -29
  54. data/lib/rspec/rails/fixture_file_upload_support.rb +40 -0
  55. data/lib/rspec/rails/fixture_support.rb +37 -31
  56. data/lib/rspec/rails/matchers/action_cable/have_broadcasted_to.rb +170 -0
  57. data/lib/rspec/rails/matchers/action_cable/have_streams.rb +58 -0
  58. data/lib/rspec/rails/matchers/action_cable.rb +65 -0
  59. data/lib/rspec/rails/matchers/action_mailbox.rb +64 -0
  60. data/lib/rspec/rails/matchers/active_job.rb +180 -22
  61. data/lib/rspec/rails/matchers/base_matcher.rb +179 -0
  62. data/lib/rspec/rails/matchers/be_a_new.rb +1 -1
  63. data/lib/rspec/rails/matchers/be_new_record.rb +1 -1
  64. data/lib/rspec/rails/matchers/be_valid.rb +1 -1
  65. data/lib/rspec/rails/matchers/have_enqueued_mail.rb +198 -0
  66. data/lib/rspec/rails/matchers/have_http_status.rb +34 -13
  67. data/lib/rspec/rails/matchers/have_rendered.rb +2 -1
  68. data/lib/rspec/rails/matchers/redirect_to.rb +1 -1
  69. data/lib/rspec/rails/matchers/routing_matchers.rb +14 -14
  70. data/lib/rspec/rails/matchers.rb +11 -0
  71. data/lib/rspec/rails/tasks/rspec.rake +7 -17
  72. data/lib/rspec/rails/vendor/capybara.rb +10 -15
  73. data/lib/rspec/rails/version.rb +1 -1
  74. data/lib/rspec/rails/view_path_builder.rb +1 -1
  75. data/lib/rspec/rails/view_rendering.rb +16 -5
  76. data/lib/rspec/rails.rb +1 -0
  77. data/lib/rspec-rails.rb +13 -10
  78. data.tar.gz.sig +0 -0
  79. metadata +55 -33
  80. metadata.gz.sig +0 -0
  81. data/lib/generators/rspec/observer/observer_generator.rb +0 -13
data/README.md CHANGED
@@ -1,600 +1,369 @@
1
- # rspec-rails [![Build Status](https://secure.travis-ci.org/rspec/rspec-rails.svg?branch=master)](http://travis-ci.org/rspec/rspec-rails) [![Code Climate](https://img.shields.io/codeclimate/github/rspec/rspec-rails.svg)](https://codeclimate.com/github/rspec/rspec-rails)
2
- **rspec-rails** is a testing framework for Rails 3.x, 4.x and 5.0.
1
+ # rspec-rails [![Build Status][]][travis-ci] [![Code Climate][]][code-climate] [![Gem Version][]](gem-version)
3
2
 
4
- Use **[rspec-rails 1.x](http://github.com/dchelimsky/rspec-rails)** for Rails
5
- 2.x.
3
+ `rspec-rails` brings the [RSpec][] testing framework to [Ruby on Rails][]
4
+ as a drop-in alternative to its default testing framework, Minitest.
6
5
 
7
- ## Installation
6
+ In RSpec, tests are not just scripts that verify your application code.
7
+ They’re also specifications (or _specs,_ for short):
8
+ detailed explanations of how the application is supposed to behave,
9
+ expressed in plain English.
8
10
 
9
- Add `rspec-rails` to **both** the `:development` and `:test` groups in the
10
- `Gemfile`:
11
+ Use **[`rspec-rails` 1.x][]** for Rails 2.x.
11
12
 
12
- ```ruby
13
- group :development, :test do
14
- gem 'rspec-rails', '~> 3.6'
15
- end
16
- ```
13
+ [Build Status]: https://secure.travis-ci.org/rspec/rspec-rails.svg?branch=master
14
+ [travis-ci]: https://travis-ci.org/rspec/rspec-rails
15
+ [Code Climate]: https://codeclimate.com/github/rspec/rspec-rails.svg
16
+ [code-climate]: https://codeclimate.com/github/rspec/rspec-rails
17
+ [Gem Version]: https://badge.fury.io/rb/rspec-rails.svg
18
+ [gem-version]: https://badge.fury.io/rb/rspec-rails
19
+ [RSpec]: https://rspec.info/
20
+ [Ruby on Rails]: https://rubyonrails.org/
21
+ [`rspec-rails` 1.x]: https://github.com/dchelimsky/rspec-rails
17
22
 
18
- Want to run against the `master` branch? You'll need to include the dependent
19
- RSpec repos as well. Add the following to your `Gemfile`:
23
+ ## Installation
20
24
 
21
- ```ruby
22
- %w[rspec-core rspec-expectations rspec-mocks rspec-rails rspec-support].each do |lib|
23
- gem lib, :git => "https://github.com/rspec/#{lib}.git", :branch => 'master'
24
- end
25
- ```
25
+ 1. Add `rspec-rails` to **both** the `:development` and `:test` groups
26
+ of your app’s `Gemfile`:
26
27
 
27
- Download and install by running:
28
+ ```ruby
29
+ # Run against the latest stable release
30
+ group :development, :test do
31
+ gem 'rspec-rails', '~> 4.0'
32
+ end
28
33
 
29
- ```
30
- bundle install
31
- ```
34
+ # Or, run against the master branch
35
+ # (requires master-branch versions of all related RSpec libraries)
36
+ group :development, :test do
37
+ %w[rspec-core rspec-expectations rspec-mocks rspec-rails rspec-support].each do |lib|
38
+ gem lib, git: "https://github.com/rspec/#{lib}.git", branch: 'master'
39
+ end
40
+ end
41
+ ```
32
42
 
33
- Initialize the `spec/` directory (where specs will reside) with:
43
+ (Adding it to the `:development` group is not strictly necessary,
44
+ but without it, generators and rake tasks must be preceded by `RAILS_ENV=test`.)
34
45
 
35
- ```
36
- rails generate rspec:install
37
- ```
46
+ 2. Then, in your project directory:
38
47
 
39
- This adds the following files which are used for configuration:
48
+ ```sh
49
+ # Download and install
50
+ $ bundle install
40
51
 
41
- - `.rspec`
42
- - `spec/spec_helper.rb`
43
- - `spec/rails_helper.rb`
52
+ # Generate boilerplate configuration files
53
+ # (check the comments in each generated file for more information)
54
+ $ rails generate rspec:install
55
+ create .rspec
56
+ create spec
57
+ create spec/spec_helper.rb
58
+ create spec/rails_helper.rb
59
+ ```
44
60
 
45
- Check the comments in each file for more information.
61
+ ## Upgrading
46
62
 
47
- Use the `rspec` command to run your specs:
63
+ If your project is already using an older version of `rspec-rails`,
64
+ upgrade to the latest version with:
48
65
 
49
- ```
50
- bundle exec rspec
66
+ ```sh
67
+ $ bundle update rspec-rails
51
68
  ```
52
69
 
53
- By default the above will run all `_spec.rb` files in the `spec` directory. For
54
- more details about this see the [RSpec spec file
55
- docs](https://www.relishapp.com/rspec/rspec-core/docs/spec-files).
70
+ RSpec follows [semantic versioning](https://semver.org/),
71
+ which means that “major version” upgrades (_e.g.,_ 2.x → 3.x)
72
+ come with **breaking changes**.
73
+ If you’re upgrading from version 2.x or below,
74
+ read the [`rspec-rails` upgrade notes][] to find out what to watch out for.
56
75
 
57
- To run only a subset of these specs use the following command:
76
+ Be sure to check the general [RSpec upgrade notes][] as well.
58
77
 
59
- ```
60
- # Run only model specs
61
- bundle exec rspec spec/models
78
+ [`rspec-rails` upgrade notes]: https://www.relishapp.com/rspec/rspec-rails/docs/upgrade
79
+ [RSpec upgrade notes]: https://relishapp.com/rspec/docs/upgrade
62
80
 
63
- # Run only specs for AccountsController
64
- bundle exec rspec spec/controllers/accounts_controller_spec.rb
81
+ ## Usage
65
82
 
66
- # Run only spec on line 8 of AccountsController
67
- bundle exec rspec spec/controllers/accounts_controller_spec.rb:8
68
- ```
83
+ ### Creating boilerplate specs with `rails generate`
69
84
 
70
- Specs can also be run via `rake spec`, though this command may be slower to
71
- start than the `rspec` command.
85
+ ```sh
86
+ # RSpec hooks into built-in generators
87
+ $ rails generate model user
88
+ invoke active_record
89
+ create db/migrate/20181017040312_create_users.rb
90
+ create app/models/user.rb
91
+ invoke rspec
92
+ create spec/models/user_spec.rb
72
93
 
73
- In Rails 4, you may want to create a binstub for the `rspec` command so it can
74
- be run via `bin/rspec`:
94
+ # RSpec also provides its own spec file generators
95
+ $ rails generate rspec:model user
96
+ create spec/models/user_spec.rb
75
97
 
98
+ # List all RSpec generators
99
+ $ rails generate --help | grep rspec
76
100
  ```
77
- bundle binstubs rspec-core
78
- ```
79
-
80
- ### Upgrade Note
81
-
82
- For detailed information on the general RSpec 3.x upgrade process see the
83
- [RSpec Upgrade docs](https://relishapp.com/rspec/docs/upgrade).
84
-
85
- There are three particular `rspec-rails` specific changes to be aware of:
86
-
87
- 1. [The default helper files created in RSpec 3.x have changed](https://www.relishapp.com/rspec/rspec-rails/docs/upgrade#default-helper-files)
88
- 2. [File-type inference disabled by default](https://www.relishapp.com/rspec/rspec-rails/docs/upgrade#file-type-inference-disabled)
89
- 3. [Rails 4.x `ActiveRecord::Migration` pending migration checks](https://www.relishapp.com/rspec/rspec-rails/docs/upgrade#pending-migration-checks)
90
- 4. Extraction of `stub_model` and `mock_model` to
91
- [`rspec-activemodel-mocks`](https://github.com/rspec/rspec-activemodel-mocks)
92
- 5. In Rails 5.x, controller testing has been moved to its own gem which is [rails-controller-testing](https://github.com/rails/rails-controller-testing). Using `assigns` in your controller specs without adding this gem will no longer work.
93
- 6. `rspec-rails` now includes two helpers, `spec_helper.rb` and `rails_helper.rb`.
94
- `spec_helper.rb` is the conventional RSpec configuration helper, whilst the
95
- Rails specific loading and bootstrapping has moved to the `rails_helper.rb`
96
- file. Rails specs now need this file required beforehand either at the top
97
- of the specific file (recommended) or a common configuration location such
98
- as your `.rspec` file.
99
101
 
100
- Please see the [RSpec Rails Upgrade
101
- docs](https://www.relishapp.com/rspec/rspec-rails/docs/upgrade) for full
102
- details.
102
+ ### Running specs
103
103
 
104
- **NOTE:** Generators run in RSpec 3.x will now require `rails_helper` instead
105
- of `spec_helper`.
104
+ ```sh
105
+ # Default: Run all spec files (i.e., those matching spec/**/*_spec.rb)
106
+ $ bundle exec rspec
106
107
 
107
- ### Generators
108
+ # Run all spec files in a single directory (recursively)
109
+ $ bundle exec rspec spec/models
108
110
 
109
- Once installed, RSpec will generate spec files instead of Test::Unit test files
110
- when commands like `rails generate model` and `rails generate controller` are
111
- used.
111
+ # Run a single spec file
112
+ $ bundle exec rspec spec/controllers/accounts_controller_spec.rb
112
113
 
113
- You may also invoke RSpec generators independently. For instance,
114
- running `rails generate rspec:model` will generate a model spec. For more
115
- information, see [list of all
116
- generators](https://www.relishapp.com/rspec/rspec-rails/docs/generators).
114
+ # Run a single example from a spec file (by line number)
115
+ $ bundle exec rspec spec/controllers/accounts_controller_spec.rb:8
117
116
 
118
- ## Contributing
119
-
120
- Once you've set up the environment, you'll need to cd into the working
121
- directory of whichever repo you want to work in. From there you can run the
122
- specs and cucumber features, and make patches.
123
-
124
- NOTE: You do not need to use rspec-dev to work on a specific RSpec repo. You
125
- can treat each RSpec repo as an independent project.
126
- Please see the following files:
127
-
128
- For `rspec-rails`-specific development information, see
129
-
130
- - [Build details](BUILD_DETAIL.md)
131
- - [Code of Conduct](CODE_OF_CONDUCT.md)
132
- - [Detailed contributing guide](CONTRIBUTING.md)
133
- - [Development setup guide](DEVELOPMENT.md)
134
-
135
-
136
- ## Model Specs
137
-
138
- Use model specs to describe behavior of models (usually ActiveRecord-based) in
139
- the application.
140
-
141
- Model specs default to residing in the `spec/models` folder. Tagging any
142
- context with the metadata `:type => :model` treats its examples as model
143
- specs.
144
-
145
- For example:
146
-
147
- ```ruby
148
- require "rails_helper"
149
-
150
- RSpec.describe User, :type => :model do
151
- it "orders by last name" do
152
- lindeman = User.create!(first_name: "Andy", last_name: "Lindeman")
153
- chelimsky = User.create!(first_name: "David", last_name: "Chelimsky")
154
-
155
- expect(User.ordered_by_last_name).to eq([chelimsky, lindeman])
156
- end
157
- end
117
+ # See all options for running specs
118
+ $ bundle exec rspec --help
158
119
  ```
159
120
 
160
- For more information, see [cucumber scenarios for model
161
- specs](https://www.relishapp.com/rspec/rspec-rails/docs/model-specs).
121
+ **Optional:** If `bundle exec rspec` is too verbose for you,
122
+ you can generate a binstub at `bin/rspec` and use that instead:
162
123
 
163
- ## Request Specs
124
+ ```sh
125
+ $ bundle binstubs rspec-core
126
+ ```
164
127
 
165
- Use request specs to describe the client-facing behavior of the application —
166
- specifically, the HTTP response to be issued for a given request (a.k.a.
167
- integration tests). Since such client-facing behavior encompasses controller
168
- actions, this is the type of spec to use for controller testing.
128
+ ## RSpec DSL Basics (or, how do I write a spec?)
169
129
 
170
- Request specs default to residing in the `spec/requests`, `spec/api`, and
171
- `spec/integration` directories. Tagging any context with the metadata `:type =>
172
- :request` treats its examples as request specs.
173
-
174
- Request specs mix in behavior from
175
- [ActionDispatch::Integration::Runner](http://api.rubyonrails.org/classes/ActionDispatch/Integration/Runner.html),
176
- which is the basis for [Rails' integration
177
- tests](http://guides.rubyonrails.org/testing.html#integration-testing).
130
+ In RSpec, application behavior is described
131
+ **first in (almost) plain English, then again in test code**, like so:
178
132
 
179
133
  ```ruby
180
- require 'rails_helper'
181
-
182
- RSpec.describe "home page", :type => :request do
183
- it "displays the user's username after successful login" do
184
- user = User.create!(:username => "jdoe", :password => "secret")
185
- get "/login"
186
- assert_select "form.login" do
187
- assert_select "input[name=?]", "username"
188
- assert_select "input[name=?]", "password"
189
- assert_select "input[type=?]", "submit"
134
+ RSpec.describe 'Post' do #
135
+ context 'before publication' do # (almost) plain English
136
+ it 'cannot have comments' do #
137
+ expect { Post.create.comments.create! }.to raise_error(ActiveRecord::RecordInvalid) # test code
190
138
  end
191
-
192
- post "/login", :username => "jdoe", :password => "secret"
193
- assert_select ".header .username", :text => "jdoe"
194
139
  end
195
140
  end
196
141
  ```
197
142
 
198
- The above example uses only standard Rails and RSpec APIs, but many
199
- RSpec/Rails users like to use extension libraries like
200
- [FactoryGirl](https://github.com/thoughtbot/factory_girl) and
201
- [Capybara](https://github.com/jnicklas/capybara):
202
-
203
- ```ruby
204
- require 'rails_helper'
205
-
206
- RSpec.describe "home page", :type => :request do
207
- it "displays the user's username after successful login" do
208
- user = FactoryGirl.create(:user, :username => "jdoe", :password => "secret")
209
- visit "/login"
210
- fill_in "Username", :with => "jdoe"
211
- fill_in "Password", :with => "secret"
212
- click_button "Log in"
143
+ Running `rspec` will execute this test code,
144
+ and then use the plain-English descriptions
145
+ to generate a report of where the application
146
+ conforms to (or fails to meet) the spec:
213
147
 
214
- expect(page).to have_selector(".header .username", :text => "jdoe")
215
- end
216
- end
217
148
  ```
149
+ $ rspec --format documentation spec/models/post_spec.rb
218
150
 
219
- FactoryGirl decouples this example from changes to validation requirements,
220
- which can be encoded into the underlying factory definition without requiring
221
- changes to this example.
222
-
223
- Among other benefits, Capybara binds the form post to the generated HTML, which
224
- means we don't need to specify them separately. Note that Capybara's DSL as
225
- shown is, by default, only available in specs in the spec/features directory.
226
- For more information, see the [Capybara integration
227
- docs](http://rubydoc.info/gems/rspec-rails/file/Capybara.md).
228
-
229
- There are several other Ruby libs that implement the factory pattern or provide
230
- a DSL for request specs (a.k.a. acceptance or integration specs), but
231
- FactoryGirl and Capybara seem to be the most widely used. Whether you choose
232
- these or other libs, we strongly recommend using something for each of these
233
- roles.
234
-
235
- For more information, see [cucumber scenarios for request
236
- specs](https://relishapp.com/rspec/rspec-rails/docs/request-specs/request-spec).
151
+ Post
152
+ before publication
153
+ cannot have comments
237
154
 
238
- ## Controller Specs
155
+ Failures:
239
156
 
240
- Controller specs can be used to describe the behavior of Rails controllers. As
241
- of version 3.5, however, controller specs are discouraged in favor of request
242
- specs (which also focus largely on controllers, but capture other critical
243
- aspects of application behavior as well). Controller specs will continue to be
244
- supported until at least version 4.0 (see the [release
245
- notes](http://rspec.info/blog/2016/07/rspec-3-5-has-been-released/#rails-support-for-rails-5)
246
- for details).
157
+ 1) Post before publication cannot have comments
158
+ Failure/Error: expect { Post.create.comments.create! }.to raise_error(ActiveRecord::RecordInvalid)
159
+ expected ActiveRecord::RecordInvalid but nothing was raised
160
+ # ./spec/models/post.rb:4:in `block (3 levels) in <top (required)>'
247
161
 
248
- For more information, see [cucumber scenarios for controller
249
- specs](https://www.relishapp.com/rspec/rspec-rails/docs/controller-specs).
162
+ Finished in 0.00527 seconds (files took 0.29657 seconds to load)
163
+ 1 example, 1 failure
250
164
 
251
- ## Feature Specs
165
+ Failed examples:
252
166
 
253
- Feature specs test your application from the outside by simulating a browser.
254
- [`capybara`](https://github.com/jnicklas/capybara) is used to manage the
255
- simulated browser.
256
-
257
- Feature specs default to residing in the `spec/features` folder. Tagging any
258
- context with the metadata `:type => :feature` treats its examples as feature
259
- specs.
260
-
261
- Feature specs mix in functionality from the capybara gem, thus they require
262
- `capybara` to use. To use feature specs, add `capybara` to the `Gemfile`:
263
-
264
- ```ruby
265
- gem "capybara"
167
+ rspec ./spec/models/post_spec.rb:3 # Post before publication cannot have comments
266
168
  ```
267
169
 
268
- For more information, see the [cucumber scenarios for feature
269
- specs](https://www.relishapp.com/rspec/rspec-rails/v/3-4/docs/feature-specs/feature-spec).
170
+ For an in-depth look at the RSpec DSL, including lots of examples,
171
+ read the official Cucumber documentation for [RSpec Core][].
270
172
 
271
- ## Mailer specs
173
+ [RSpec Core]: https://relishapp.com/rspec/rspec-core/docs
272
174
 
273
- By default Mailer specs reside in the `spec/mailers` folder. Adding the metadata
274
- `:type => :mailer` to any context makes its examples be treated as mailer specs.
175
+ ### Helpful Rails Matchers
275
176
 
276
- `ActionMailer::TestCase::Behavior` is mixed into your mailer specs.
177
+ In RSpec, assertions are called _expectations,_
178
+ and every expectation is built around a _matcher._
179
+ When you `expect(a).to eq(b)`, you’re using the `eq` matcher.
277
180
 
278
- ```ruby
279
- require "rails_helper"
181
+ In addition to [the matchers that come standard in RSpec][],
182
+ here are some extras that make it easier
183
+ to test the various parts of a Rails system:
280
184
 
281
- RSpec.describe Notifications, :type => :mailer do
282
- describe "notify" do
283
- let(:mail) { Notifications.signup }
185
+ | RSpec matcher | Delegates to | Available in | Notes |
186
+ | ------------------------ | ----------------- | ------------------------------- | -------------------------------------------------------- |
187
+ | [`be_a_new`][] | | all | primarily intended for controller specs |
188
+ | [`render_template`][] | `assert_template` | request / controller / view | use with `expect(response).to` |
189
+ | [`redirect_to`][] | `assert_redirect` | request / controller | use with `expect(response).to` |
190
+ | [`route_to`] | `assert_routing` | routing / controller | replaces `route_for` from version 1.x |
191
+ | [`be_routable`] | | routing / controller | usu. for `expect(...).not_to be_routable` |
192
+ | [`have_http_status`][] | | request / controller / feature | |
193
+ | [`match_array`][] | | all | for comparing arrays of ActiveRecord objects |
194
+ | [`have_been_enqueued`][] | | all | requires config: `ActiveJob::Base.queue_adapter = :test` |
195
+ | [`have_enqueued_job`][] | | all | requires config: `ActiveJob::Base.queue_adapter = :test` |
284
196
 
285
- it "renders the headers" do
286
- expect(mail.subject).to eq("Signup")
287
- expect(mail.to).to eq(["to@example.org"])
288
- expect(mail.from).to eq(["from@example.com"])
289
- end
197
+ Follow the links above for examples of how each matcher is used.
290
198
 
291
- it "renders the body" do
292
- expect(mail.body.encoded).to match("Hi")
293
- end
294
- end
295
- end
296
- ```
199
+ [the matchers that come standard in RSpec]: https://relishapp.com/rspec/rspec-expectations/docs/built-in-matchers
200
+ [`be_a_new`]: https://relishapp.com/rspec/rspec-rails/docs/matchers/be-a-new-matcher
201
+ [`render_template`]: https://relishapp.com/rspec/rspec-rails/docs/matchers/render-template-matcher
202
+ [`redirect_to`]: https://relishapp.com/rspec/rspec-rails/docs/matchers/redirect-to-matcher
203
+ [`route_to`]: https://relishapp.com/rspec/rspec-rails/docs/routing-specs/route-to-matcher
204
+ [`be_routable`]: https://relishapp.com/rspec/rspec-rails/docs/routing-specs/be-routable-matcher
205
+ [`have_http_status`]: https://relishapp.com/rspec/rspec-rails/docs/matchers/have-http-status-matcher
206
+ [`match_array`]: https://relishapp.com/rspec/rspec-rails/docs/matchers/activerecord-relation-match-array
207
+ [`have_been_enqueued`]: https://relishapp.com/rspec/rspec-rails/docs/matchers/have-been-enqueued-matcher
208
+ [`have_enqueued_job`]: https://relishapp.com/rspec/rspec-rails/docs/matchers/have-enqueued-job-matcher
297
209
 
298
- For more information, see the [cucumber scenarios for mailer specs
299
- ](https://relishapp.com/rspec/rspec-rails/v/3-4/docs/mailer-specs).
210
+ ### What else does RSpec Rails add?
300
211
 
301
- ## Job specs
212
+ For a comprehensive look at RSpec Rails’ features,
213
+ read the [official Cucumber documentation][].
302
214
 
303
- Tagging a context with the metadata `:type => :job` treats its examples as job
304
- specs. Typically these specs will live in `spec/jobs`.
215
+ [official Cucumber documentation]: https://relishapp.com/rspec/rspec-rails/docs
305
216
 
306
- ```ruby
307
- require 'rails_helper'
308
-
309
- RSpec.describe UploadBackupsJob, :type => :job do
310
- describe "#perform_later" do
311
- it "uploads a backup" do
312
- ActiveJob::Base.queue_adapter = :test
313
- UploadBackupsJob.perform_later('backup')
314
- expect(UploadBackupsJob).to have_been_enqueued
315
- end
316
- end
317
- end
318
- ```
217
+ ## What tests should I write?
319
218
 
320
- For more information, see the [cucumber scenarios for job specs
321
- ](https://relishapp.com/rspec/rspec-rails/docs/job-specs).
219
+ RSpec Rails defines ten different _types_ of specs
220
+ for testing different parts of a typical Rails application.
221
+ Each one inherits from one of Rails’ built-in `TestCase` classes,
222
+ meaning the helper methods provided by default in Rails tests
223
+ are available in RSpec, as well.
322
224
 
323
- ## View specs
225
+ | Spec type | Corresponding Rails test class |
226
+ | -------------- | -------------------------------- |
227
+ | [model][] | |
228
+ | [controller][] | [`ActionController::TestCase`][] |
229
+ | [mailer][] | `ActionMailer::TestCase` |
230
+ | [job][] | |
231
+ | [view][] | `ActionView::TestCase` |
232
+ | [routing][] | |
233
+ | [helper][] | `ActionView::TestCase` |
234
+ | [request][] | [`ActionDispatch::IntegrationTest`][] |
235
+ | [feature][] | |
236
+ | [system][] | [`ActionDispatch::SystemTestCase`][] |
324
237
 
325
- View specs default to residing in the `spec/views` folder. Tagging any context
326
- with the metadata `:type => :view` treats its examples as view specs.
238
+ Follow the links above to see examples of each spec type,
239
+ or for official Rails API documentation on the given `TestCase` class.
327
240
 
328
- View specs mix in `ActionView::TestCase::Behavior`.
241
+ > **Note: This is not a checklist.**
242
+ >
243
+ > Ask a hundred developers how to test an application,
244
+ > and you’ll get a hundred different answers.
245
+ >
246
+ > RSpec Rails provides thoughtfully selected features
247
+ > to encourage good testing practices, but there’s no “right” way to do it.
248
+ > Ultimately, it’s up to you to decide how your test suite will be composed.
249
+
250
+ When creating a spec file,
251
+ assign it a type in the top-level `describe` block, like so:
329
252
 
330
253
  ```ruby
331
- require 'rails_helper'
254
+ # spec/models/user_spec.rb
332
255
 
333
- RSpec.describe "events/index", :type => :view do
334
- it "renders _event partial for each event" do
335
- assign(:events, [double(Event), double(Event)])
336
- render
337
- expect(view).to render_template(:partial => "_event", :count => 2)
338
- end
339
- end
340
-
341
- RSpec.describe "events/show", :type => :view do
342
- it "displays the event location" do
343
- assign(:event, Event.new(:location => "Chicago"))
344
- render
345
- expect(rendered).to include("Chicago")
346
- end
347
- end
256
+ RSpec.describe User, type: :model do
257
+ ...
348
258
  ```
349
259
 
350
- View specs infer the controller name and path from the path to the view
351
- template. e.g. if the template is `events/index.html.erb` then:
260
+ [request]: https://relishapp.com/rspec/rspec-rails/docs/request-specs/request-spec
261
+ [feature]: https://www.relishapp.com/rspec/rspec-rails/docs/feature-specs/feature-spec
262
+ [system]: https://relishapp.com/rspec/rspec-rails/docs/system-specs/system-spec
263
+ [model]: https://www.relishapp.com/rspec/rspec-rails/docs/model-specs
264
+ [controller]: https://www.relishapp.com/rspec/rspec-rails/docs/controller-specs
265
+ [mailer]: https://relishapp.com/rspec/rspec-rails/docs/mailer-specs
266
+ [job]: https://relishapp.com/rspec/rspec-rails/docs/job-specs/job-spec
267
+ [view]: https://www.relishapp.com/rspec/rspec-rails/docs/view-specs/view-spec
268
+ [routing]: https://www.relishapp.com/rspec/rspec-rails/docs/routing-specs
269
+ [helper]: https://www.relishapp.com/rspec/rspec-rails/docs/helper-specs/helper-spec
270
+ [`ActionDispatch::IntegrationTest`]: https://api.rubyonrails.org/classes/ActionDispatch/IntegrationTest.html
271
+ [`ActionDispatch::SystemTestCase`]: https://api.rubyonrails.org/classes/ActionDispatch/SystemTestCase.html
272
+ [`ActionController::TestCase`]: https://api.rubyonrails.org/classes/ActionController/TestCase.html
273
+ [in the appropriate folder]: https://relishapp.com/rspec/rspec-rails/docs/directory-structure
352
274
 
353
- ```ruby
354
- controller.controller_path == "events"
355
- controller.request.path_parameters[:controller] == "events"
356
- ```
275
+ ### System specs, feature specs, request specs–what’s the difference?
357
276
 
358
- This means that most of the time you don't need to set these values. When
359
- spec'ing a partial that is included across different controllers, you _may_
360
- need to override these values before rendering the view.
277
+ RSpec Rails provides some end-to-end (entire application) testing capability
278
+ to specify the interaction with the client.
361
279
 
362
- To provide a layout for the render, you'll need to specify _both_ the template
363
- and the layout explicitly. For example:
280
+ #### System specs
364
281
 
365
- ```ruby
366
- render :template => "events/show", :layout => "layouts/application"
367
- ```
282
+ Also called **acceptance tests**, **browser tests**, or **end-to-end tests**,
283
+ system specs test the application from the perspective of a _human client._
284
+ The test code walks through a user’s browser interactions,
368
285
 
369
- ### `assign(key, val)`
286
+ * `visit '/login'`
287
+ * `fill_in 'Name', with: 'jdoe'`
370
288
 
371
- Use this to assign values to instance variables in the view:
289
+ and the expectations revolve around page content.
372
290
 
373
- ```ruby
374
- assign(:widget, Widget.new)
375
- render
376
- ```
291
+ * `expect(page).to have_text('Welcome')`
377
292
 
378
- The code above assigns `Widget.new` to the `@widget` variable in the view, and
379
- then renders the view.
293
+ Because system specs are a wrapper around Rails’ built-in `SystemTestCase`,
294
+ they’re only available on Rails 5.1+.
295
+ (Feature specs serve the same purpose, but without this dependency.)
380
296
 
381
- Note that because view specs mix in `ActionView::TestCase` behavior, any
382
- instance variables you set will be transparently propagated into your views
383
- (similar to how instance variables you set in controller actions are made
384
- available in views). For example:
297
+ #### Feature specs
385
298
 
386
- ```ruby
387
- @widget = Widget.new
388
- render # @widget is available inside the view
389
- ```
299
+ Before Rails introduced system testing facilities,
300
+ feature specs were the only spec type for end-to-end testing.
301
+ While the RSpec team now [officially recommends system specs][] instead,
302
+ feature specs are still fully supported, look basically identical,
303
+ and work on older versions of Rails.
390
304
 
391
- RSpec doesn't officially support this pattern, which only works as a
392
- side-effect of the inclusion of `ActionView::TestCase`. Be aware that it may be
393
- made unavailable in the future.
305
+ On the other hand, feature specs require non-trivial configuration
306
+ to get some important features working,
307
+ like JavaScript testing or making sure each test runs with a fresh DB state.
308
+ With system specs, this configuration is provided out-of-the-box.
394
309
 
395
- #### Upgrade note
310
+ Like system specs, feature specs require the [Capybara][] gem.
311
+ Rails 5.1+ includes it by default as part of system tests,
312
+ but if you don’t have the luxury of upgrading,
313
+ be sure to add it to the `:test` group of your `Gemfile` first:
396
314
 
397
315
  ```ruby
398
- # rspec-rails-1.x
399
- assigns[key] = value
400
-
401
- # rspec-rails-2.x+
402
- assign(key, value)
403
- ```
404
-
405
- ### `rendered`
406
-
407
- This represents the rendered view.
408
-
409
- ```ruby
410
- render
411
- expect(rendered).to match /Some text expected to appear on the page/
412
- ```
413
-
414
- #### Upgrade note
415
-
416
- ```ruby
417
- # rspec-rails-1.x
418
- render
419
- response.should xxx
420
-
421
- # rspec-rails-2.x+
422
- render
423
- rendered.should xxx
424
-
425
- # rspec-rails-2.x+ with expect syntax
426
- render
427
- expect(rendered).to xxx
428
- ```
429
-
430
- ## Routing specs
431
-
432
- Routing specs default to residing in the `spec/routing` folder. Tagging any
433
- context with the metadata `:type => :routing` treats its examples as routing
434
- specs.
435
-
436
- ```ruby
437
- require 'rails_helper'
438
-
439
- RSpec.describe "routing to profiles", :type => :routing do
440
- it "routes /profile/:username to profile#show for username" do
441
- expect(:get => "/profiles/jsmith").to route_to(
442
- :controller => "profiles",
443
- :action => "show",
444
- :username => "jsmith"
445
- )
446
- end
447
-
448
- it "does not expose a list of profiles" do
449
- expect(:get => "/profiles").not_to be_routable
450
- end
316
+ group :test do
317
+ gem "capybara"
451
318
  end
452
319
  ```
453
320
 
454
- ### Upgrade note
455
-
456
- `route_for` from rspec-rails-1.x is gone. Use `route_to` and `be_routable`
457
- instead.
458
-
459
- ## Helper specs
460
-
461
- Helper specs default to residing in the `spec/helpers` folder. Tagging any
462
- context with the metadata `:type => :helper` treats its examples as helper
463
- specs.
464
-
465
- Helper specs mix in ActionView::TestCase::Behavior. A `helper` object is
466
- provided which mixes in the helper module being spec'd, along with
467
- `ApplicationHelper` (if present).
468
-
469
- ```ruby
470
- require 'rails_helper'
471
-
472
- RSpec.describe EventsHelper, :type => :helper do
473
- describe "#link_to_event" do
474
- it "displays the title, and formatted date" do
475
- event = Event.new("Ruby Kaigi", Date.new(2010, 8, 27))
476
- # helper is an instance of ActionView::Base configured with the
477
- # EventsHelper and all of Rails' built-in helpers
478
- expect(helper.link_to_event).to match /Ruby Kaigi, 27 Aug, 2010/
479
- end
480
- end
481
- end
482
- ```
483
-
484
- ## Matchers
485
-
486
- Several domain-specific matchers are provided to each of the example group
487
- types. Most simply delegate to their equivalent Rails' assertions.
488
-
489
- ### `be_a_new`
490
-
491
- - Available in all specs
492
- - Primarily intended for controller specs
493
-
494
- ```ruby
495
- expect(object).to be_a_new(Widget)
496
- ```
497
-
498
- Passes if the object is a `Widget` and returns true for `new_record?`
321
+ [officially recommends system specs]: https://rspec.info/blog/2017/10/rspec-3-7-has-been-released/#rails-actiondispatchsystemtest-integration-system-specs
322
+ [Capybara]: https://github.com/teamcapybara/capybara
499
323
 
500
- ### `render_template`
324
+ #### Request specs
501
325
 
502
- - Delegates to Rails' `assert_template`
503
- - Available in request, controller, and view specs
326
+ Request specs are for testing the application
327
+ from the perspective of a _machine client._
328
+ They begin with an HTTP request and end with the HTTP response,
329
+ so they’re faster than feature specs,
330
+ but do not examine your app’s UI or JavaScript.
504
331
 
505
- In request and controller specs, apply to the `response` object:
332
+ Request specs provide a high-level alternative to controller specs.
333
+ In fact, as of RSpec 3.5, both the Rails and RSpec teams
334
+ [discourage directly testing controllers][]
335
+ in favor of functional tests like request specs.
506
336
 
507
- ```ruby
508
- expect(response).to render_template("new")
509
- ```
510
-
511
- In view specs, apply to the `view` object:
512
-
513
- ```ruby
514
- expect(view).to render_template(:partial => "_form", :locals => { :widget => widget } )
515
- ```
516
-
517
- ### `redirect_to`
518
-
519
- - Delegates to `assert_redirect`
520
- - Available in request and controller specs
521
-
522
- ```ruby
523
- expect(response).to redirect_to(widgets_path)
524
- ```
525
-
526
- ### `route_to`
527
-
528
- - Delegates to Rails' `assert_routing`
529
- - Available in routing and controller specs
530
-
531
- ```ruby
532
- expect(:get => "/widgets").to route_to(:controller => "widgets", :action => "index")
533
- ```
534
-
535
- ### `be_routable`
536
-
537
- Passes if the path is recognized by Rails' routing. This is primarily intended
538
- to be used with `not_to` to specify standard CRUD routes which should not be
539
- routable.
540
-
541
- ```ruby
542
- expect(:get => "/widgets/1/edit").not_to be_routable
543
- ```
544
-
545
- ### `have_http_status`
546
-
547
- - Passes if `response` has a matching HTTP status code
548
- - The following symbolic status codes are allowed:
549
- - `Rack::Utils::SYMBOL_TO_STATUS_CODE`
550
- - One of the defined `ActionDispatch::TestResponse` aliases:
551
- - `:error`
552
- - `:missing`
553
- - `:redirect`
554
- - `:success`
555
- - Available in controller, feature, and request specs.
556
-
557
- In controller and request specs, apply to the `response` object:
337
+ When writing them, try to answer the question,
338
+ “For a given HTTP request (verb + path + parameters),
339
+ what HTTP response should the application return?”
558
340
 
559
- ```ruby
560
- expect(response).to have_http_status(201)
561
- expect(response).not_to have_http_status(:created)
562
- ```
563
-
564
- In feature specs, apply to the `page` object:
341
+ [discourage directly testing controllers]: https://rspec.info/blog/2016/07/rspec-3-5-has-been-released/#rails-support-for-rails-5
565
342
 
566
- ```ruby
567
- expect(page).to have_http_status(:success)
568
- ```
569
-
570
- ## `rake` tasks
571
-
572
- Several rake tasks are provided as a convenience for working with RSpec. To run
573
- the entire spec suite use `rake spec`. To run a subset of specs use the
574
- associated type task, for example `rake spec:models`.
575
-
576
- A full list of the available rake tasks can be seen by running `rake -T | grep
577
- spec`.
343
+ ## Contributing
578
344
 
579
- ### Customizing `rake` tasks
345
+ - [Build details](BUILD_DETAIL.md)
346
+ - [Code of Conduct](CODE_OF_CONDUCT.md)
347
+ - [Detailed contributing guide](CONTRIBUTING.md)
580
348
 
581
- If you want to customize the behavior of `rake spec`, you may [define your own
582
- task in the `Rakefile` for your
583
- project](https://www.relishapp.com/rspec/rspec-core/docs/command-line/rake-task).
584
- However, you must first clear the task that rspec-rails defined:
349
+ Once you’ve cloned the repo and [set up the environment](DEVELOPMENT.md),
350
+ you can run the specs and Cucumber features, or submit a pull request.
585
351
 
586
- ```ruby
587
- task("spec").clear
588
- ```
352
+ ## See Also
589
353
 
354
+ ### RSpec base libraries
590
355
 
591
- ## Also see
356
+ * <https://github.com/rspec/rspec>
357
+ * <https://github.com/rspec/rspec-core>
358
+ * <https://github.com/rspec/rspec-expectations>
359
+ * <https://github.com/rspec/rspec-mocks>
592
360
 
593
- * [https://github.com/rspec/rspec](https://github.com/rspec/rspec)
594
- * [https://github.com/rspec/rspec-core](https://github.com/rspec/rspec-core)
595
- * [https://github.com/rspec/rspec-expectations](https://github.com/rspec/rspec-expectations)
596
- * [https://github.com/rspec/rspec-mocks](https://github.com/rspec/rspec-mocks)
361
+ ### Recommended third-party extensions
597
362
 
598
- ## Feature Requests & Bugs
363
+ * [FactoryBot](https://github.com/thoughtbot/factory_bot)
364
+ * [Capybara](https://github.com/teamcapybara/capybara)
365
+ (Included by default in Rails 5.1+.
366
+ Note that [additional configuration is required][] to use the Capybara DSL
367
+ anywhere other than system specs and feature specs.)
599
368
 
600
- See <http://github.com/rspec/rspec-rails/issues>
369
+ [additional configuration is required]: https://rubydoc.info/gems/rspec-rails/file/Capybara.md