Skip to content

Commit 9eb8d2a

Browse files
JonRoweklyonrad
andcommitted
Add request spec templates for scaffold and make default
Co-authored-by: Luka Lüdicke <[email protected]>
1 parent 1f00752 commit 9eb8d2a

File tree

4 files changed

+332
-7
lines changed

4 files changed

+332
-7
lines changed

lib/generators/rspec/scaffold/scaffold_generator.rb

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ class ScaffoldGenerator < Base
1414
class_option :singleton, type: :boolean, desc: "Supply to create a singleton controller"
1515
class_option :api, type: :boolean, desc: "Skip specs unnecessary for API-only apps"
1616

17-
class_option :controller_specs, type: :boolean, default: true, desc: "Generate controller specs"
17+
class_option :controller_specs, type: :boolean, default: false, desc: "Generate controller specs"
18+
class_option :request_specs, type: :boolean, default: true, desc: "Generate request specs"
1819
class_option :view_specs, type: :boolean, default: true, desc: "Generate view specs"
1920
class_option :helper_specs, type: :boolean, default: true, desc: "Generate helper specs"
2021
class_option :routing_specs, type: :boolean, default: true, desc: "Generate routing specs"
@@ -39,6 +40,21 @@ def generate_controller_spec
3940
end
4041
end
4142

