Skip to content

Commit

Permalink
Merge pull request #2288 from rspec/scaffold-request-specs
Browse files Browse the repository at this point in the history
Generate request specs when scaffold generator is used
  • Loading branch information
JonRowe committed Mar 13, 2020
1 parent 8a6a16c commit 1532449
Show file tree
Hide file tree
Showing 5 changed files with 349 additions and 18 deletions.
18 changes: 16 additions & 2 deletions example_app_generator/generate_stuff.rb
Expand Up @@ -93,6 +93,8 @@ def using_source_path(path)
generate('scaffold gadget') # scaffold with no attributes
generate('scaffold ticket original_price:float discounted_price:float')
generate('scaffold admin/account name:string') # scaffold with nested resource
generate('scaffold card --api')
generate('scaffold upload --no-request_specs --controller_specs')
generate('rspec:feature gadget')
generate('controller things custom_action')

Expand Down Expand Up @@ -137,9 +139,21 @@ def using_source_path(path)
'config.warnings = false'
gsub_file '.rspec', '--warnings', ''

# Remove skips so we can test controller specs work
gsub_file 'spec/controllers/gadgets_controller_spec.rb',
# Make a generated file work
gsub_file 'app/views/cards/_card.json.jbuilder',
', :created_at, :updated_at',
''

# Remove skips so we can test specs work
gsub_file 'spec/requests/cards_spec.rb',
'skip("Add a hash of attributes valid for your model")',
'{}'

gsub_file 'spec/requests/gadgets_spec.rb',
'skip("Add a hash of attributes valid for your model")',
'{}'

gsub_file 'spec/controllers/uploads_controller_spec.rb',
'skip("Add a hash of attributes valid for your model")',
'{}'
final_tasks
28 changes: 18 additions & 10 deletions lib/generators/rspec/scaffold/scaffold_generator.rb
Expand Up @@ -14,7 +14,8 @@ class ScaffoldGenerator < Base
class_option :singleton, type: :boolean, desc: "Supply to create a singleton controller"
class_option :api, type: :boolean, desc: "Skip specs unnecessary for API-only apps"

class_option :controller_specs, type: :boolean, default: true, desc: "Generate controller specs"
class_option :controller_specs, type: :boolean, default: false, desc: "Generate controller specs"
class_option :request_specs, type: :boolean, default: true, desc: "Generate request specs"
class_option :view_specs, type: :boolean, default: true, desc: "Generate view specs"
class_option :helper_specs, type: :boolean, default: true, desc: "Generate helper specs"
class_option :routing_specs, type: :boolean, default: true, desc: "Generate routing specs"
Expand All @@ -27,15 +28,20 @@ def initialize(*args, &blk)
def generate_controller_spec
return unless options[:controller_specs]

template_file = File.join(
'spec/controllers',
controller_class_path,
"#{controller_file_name}_controller_spec.rb"
)
if options[:api]
template 'api_controller_spec.rb', template_file
template 'api_controller_spec.rb', template_file(folder: 'controllers', suffix: '_controller')
else
template 'controller_spec.rb', template_file(folder: 'controllers', suffix: '_controller')
end
end

def generate_request_spec
return unless options[:request_specs]

if options[:api]
template 'api_request_spec.rb', template_file(folder: 'requests')
else
template 'controller_spec.rb', template_file
template 'request_spec.rb', template_file(folder: 'requests')
end
end

Expand All @@ -60,8 +66,6 @@ def generate_routing_spec
template 'routing_spec.rb', template_file
end

hook_for :integration_tool, as: :integration

protected

attr_reader :generator_args
Expand Down Expand Up @@ -116,6 +120,10 @@ def raw_value_for(attribute)
end
end

def template_file(folder:, suffix: '')
File.join('spec', folder, controller_class_path, "#{controller_file_name}#{suffix}_spec.rb")
end

def banner
self.class.banner
end
Expand Down
131 changes: 131 additions & 0 deletions lib/generators/rspec/scaffold/templates/api_request_spec.rb
@@ -0,0 +1,131 @@
require 'rails_helper'

# This spec was generated by rspec-rails when you ran the scaffold generator.
# It demonstrates how one might use RSpec to test the controller code that
# was generated by Rails when you ran the scaffold generator.
#
# It assumes that the implementation code is generated by the rails scaffold
# generator. If you are using any extension libraries to generate different
# controller code, this generated spec may or may not pass.
#
# It only uses APIs available in rails and/or rspec-rails. There are a number
# of tools you can use to make these specs even more expressive, but we're
# sticking to rails and rspec-rails APIs to keep things simple and stable.

