Skip to content

Commit 8656e84

Browse files
k3rnisebjacobs
authored andcommitted
Update scaffold generator to care about --api flag. (rspec#1685)
* Update scaffold generator to care about --api flag. * Fix misplaced assignment in update/invalid params test.
1 parent 7810cf6 commit 8656e84

File tree

4 files changed

+240
-68
lines changed

4 files changed

+240
-68
lines changed

lib/generators/rspec/scaffold/scaffold_generator.rb

Lines changed: 7 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ class ScaffoldGenerator < Base
1212
class_option :orm, :desc => "ORM used to generate the controller"
1313
class_option :template_engine, :desc => "Template engine to generate view files"
1414
class_option :singleton, :type => :boolean, :desc => "Supply to create a singleton controller"
15+
class_option :api, :type => :boolean, :desc => "Skip specs unnecessary for API-only apps"
1516

1617
class_option :controller_specs, :type => :boolean, :default => true, :desc => "Generate controller specs"
1718
class_option :view_specs, :type => :boolean, :default => true, :desc => "Generate view specs"
@@ -26,10 +27,15 @@ def generate_controller_spec
2627
controller_class_path,
2728
"#{controller_file_name}_controller_spec.rb"
2829
)
29-
template 'controller_spec.rb', template_file
30+
if options[:api]
31+
template 'api_controller_spec.rb', template_file
32+
else
33+
template 'controller_spec.rb', template_file
34+
end
3035
end
3136

3237
def generate_view_specs
38+
return if options[:api]
3339
return unless options[:view_specs] && options[:template_engine]
3440

3541
copy_view :edit
@@ -58,14 +64,6 @@ def copy_view(view)
5864
File.join("spec/views", controller_file_path, "#{view}.html.#{options[:template_engine]}_spec.rb")
5965
end
6066

61-
def formatted_hash(hash)
62-
formatted = hash.inspect
63-
formatted.gsub!("{", "{ ")
64-
formatted.gsub!("}", " }")
65-
formatted.gsub!("=>", " => ")
66-
formatted
67-
end
68-
6967
# support for namespaced-resources
7068
def ns_file_name
7169
ns_parts.empty? ? file_name : "#{ns_parts[0].underscore}_#{ns_parts[1].singularize.underscore}"
@@ -83,65 +81,6 @@ def ns_parts
8381
end
8482
end
8583

