Skip to content

Commit 7ce0a76

Browse files
authored
Merge pull request #2288 from rspec/scaffold-request-specs
Generate request specs when scaffold generator is used
2 parents 9fb6c9c + f885d15 commit 7ce0a76

File tree

5 files changed

+349
-18
lines changed

5 files changed

+349
-18
lines changed

example_app_generator/generate_stuff.rb

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,8 @@ def using_source_path(path)
9393
generate('scaffold gadget') # scaffold with no attributes
9494
generate('scaffold ticket original_price:float discounted_price:float')
9595
generate('scaffold admin/account name:string') # scaffold with nested resource
96+
generate('scaffold card --api')
97+
generate('scaffold upload --no-request_specs --controller_specs')
9698
generate('rspec:feature gadget')
9799
generate('controller things custom_action')
98100

@@ -137,9 +139,21 @@ def using_source_path(path)
137139
'config.warnings = false'
138140
gsub_file '.rspec', '--warnings', ''
139141

140-
# Remove skips so we can test controller specs work
141-
gsub_file 'spec/controllers/gadgets_controller_spec.rb',
142+
# Make a generated file work
143+
gsub_file 'app/views/cards/_card.json.jbuilder',
144+
', :created_at, :updated_at',
145+
''
146+
147+
# Remove skips so we can test specs work
148+
gsub_file 'spec/requests/cards_spec.rb',
149+
'skip("Add a hash of attributes valid for your model")',
150+
'{}'
151+
152+
gsub_file 'spec/requests/gadgets_spec.rb',
142153
'skip("Add a hash of attributes valid for your model")',
143154
'{}'
144155

156+
gsub_file 'spec/controllers/uploads_controller_spec.rb',
157+
'skip("Add a hash of attributes valid for your model")',
158+
'{}'
145159
final_tasks

lib/generators/rspec/scaffold/scaffold_generator.rb

Lines changed: 18 additions & 10 deletions
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"
@@ -27,15 +28,20 @@ def initialize(*args, &blk)
2728
def generate_controller_spec
2829
return unless options[:controller_specs]
2930

30-
template_file = File.join(
31-
'spec/controllers',
32-
controller_class_path,
33-
"#{controller_file_name}_controller_spec.rb"
34-
)
3531
if options[:api]
36-
template 'api_controller_spec.rb', template_file
32+
template 'api_controller_spec.rb', template_file(folder: 'controllers', suffix: '_controller')
33+
else
34+
template 'controller_spec.rb', template_file(folder: 'controllers', suffix: '_controller')
35+
end
36+
end
37+
38+
def generate_request_spec
39+
return unless options[:request_specs]
40+
41+
if options[:api]
42+
template 'api_request_spec.rb', template_file(folder: 'requests')
3743
else
38-
template 'controller_spec.rb', template_file
44+
template 'request_spec.rb', template_file(folder: 'requests')
3945
end
4046
end
4147

@@ -60,8 +66,6 @@ def generate_routing_spec
6066
template 'routing_spec.rb', template_file
6167
end
6268

63-
hook_for :integration_tool, as: :integration
64-
6569
protected
6670

6771
attr_reader :generator_args
@@ -116,6 +120,10 @@ def raw_value_for(attribute)
116120
end
117121
end
118122

123+
def template_file(folder:, suffix: '')
124+
File.join('spec', folder, controller_class_path, "#{controller_file_name}#{suffix}_spec.rb")
125+
end
126+
119127
def banner
120128
self.class.banner
121129
end
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 -%>

0 commit comments

Comments
 (0)