<% module_namespacing do -%>
RSpec.describe "/<%= name.underscore.pluralize %>", <%= type_metatag(:request) %> do
# This should return the minimal set of attributes required to create a valid
# <%= class_name %>. As you add validations to <%= class_name %>, be sure to
# adjust the attributes here as well.
let(:valid_attributes) {
skip("Add a hash of attributes valid for your model")
}
let(:invalid_attributes) {
skip("Add a hash of attributes invalid for your model")
}
# This should return the minimal set of values that should be in the headers
# in order to pass any filters (e.g. authentication) defined in
# <%= controller_class_name %>Controller, or in your router and rack
# middleware. Be sure to keep this updated too.
let(:valid_headers) {
{}
}
<% unless options[:singleton] -%>
describe "GET /index" do
it "renders a successful response" do
<%= class_name %>.create! valid_attributes
get <%= index_helper %>_url, headers: valid_headers, as: :json
expect(response).to be_successful
end
end
<% end -%>
describe "GET /show" do
it "renders a successful response" do
<%= file_name %> = <%= class_name %>.create! valid_attributes
get <%= show_helper.tr('@', '') %>, as: :json
expect(response).to be_successful
end
end
describe "POST /create" do
context "with valid parameters" do
it "creates a new <%= class_name %>" do
expect {
post <%= index_helper %>_url,
params: { <%= ns_file_name %>: valid_attributes }, headers: valid_headers, as: :json
}.to change(<%= class_name %>, :count).by(1)
end
it "renders a JSON response with the new <%= ns_file_name %>" do
post <%= index_helper %>_url,
params: { <%= ns_file_name %>: valid_attributes }, headers: valid_headers, as: :json
expect(response).to have_http_status(:created)
expect(response.content_type).to match(a_string_including("application/json"))
end
end
context "with invalid parameters" do
it "does not create a new <%= class_name %>" do
expect {
post <%= index_helper %>_url,
params: { <%= ns_file_name %>: invalid_attributes }, as: :json
}.to change(<%= class_name %>, :count).by(0)
end
it "renders a JSON response with errors for the new <%= ns_file_name %>" do
post <%= index_helper %>_url,
params: { <%= ns_file_name %>: invalid_attributes }, headers: valid_headers, as: :json
expect(response).to have_http_status(:unprocessable_entity)
expect(response.content_type).to eq("application/json")
end
end
end
describe "PATCH /update" do
context "with valid parameters" do
let(:new_attributes) {
skip("Add a hash of attributes valid for your model")
}
it "updates the requested <%= ns_file_name %>" do
<%= file_name %> = <%= class_name %>.create! valid_attributes
patch <%= show_helper.tr('@', '') %>,
params: { <%= singular_table_name %>: invalid_attributes }, headers: valid_headers, as: :json
<%= file_name %>.reload
skip("Add assertions for updated state")
end
it "renders a JSON response with the <%= ns_file_name %>" do
<%= file_name %> = <%= class_name %>.create! valid_attributes
patch <%= show_helper.tr('@', '') %>,
params: { <%= singular_table_name %>: invalid_attributes }, headers: valid_headers, as: :json
expect(response).to have_http_status(:ok)
expect(response.content_type).to eq("application/json")
end
end
context "with invalid parameters" do
it "renders a JSON response with errors for the <%= ns_file_name %>" do
<%= file_name %> = <%= class_name %>.create! valid_attributes
patch <%= show_helper.tr('@', '') %>,
params: { <%= singular_table_name %>: invalid_attributes }, headers: valid_headers, as: :json
expect(response).to have_http_status(:unprocessable_entity)
expect(response.content_type).to eq("application/json")
end
end
end
describe "DELETE /destroy" do
it "destroys the requested <%= ns_file_name %>" do
<%= file_name %> = <%= class_name %>.create! valid_attributes
expect {
delete <%= show_helper.tr('@', '') %>, headers: valid_headers, as: :json
}.to change(<%= class_name %>, :count).by(-1)
end
end
end
<% end -%>
133 changes: 133 additions & 0 deletions lib/generators/rspec/scaffold/templates/request_spec.rb
@@ -0,0 +1,133 @@
require 'rails_helper'