86-
# Returns the name of the mock. For example, if the file name is user,
87-
# it returns mock_user.
88-
#
89-
# If a hash is given, it uses the hash key as the ORM method and the
90-
# value as response. So, for ActiveRecord and file name "User":
91-
#
92-
# mock_file_name(:save => true)
93-
# #=> mock_user(:save => true)
94-
#
95-
# If another ORM is being used and another method instead of save is
96-
# called, it will be the one used.
97-
#
98-
def mock_file_name(hash = nil)
99-
if hash
100-
method, and_return = hash.to_a.first
101-
method = orm_instance.send(method).split('.').last.gsub(/\(.*?\)/, '')
102-
"mock_#{ns_file_name}(:#{method} => #{and_return})"
103-
else
104-
"mock_#{ns_file_name}"
105-
end
106-
end
107-
108-
# Receives the ORM chain and convert to expects. For ActiveRecord:
109-
#
110-
# should! orm_class.find(User, "37")
111-
# #=> User.should_receive(:find).with(37)
112-
#
113-
# For Datamapper:
114-
#
115-
# should! orm_class.find(User, "37")
116-
# #=> User.should_receive(:get).with(37)
117-
#
118-
def should_receive(chain)
119-
stub_or_should_chain(:should_receive, chain)
120-
end
121-
122-
# Receives the ORM chain and convert to stub. For ActiveRecord:
123-
#
124-
# stub orm_class.find(User, "37")
125-
# #=> User.stub(:find).with(37)
126-
#
127-
# For Datamapper:
128-
#
129-
# stub orm_class.find(User, "37")
130-
# #=> User.stub(:get).with(37)
131-
#
132-
def stub(chain)
133-
stub_or_should_chain(:stub, chain)
134-
end
135-
136-
def stub_or_should_chain(mode, chain)
137-
receiver, method = chain.split(".")
138-
method.gsub!(/\((.*?)\)/, '')
139-
140-
response = "#{receiver}.#{mode}(:#{method})"
141-
response << ".with(#{$1})" unless $1.blank?
142-
response
143-
end
144-
14584
def value_for(attribute)
14685
raw_value_for(attribute).inspect
14786
end
Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
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 specify 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+
# Compared to earlier versions of this generator, there is very limited use of
16+
# stubs and message expectations in this spec. Stubs are only used when there
17+
# is no simpler way to get a handle on the object needed for the example.
18+
# Message expectations are only used when there is no simpler way to specify
19+
# that an instance is receiving a specific message.
20+
#
21+
# Also compared to earlier versions of this generator, there are no longer any
22+
# expectations of assigns and templates rendered. These features have been
23+
# removed from Rails core in Rails 5, but can be added back in via the
24+
# `rails-controller-testing` gem.
25+
26+
<% module_namespacing do -%>
27+
RSpec.describe <%= controller_class_name %>Controller, <%= type_metatag(:controller) %> do
28+
29+
# This should return the minimal set of attributes required to create a valid
30+
# <%= class_name %>. As you add validations to <%= class_name %>, be sure to
31+
# adjust the attributes here as well.
32+
let(:valid_attributes) {
33+
skip("Add a hash of attributes valid for your model")
34+
}
35+
36+
let(:invalid_attributes) {
37+
skip("Add a hash of attributes invalid for your model")
38+
}
39+
40+
# This should return the minimal set of values that should be in the session
41+
# in order to pass any filters (e.g. authentication) defined in
42+
# <%= controller_class_name %>Controller. Be sure to keep this updated too.
43+
let(:valid_session) { {} }
44+
45+
<% unless options[:singleton] -%>
46+
describe "GET #index" do
47+
it "returns a success response" do
48+
<%= file_name %> = <%= class_name %>.create! valid_attributes
49+
<% if RUBY_VERSION < '1.9.3' -%>
50+
get :index, {}, valid_session
51+
<% else -%>
52+
get :index, params: {}, session: valid_session
53+
<% end -%>
54+
expect(response).to be_success
55+
end
56+
end
57+
58+
<% end -%>
59+
describe "GET #show" do
60+
it "returns a success response" do
61+
<%= file_name %> = <%= class_name %>.create! valid_attributes
62+
<% if RUBY_VERSION < '1.9.3' -%>
63+
get :show, {:id => <%= file_name %>.to_param}, valid_session
64+
<% else -%>
65+
get :show, params: {id: <%= file_name %>.to_param}, session: valid_session
66+
<% end -%>
67+
expect(response).to be_success
68+
end
69+
end
70+
71+
describe "POST #create" do
72+
context "with valid params" do
73+
it "creates a new <%= class_name %>" do
74+
expect {
75+
<% if RUBY_VERSION < '1.9.3' -%>
76+
post :create, {:<%= ns_file_name %> => valid_attributes}, valid_session
77+
<% else -%>
78+
post :create, params: {<%= ns_file_name %>: valid_attributes}, session: valid_session
79+
<% end -%>
80+
}.to change(<%= class_name %>, :count).by(1)
81+
end
82+
83+
it "renders a JSON response with the new <%= ns_file_name %>" do
84+
<% if RUBY_VERSION < '1.9.3' -%>
85+
post :create, {:<%= ns_file_name %> => valid_attributes}, valid_session
86+
<% else %>
87+
post :create, params: {<%= ns_file_name %>: valid_attributes}, session: valid_session
88+
<% end -%>
89+
expect(response).to have_http_status(:created)
90+
expect(response.content_type).to eq('application/json')
91+
expect(response.location).to eq(<%= ns_file_name %>_url(<%= class_name %>.last))
92+
end
93+
end
94+
95+
context "with invalid params" do
96+
it "renders a JSON response with errors for the new <%= ns_file_name %>" do
97+
<% if RUBY_VERSION < '1.9.3' -%>
98+
post :create, {:<%= ns_file_name %> => invalid_attributes}, valid_session
99+
<% else %>
100+
post :create, params: {<%= ns_file_name %>: invalid_attributes}, session: valid_session
101+
<% end -%>
102+
expect(response).to have_http_status(:unprocessable_entity)
103+
expect(response.content_type).to eq('application/json')
104+
end
105+
end
106+
end
107+
108+
describe "PUT #update" do
109+
context "with valid params" do
110+
let(:new_attributes) {
111+
skip("Add a hash of attributes valid for your model")
112+
}
113+
114+
it "updates the requested <%= ns_file_name %>" do
115+
<%= file_name %> = <%= class_name %>.create! valid_attributes
116+
<% if RUBY_VERSION < '1.9.3' -%>
117+
put :update, {:id => <%= file_name %>.to_param, :<%= ns_file_name %> => new_attributes}, valid_session
118+
<% else -%>
119+
put :update, params: {id: <%= file_name %>.to_param, <%= ns_file_name %>: new_attributes}, session: valid_session
120+
<% end -%>
121+
<%= file_name %>.reload
122+
skip("Add assertions for updated state")
123+
end
124+
125+
it "renders a JSON response with the <%= ns_file_name %>" do
126+
<%= file_name %> = <%= class_name %>.create! valid_attributes
127+
<% if RUBY_VERSION < '1.9.3' -%>
128+
put :update, {:id => <%= file_name %>.to_param, :<%= ns_file_name %> => valid_attributes}, valid_session
129+
<% else %>
130+
put :update, params: {id: <%= file_name %>.to_param, <%= ns_file_name %>: valid_attributes}, session: valid_session
131+
<% end -%>
132+
expect(response).to have_http_status(:ok)
133+
expect(response.content_type).to eq('application/json')
134+
end
135+
end
136+
137+
context "with invalid params" do
138+
it "renders a JSON response with errors for the <%= ns_file_name %>" do
139+
<%= file_name %> = <%= class_name %>.create! valid_attributes
140+
<% if RUBY_VERSION < '1.9.3' -%>
141+
put :update, {:id => <%= file_name %>.to_param, :<%= ns_file_name %> => invalid_attributes}, valid_session
142+
<% else %>
143+
put :update, params: {id: <%= file_name %>.to_param, <%= ns_file_name %>: invalid_attributes}, session: valid_session
144+
<% end -%>
145+
expect(response).to have_http_status(:unprocessable_entity)
146+
expect(response.content_type).to eq('application/json')
147+
end
148+
end
149+
end
150+
151+
describe "DELETE #destroy" do
152+
it "destroys the requested <%= ns_file_name %>" do
153+
<%= file_name %> = <%= class_name %>.create! valid_attributes
154+
expect {
155+
<% if RUBY_VERSION < '1.9.3' -%>
156+
delete :destroy, {:id => <%= file_name %>.to_param}, valid_session
157+
<% else -%>
158+
delete :destroy, params: {id: <%= file_name %>.to_param}, session: valid_session
159+
<% end -%>
160+
}.to change(<%= class_name %>, :count).by(-1)
161+
end
162+
end
163+
164+
end
165+
<% end -%>

