Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generate request specs when scaffold generator is used #2288

Merged
merged 4 commits into from Mar 13, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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 -%>