43+
def generate_request_spec
44+
return unless options[:request_specs]
45+
46+
template_file = File.join(
47+
'spec/requests',
48+
controller_class_path,
49+
"#{controller_file_name}_spec.rb"
50+
)
51+
if options[:api]
52+
template 'api_request_spec.rb', template_file
53+
else
54+
template 'request_spec.rb', template_file
55+
end
56+
end
57+
4258
def generate_view_specs
4359
return if options[:api]
4460
return unless options[:view_specs] && options[:template_engine]
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
require 'rails_helper'
2+
3+
# This spec was generated by rspec-rails when you ran the scaffold generator.
4+
# It demonstrates how one might use RSpec to test the controller code that
5+
# was generated by Rails when you ran the scaffold generator.
6+
#
7+
# It assumes that the implementation code is generated by the rails scaffold
8+
# generator. If you are using any extension libraries to generate different
9+
# controller code, this generated spec may or may not pass.
10+
#
11+
# It only uses APIs available in rails and/or rspec-rails. There are a number
12+
# of tools you can use to make these specs even more expressive, but we're
13+
# sticking to rails and rspec-rails APIs to keep things simple and stable.
14+
15+
<% module_namespacing do -%>
16+
RSpec.describe "/<%= name.underscore.pluralize %>", <%= type_metatag(:request) %> do
17+
# This should return the minimal set of attributes required to create a valid
18+
# <%= class_name %>. As you add validations to <%= class_name %>, be sure to
19+
# adjust the attributes here as well.
20+
let(:valid_attributes) {
21+
skip("Add a hash of attributes valid for your model")
22+
}
23+
24+
let(:invalid_attributes) {
25+
skip("Add a hash of attributes invalid for your model")
26+
}
27+
28+
# This should return the minimal set of values that should be in the headers
29+
# in order to pass any filters (e.g. authentication) defined in
30+
# <%= controller_class_name %>Controller, or in your router and rack
31+
# middleware. Be sure to keep this updated too.
32+
let(:valid_headers) {
33+
{}
34+
}
35+
36+
<% unless options[:singleton] -%>
37+
describe "GET /index" do
38+
it "renders a successful response" do
39+
<%= class_name %>.create! valid_attributes
40+
get <%= index_helper %>_url, headers: valid_headers, as: :json
41+
expect(response).to be_successful
42+
end
43+
end
44+
<% end -%>
45+
46+
describe "GET /show" do
47+
it "renders a successful response" do
48+
<%= file_name %> = <%= class_name %>.create! valid_attributes
49+
get <%= show_helper.tr('@', '') %>, as: :json
50+
expect(response).to be_successful
51+
end
52+
end
53+
54+
describe "POST /create" do
55+
context "with valid parameters" do
56+
it "creates a new <%= class_name %>" do
57+
expect {
58+
post <%= index_helper %>_url,
59+
params: { <%= ns_file_name %>: valid_attributes }, headers: valid_headers, as: :json
60+
}.to change(<%= class_name %>, :count).by(1)
61+
end
62+
63+
it "renders a JSON response with the new <%= ns_file_name %>" do
64+
post <%= index_helper %>_url,
65+
params: { <%= ns_file_name %>: valid_attributes }, headers: valid_headers, as: :json
66+
expect(response).to have_http_status(:created)
67+
expect(response.content_type).to match(a_string_including("application/json"))
68+
end
69+
end
70+
71+
context "with invalid parameters" do
72+
it "does not create a new <%= class_name %>" do
73+
expect {
74+
post <%= index_helper %>_url,
75+
params: { <%= ns_file_name %>: invalid_attributes }, as: :json
76+
}.to change(<%= class_name %>, :count).by(0)
77+
end
78+
79+
it "renders a JSON response with errors for the new <%= ns_file_name %>" do
80+
post <%= index_helper %>_url,
81+
params: { <%= ns_file_name %>: invalid_attributes }, headers: valid_headers, as: :json
82+
expect(response).to have_http_status(:unprocessable_entity)
83+
expect(response.content_type).to eq("application/json")
84+
end
85+
end
86+
end
87+
88+
describe "PATCH /update" do
89+
context "with valid parameters" do
90+
let(:new_attributes) {
91+
skip("Add a hash of attributes valid for your model")
92+
}
93+
94+
it "updates the requested <%= ns_file_name %>" do
95+
<%= file_name %> = <%= class_name %>.create! valid_attributes
96+
patch <%= show_helper.tr('@', '') %>,
97+
params: { <%= singular_table_name %>: invalid_attributes }, headers: valid_headers, as: :json
98+
<%= file_name %>.reload
99+
skip("Add assertions for updated state")
100+
end
101+
102+
it "renders a JSON response with the <%= ns_file_name %>" do
103+
<%= file_name %> = <%= class_name %>.create! valid_attributes
104+
patch <%= show_helper.tr('@', '') %>,
105+
params: { <%= singular_table_name %>: invalid_attributes }, headers: valid_headers, as: :json
106+
expect(response).to have_http_status(:ok)
107+
expect(response.content_type).to eq("application/json")
108+
end
109+
end
110+
111+
context "with invalid parameters" do
112+
it "renders a JSON response with errors for the <%= ns_file_name %>" do
113+
<%= file_name %> = <%= class_name %>.create! valid_attributes
114+
patch <%= show_helper.tr('@', '') %>,
115+
params: { <%= singular_table_name %>: invalid_attributes }, headers: valid_headers, as: :json
116+
expect(response).to have_http_status(:unprocessable_entity)
117+
expect(response.content_type).to eq("application/json")
118+
end
119+
end
120+
end
121+
122+
describe "DELETE /destroy" do
123+
it "destroys the requested <%= ns_file_name %>" do
124+
<%= file_name %> = <%= class_name %>.create! valid_attributes
125+
expect {
126+
delete <%= show_helper.tr('@', '') %>, headers: valid_headers, as: :json
127+
}.to change(<%= class_name %>, :count).by(-1)
128+
end
129+
end
130+
end
131+
<% end -%>
Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
require 'rails_helper'
2+
3+
# This spec was generated by rspec-rails when you ran the scaffold generator.
4+
# It demonstrates how one might use RSpec to test the controller code that
5+
# was generated by Rails when you ran the scaffold generator.
6+
#
7+
# It assumes that the implementation code is generated by the rails scaffold
8+
# generator. If you are using any extension libraries to generate different
9+
# controller code, this generated spec may or may not pass.
10+
#
11+
# It only uses APIs available in rails and/or rspec-rails. There are a number
12+
# of tools you can use to make these specs even more expressive, but we're
13+
# sticking to rails and rspec-rails APIs to keep things simple and stable.
14+
15+
<% module_namespacing do -%>
16+
RSpec.describe "/<%= name.underscore.pluralize %>", <%= type_metatag(:request) %> do
17+
# <%= class_name %>. As you add validations to <%= class_name %>, be sure to
18+
# adjust the attributes here as well.
19+
let(:valid_attributes) {
20+
skip("Add a hash of attributes valid for your model")
21+
}
22+
23+
let(:invalid_attributes) {
24+
skip("Add a hash of attributes invalid for your model")
25+
}
26+
27+
<% unless options[:singleton] -%>
28+
describe "GET /index" do
29+
it "renders a successful response" do
30+
<%= class_name %>.create! valid_attributes
31+
get <%= index_helper %>_url
32+
expect(response).to be_successful
33+
end
34+
end
35+
<% end -%>
36+
37+
describe "GET /show" do
38+
it "renders a successful response" do
39+
<%= file_name %> = <%= class_name %>.create! valid_attributes
40+
get <%= show_helper.tr('@', '') %>
41+
expect(response).to be_successful
42+
end
43+
end
44+
45+
describe "GET /new" do
46+
it "renders a successful response" do
47+
get <%= new_helper %>
48+
expect(response).to be_successful
49+
end
50+
end
51+
52+
describe "GET /edit" do
53+
it "render a successful response" do
54+
<%= file_name %> = <%= class_name %>.create! valid_attributes
55+
get <%= edit_helper.tr('@','') %>
56+
expect(response).to be_successful
57+
end
58+
end
59+
60+
describe "POST /create" do
61+
context "with valid parameters" do
62+
it "creates a new <%= class_name %>" do
63+
expect {
64+
post <%= index_helper %>_url, params: { <%= ns_file_name %>: valid_attributes }
65+
}.to change(<%= class_name %>, :count).by(1)
66+
end
67+
68+
it "redirects to the created <%= ns_file_name %>" do
69+
post <%= index_helper %>_url, params: { <%= ns_file_name %>: valid_attributes }
70+
expect(response).to redirect_to(<%= show_helper.gsub("\@#{file_name}", class_name+".last") %>)
71+
end
72+
end
73+
74+
context "with invalid parameters" do
75+
it "does not create a new <%= class_name %>" do
76+
expect {
77+
post <%= index_helper %>_url, params: { <%= ns_file_name %>: invalid_attributes }
78+
}.to change(<%= class_name %>, :count).by(0)
79+
end
80+
81+
it "renders a successful response (i.e. to display the 'new' template)" do
82+
post <%= index_helper %>_url, params: { <%= ns_file_name %>: invalid_attributes }
83+
expect(response).to be_successful
84+
end
85+
end
86+
end
87+
88+
describe "PATCH /update" do
89+
context "with valid parameters" do
90+
let(:new_attributes) {
91+
skip("Add a hash of attributes valid for your model")
92+
}
93+
94+
it "updates the requested <%= ns_file_name %>" do
95+
<%= file_name %> = <%= class_name %>.create! valid_attributes
96+
patch <%= show_helper.tr('@', '') %>, params: { <%= singular_table_name %>: new_attributes }
97+
<%= file_name %>.reload
98+
skip("Add assertions for updated state")
99+
end
100+
101+
it "redirects to the <%= ns_file_name %>" do
102+
<%= file_name %> = <%= class_name %>.create! valid_attributes
103+
patch <%= show_helper.tr('@', '') %>, params: { <%= singular_table_name %>: new_attributes }
104+
<%= file_name %>.reload
105+
expect(response).to redirect_to(<%= singular_table_name %>_url(<%= file_name %>))
106+
end
107+
end
108+
109+
context "with invalid parameters" do
110+
it "renders a successful response (i.e. to display the 'edit' template)" do
111+
<%= file_name %> = <%= class_name %>.create! valid_attributes
112+
patch <%= show_helper.tr('@', '') %>, params: { <%= singular_table_name %>: invalid_attributes }
113+
expect(response).to be_successful
114+
end
115+
end
116+
end
117+
118+
describe "DELETE /destroy" do
119+
it "destroys the requested <%= ns_file_name %>" do
120+
<%= file_name %> = <%= class_name %>.create! valid_attributes
121+
expect {
122+
delete <%= show_helper.tr('@', '') %>
123+
}.to change(<%= class_name %>, :count).by(-1)
124+
end
125+
126+
it "redirects to the <%= table_name %> list" do
127+
<%= file_name %> = <%= class_name %>.create! valid_attributes
128+
delete <%= show_helper.tr('@', '') %>
129+
expect(response).to redirect_to(<%= index_helper %>_url)
130+
end
131+
end
132+
end
133+
<% end -%>