lib/generators/rspec/scaffold/templates/routing_spec.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,21 @@
1010
end
1111
1212
<% end -%>
13+
<% unless options[:api] -%>
1314
it "routes to #new" do
1415
expect(:get => "/<%= ns_table_name %>/new").to route_to("<%= ns_table_name %>#new")
1516
end
17+
<% end -%>
1618
1719
it "routes to #show" do
1820
expect(:get => "/<%= ns_table_name %>/1").to route_to("<%= ns_table_name %>#show", :id => "1")
1921
end
2022
23+
<% unless options[:api] -%>
2124
it "routes to #edit" do
2225
expect(:get => "/<%= ns_table_name %>/1/edit").to route_to("<%= ns_table_name %>#edit", :id => "1")
2326
end
27+
<% end -%>
2428
2529
it "routes to #create" do
2630
expect(:post => "/<%= ns_table_name %>").to route_to("<%= ns_table_name %>#create")

spec/generators/rspec/scaffold/scaffold_generator_spec.rb

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,44 @@
1212
before { run_generator %w(posts) }
1313
it { is_expected.to contain(/require 'rails_helper'/) }
1414
it { is_expected.to contain(/^RSpec.describe PostsController, #{type_metatag(:controller)}/) }
15+
it { is_expected.to contain(/GET #new/) }
16+
it { is_expected.to contain(/"redirects to the created \w+"/) }
17+
it { is_expected.to contain(/display the 'new' template/) }
18+
it { is_expected.not_to contain(/"renders a JSON response with the new \w+"/) }
19+
it { is_expected.not_to contain(/"renders a JSON response with errors for the new \w+"/) }
20+
21+
it { is_expected.to contain(/GET #edit/) }
22+
it { is_expected.to contain(/"redirects to the \w+"/) }
23+
it { is_expected.to contain(/display the 'edit' template/) }
24+
it { is_expected.not_to contain(/"renders a JSON response with the \w+"/) }
25+
it { is_expected.not_to contain(/"renders a JSON response with errors for the \w+"/) }
26+
27+
it { is_expected.to contain(/"redirects to the \w+ list"/) }
1528
end
1629

1730
describe 'with --no-controller_specs' do
1831
before { run_generator %w(posts --no-controller_specs) }
1932
it { is_expected.not_to exist }
2033
end
34+
35+
describe 'with --api' do
36+
before { run_generator %w(posts --api) }
37+
it { is_expected.to contain(/require 'rails_helper'/) }
38+
it { is_expected.to contain(/^RSpec.describe PostsController, #{type_metatag(:controller)}/) }
39+
it { is_expected.not_to contain(/GET #new/) }
40+
it { is_expected.not_to contain(/"redirects to the created \w+"/) }
41+
it { is_expected.not_to contain(/display the 'new' template/) }
42+
it { is_expected.to contain(/"renders a JSON response with the new \w+"/) }
43+
it { is_expected.to contain(/"renders a JSON response with errors for the new \w+"/) }
44+
it { is_expected.not_to contain(/GET #edit/) }
45+
it { is_expected.not_to contain(/"redirects to the \w+"/) }
46+
it { is_expected.not_to contain(/display the 'edit' template/) }
47+
it { is_expected.to contain(/"renders a JSON response with the \w+"/) }
48+
it { is_expected.to contain(/"renders a JSON response with errors for the \w+"/) }
49+
50+
it { is_expected.not_to contain(/"redirects to the \w+ list"/) }
51+
52+
end
2153
end
2254

2355
describe 'namespaced controller spec' do
@@ -119,6 +151,30 @@
119151
end
120152
end
121153

154+
describe 'with --api' do
155+
before { run_generator %w(posts --api) }
156+
157+
describe 'edit' do
158+
subject { file("spec/views/posts/edit.html.erb_spec.rb") }
159+
it { is_expected.not_to exist }
160+
end
161+
162+
describe 'index' do
163+
subject { file("spec/views/posts/index.html.erb_spec.rb") }
164+
it { is_expected.not_to exist }
165+
end
166+
167+
describe 'new' do
168+
subject { file("spec/views/posts/index.html.erb_spec.rb") }
169+
it { is_expected.not_to exist }
170+
end
171+
172+
describe 'show' do
173+
subject { file("spec/views/posts/index.html.erb_spec.rb") }
174+
it { is_expected.not_to exist }
175+
end
176+
end
177+
122178
describe 'with --no-view-specs' do
123179
before { run_generator %w(posts --no-view-specs) }
124180

@@ -152,11 +208,19 @@
152208
it { is_expected.to contain(/require "rails_helper"/) }
153209
it { is_expected.to contain(/^RSpec.describe PostsController, #{type_metatag(:routing)}/) }
154210
it { is_expected.to contain(/describe "routing"/) }
211+
it { is_expected.to contain(/routes to #new/) }
212+
it { is_expected.to contain(/routes to #edit/) }
155213
end
156214

157215
describe 'with --no-routing-specs' do
158216
before { run_generator %w(posts --no-routing_specs) }
159217
it { is_expected.not_to exist }
160218
end
219+
220+
describe 'with --api' do
221+
before { run_generator %w(posts --api) }
222+
it { is_expected.not_to contain(/routes to #new/) }
223+
it { is_expected.not_to contain(/routes to #edit/) }
224+
end
161225
end
162226
end

0 commit comments

Comments
 (0)