# This spec was generated by rspec-rails when you ran the scaffold generator.
# It demonstrates how one might use RSpec to test the controller code that
# was generated by Rails when you ran the scaffold generator.
#
# It assumes that the implementation code is generated by the rails scaffold
# generator. If you are using any extension libraries to generate different
# controller code, this generated spec may or may not pass.
#
# It only uses APIs available in rails and/or rspec-rails. There are a number
# of tools you can use to make these specs even more expressive, but we're
# sticking to rails and rspec-rails APIs to keep things simple and stable.

<% module_namespacing do -%>
RSpec.describe "/<%= name.underscore.pluralize %>", <%= type_metatag(:request) %> do
# <%= class_name %>. As you add validations to <%= class_name %>, be sure to
# adjust the attributes here as well.
let(:valid_attributes) {
skip("Add a hash of attributes valid for your model")
}
let(:invalid_attributes) {
skip("Add a hash of attributes invalid for your model")
}
<% unless options[:singleton] -%>
describe "GET /index" do
it "renders a successful response" do
<%= class_name %>.create! valid_attributes
get <%= index_helper %>_url
expect(response).to be_successful
end
end
<% end -%>
describe "GET /show" do
it "renders a successful response" do
<%= file_name %> = <%= class_name %>.create! valid_attributes
get <%= show_helper.tr('@', '') %>
expect(response).to be_successful
end
end
describe "GET /new" do
it "renders a successful response" do
get <%= new_helper %>
expect(response).to be_successful
end
end
describe "GET /edit" do
it "render a successful response" do
<%= file_name %> = <%= class_name %>.create! valid_attributes
get <%= edit_helper.tr('@','') %>
expect(response).to be_successful
end
end
describe "POST /create" do
context "with valid parameters" do
it "creates a new <%= class_name %>" do
expect {
post <%= index_helper %>_url, params: { <%= ns_file_name %>: valid_attributes }
}.to change(<%= class_name %>, :count).by(1)
end
it "redirects to the created <%= ns_file_name %>" do
post <%= index_helper %>_url, params: { <%= ns_file_name %>: valid_attributes }
expect(response).to redirect_to(<%= show_helper.gsub("\@#{file_name}", class_name+".last") %>)
end
end
context "with invalid parameters" do
it "does not create a new <%= class_name %>" do
expect {
post <%= index_helper %>_url, params: { <%= ns_file_name %>: invalid_attributes }
}.to change(<%= class_name %>, :count).by(0)
end
it "renders a successful response (i.e. to display the 'new' template)" do
post <%= index_helper %>_url, params: { <%= ns_file_name %>: invalid_attributes }
expect(response).to be_successful
end
end
end
describe "PATCH /update" do
context "with valid parameters" do
let(:new_attributes) {
skip("Add a hash of attributes valid for your model")
}
it "updates the requested <%= ns_file_name %>" do
<%= file_name %> = <%= class_name %>.create! valid_attributes
patch <%= show_helper.tr('@', '') %>, params: { <%= singular_table_name %>: new_attributes }
<%= file_name %>.reload
skip("Add assertions for updated state")
end

it "redirects to the <%= ns_file_name %>" do
<%= file_name %> = <%= class_name %>.create! valid_attributes
patch <%= show_helper.tr('@', '') %>, params: { <%= singular_table_name %>: new_attributes }
<%= file_name %>.reload
expect(response).to redirect_to(<%= singular_table_name %>_url(<%= file_name %>))
end
end

context "with invalid parameters" do
it "renders a successful response (i.e. to display the 'edit' template)" do
<%= file_name %> = <%= class_name %>.create! valid_attributes
patch <%= show_helper.tr('@', '') %>, params: { <%= singular_table_name %>: invalid_attributes }
expect(response).to be_successful
end
end
end

describe "DELETE /destroy" do
it "destroys the requested <%= ns_file_name %>" do
<%= file_name %> = <%= class_name %>.create! valid_attributes
expect {
delete <%= show_helper.tr('@', '') %>
}.to change(<%= class_name %>, :count).by(-1)
end

it "redirects to the <%= table_name %> list" do
<%= file_name %> = <%= class_name %>.create! valid_attributes
delete <%= show_helper.tr('@', '') %>
expect(response).to redirect_to(<%= index_helper %>_url)
end
end
end
<% end -%>

0 comments on commit 1532449

Please sign in to comment.