spec/generators/rspec/scaffold/scaffold_generator_spec.rb

Lines changed: 51 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,47 @@
55
RSpec.describe Rspec::Generators::ScaffoldGenerator, type: :generator do
66
setup_default_destination
77

8+
describe 'standard request specs' do
9+
subject { file('spec/requests/posts_spec.rb') }
10+
11+
describe 'with no options' do
12+
before { run_generator %w[posts --request_specs] }
13+
it { is_expected.to exist }
14+
it { is_expected.to contain("require 'rails_helper'") }
15+
it { is_expected.to contain(/^RSpec.describe "\/posts", #{type_metatag(:request)}/) }
16+
it { is_expected.to contain('GET /new') }
17+
it { is_expected.to contain(/"redirects to the created post"/) }
18+
it { is_expected.to contain('get post_url(post)') }
19+
it { is_expected.to contain('redirect_to(post_url(Post.last))') }
20+
it { is_expected.to contain(/"redirects to the \w+ list"/) }
21+
end
22+
23+
describe 'with --no-request_specs' do
24+
before { run_generator %w[posts --no-request_specs] }
25+
it { is_expected.not_to exist }
26+
end
27+
28+
describe 'with --api' do
29+
before { run_generator %w[posts --api] }
30+
it { is_expected.to exist }
31+
it { is_expected.to contain(/require 'rails_helper'/) }
32+
it { is_expected.to contain(/^RSpec.describe "\/posts", #{type_metatag(:request)}/) }
33+
it { is_expected.to contain('as: :json') }
34+
it { is_expected.not_to contain('get new_posts_path') }
35+
it { is_expected.not_to contain(/"redirects to\w+"/) }
36+
it { is_expected.to contain('renders a JSON response with the new post') }
37+
it { is_expected.to contain('renders a JSON response with errors for the new post') }
38+
it { is_expected.not_to contain('get edit_posts_path') }
39+
it { is_expected.to contain('renders a JSON response with the post') }
40+
it { is_expected.to contain('renders a JSON response with errors for the post') }
41+
end
42+
end
43+
844
describe 'standard controller spec' do
945
subject { file('spec/controllers/posts_controller_spec.rb') }
1046

11-
describe 'with no options' do
12-
before { run_generator %w[posts] }
47+
describe 'with --controller_specs' do
48+
before { run_generator %w[posts --controller_specs] }
1349
it { is_expected.to contain(/require 'rails_helper'/) }
1450
it { is_expected.to contain(/^RSpec.describe PostsController, #{type_metatag(:controller)}/) }
1551
it { is_expected.to contain(/GET #new/) }
@@ -27,13 +63,13 @@
2763
it { is_expected.to contain(/"redirects to the \w+ list"/) }
2864
end
2965

30-
describe 'with --no-controller_specs' do
31-
before { run_generator %w[posts --no-controller_specs] }
66+
describe 'with no options' do
67+
before { run_generator %w[posts] }
3268
it { is_expected.not_to exist }
3369
end
3470

3571
describe 'with --api' do
36-
before { run_generator %w[posts --api] }
72+
before { run_generator %w[posts --controller_specs --api] }
3773
it { is_expected.to contain(/require 'rails_helper'/) }
3874
it { is_expected.to contain(/^RSpec.describe PostsController, #{type_metatag(:controller)}/) }
3975
it { is_expected.not_to contain(/GET #new/) }
@@ -51,9 +87,18 @@
5187
end
5288
end
5389

90+
describe 'namespaced request spec' do
91+
subject { file('spec/requests/admin/posts_spec.rb') }
92+
before { run_generator %w[admin/posts] }
93+
it { is_expected.to exist }
94+
it { is_expected.to contain(/^RSpec.describe "\/admin\/posts", #{type_metatag(:request)}/) }
95+
it { is_expected.to contain('admin_post_url(admin_post)') }
96+
it { is_expected.to contain('Admin::Post.create') }
97+
end
98+
5499
describe 'namespaced controller spec' do
55100
subject { file('spec/controllers/admin/posts_controller_spec.rb') }
56-
before { run_generator %w[admin/posts] }
101+
before { run_generator %w[admin/posts --controller_specs] }
57102
it { is_expected.to contain(/^RSpec.describe Admin::PostsController, #{type_metatag(:controller)}/) }
58103
end
59104

0 commit comments

Comments
 (0)