Commit 1fb5bbf6bea269d95504b37f97f87f687ccb2c8d

Authored by Dan Croak
1 parent 75ebbbce

upgraded coulda

Showing 25 changed files with 349 additions and 315 deletions   Show diff stats
vendor/plugins/coulda/README.textile
1 1 h1. Coulda generators
2 2  
3   -A plugin that overrides Rails' model, controller, & helper generators. It also adds a view generator. It uses Shoulda & Factory Girl for tests.
  3 +A Rails plugin for feature, view, controller, model, & helper generators. It is meant to be used as part of an "Outside-In" Test-Driven Development cycle.
4 4  
5 5 h2. Requirements
6 6  
  7 +* "Cucumber":http://github.com/aslakhellesoy/cucumber
7 8 * "Shoulda":http://github.com/thoughtbot/shoulda
8 9 * "Factory Girl":http://github.com/thoughtbot/factory_girl
  10 +* "Mocha":http://github.com/jferris/mocha
9 11  
10 12 h2. Installation
11 13  
12 14 $ script/plugin install git://github.com/dancroak/coulda.git
13 15  
  16 +h2. Feature generator
  17 +
  18 + $ script/generate feature Posts new create
  19 +
  20 +generates...
  21 +
  22 +<pre><code> Scenario: Create a new post
  23 + Given I am on the new post page
  24 + When I create a 'post' named 'A new post'
  25 + Then I should see 'A new post'</code></pre>
  26 +
  27 +Now run it:
  28 +
  29 + $ cucumber features/posts.feature
  30 +
  31 +The failure will be:
  32 +
  33 + undefined method `new_post_path'
  34 +
  35 +To get past this error, we'll create just the route we need:
  36 +
  37 + map.resources :posts, :only => [:new]
  38 +
  39 +Running the test again, we have a new failure:
  40 +
  41 + uninitialized constant PostsController
  42 +
  43 +h2. Controller test generator
  44 +
  45 +We've reached a point in our Outside-In cycle where we want to spiral down into a tighter feedback loop to unit test the non-existant controller.
  46 +
  47 + $ script/generate controller_test Posts new create
  48 +
  49 +h2. Controller generator
  50 +
  51 + $ script/generate controller Posts new create
  52 +
  53 +generates...
  54 +
  55 +
14 56 h2. Model generator
15 57  
16 58 $ script/generate model User
... ... @@ -20,14 +62,6 @@ h2. Model generator
20 62 * migration
21 63 * model
22 64  
23   -h2. Controller generator
24   -
25   - $ script/generate controller Users new
26   -
27   -* functional test (Shoulda & Factory Girl), only test RESTful new action
28   -* controller, only RESTful new action
29   -* no helper file
30   -
31 65 h2. Helper generator
32 66  
33 67 $ script/generate helper Navigation
... ... @@ -39,16 +73,11 @@ h2. View generator
39 73  
40 74 $ script/generate view Posts new
41 75  
42   -* We're not sure we like this one yet. Let us know what you think.
43   -
44 76 h2. Model generator: belongs_to
45 77  
46 78 $ script/generate model post user:belongs_to
47 79  
48   -* "add_index" in the migration
49   -* "belongs_to" in the model
50   -* "should_belong_to" in unit test
51   -* association in the factory
  80 +generates...
52 81  
53 82 <pre><code>class CreatePosts < ActiveRecord::Migration
54 83 def self.up
... ...
vendor/plugins/coulda/features/controller_generator.feature
... ... @@ -9,7 +9,6 @@ Feature: Rails controller generator
9 9 When I generate a "Posts" controller with "index" action
10 10 Then a standard "index" functional test for "posts" should be generated
11 11 And an empty "index" controller action for "posts" should be generated
12   - And only a "index" action for RESTful "posts" route should be generated
13 12  
14 13 Scenario: Controller generator for new action
15 14 Given a Rails app
... ... @@ -17,7 +16,6 @@ Feature: Rails controller generator
17 16 When I generate a "Posts" controller with "new" action
18 17 Then a standard "new" functional test for "posts" should be generated
19 18 And a "new" controller action for "posts" should be generated
20   - And only a "new" action for RESTful "posts" route should be generated
21 19  
22 20 Scenario: Controller generator for create action
23 21 Given a Rails app
... ... @@ -25,7 +23,6 @@ Feature: Rails controller generator
25 23 When I generate a "Posts" controller with "create" action
26 24 Then a standard "create" functional test for "posts" should be generated
27 25 And a "create" controller action for "posts" should be generated
28   - And only a "create" action for RESTful "posts" route should be generated
29 26  
30 27 Scenario: Controller generator for create action when Cucumber is installed
31 28 Given a Rails app with Cucumber
... ... @@ -33,7 +30,6 @@ Feature: Rails controller generator
33 30 When I generate a "Posts" controller with "create" action
34 31 Then a standard "create" functional test for "posts" should be generated
35 32 And a "create" controller action for "posts" should be generated
36   - And only a "create" action for RESTful "posts" route should be generated
37 33  
38 34 Scenario: Controller generator for show action
39 35 Given a Rails app
... ... @@ -41,7 +37,6 @@ Feature: Rails controller generator
41 37 When I generate a "Posts" controller with "show" action
42 38 Then a standard "show" functional test for "posts" should be generated
43 39 And a "show" controller action for "posts" should be generated
44   - And only a "show" action for RESTful "posts" route should be generated
45 40  
46 41 Scenario: Controller generator for edit action
47 42 Given a Rails app
... ... @@ -49,7 +44,6 @@ Feature: Rails controller generator
49 44 When I generate a "Posts" controller with "edit" action
50 45 Then a standard "edit" functional test for "posts" should be generated
51 46 And a "edit" controller action for "posts" should be generated
52   - And only a "edit" action for RESTful "posts" route should be generated
53 47  
54 48 Scenario: Controller generator for update action
55 49 Given a Rails app
... ... @@ -57,7 +51,6 @@ Feature: Rails controller generator
57 51 When I generate a "Posts" controller with "update" action
58 52 Then a standard "update" functional test for "posts" should be generated
59 53 And a "update" controller action for "posts" should be generated
60   - And only a "update" action for RESTful "posts" route should be generated
61 54  
62 55 Scenario: Controller generator for destroy action
63 56 Given a Rails app
... ... @@ -65,5 +58,4 @@ Feature: Rails controller generator
65 58 When I generate a "Posts" controller with "destroy" action
66 59 Then a standard "destroy" functional test for "posts" should be generated
67 60 And a "destroy" controller action for "posts" should be generated
68   - And only a "destroy" action for RESTful "posts" route should be generated
69 61  
... ...
vendor/plugins/coulda/features/feature_generator.feature 0 → 100644
... ... @@ -0,0 +1,21 @@
  1 +Feature: Rails controller generator
  2 + In order to better do Test-Driven Development with Rails
  3 + As a user
  4 + I want to generate Shoulda & Factory Girl tests for only RESTful actions I need.
  5 +
  6 + Scenario: Feature generator for new action
  7 + Given a Rails app with Cucumber
  8 + And the coulda plugin is installed
  9 + When I generate a "new" feature for "Posts"
  10 + Then a "posts" feature for the "create" scenario should be generated
  11 + And a "posts" step definition should be generated
  12 + And a new post page path should be generated
  13 +
  14 + Scenario: Feature generator for create action same as new
  15 + Given a Rails app with Cucumber
  16 + And the coulda plugin is installed
  17 + When I generate a "create" feature for "Posts"
  18 + Then a "posts" feature for the "create" scenario should be generated
  19 + And a "posts" step definition should be generated
  20 + And a new post page path should be generated
  21 +
... ...
vendor/plugins/coulda/features/step_definitions/controller_steps.rb
... ... @@ -5,180 +5,155 @@ When /^I generate a &quot;(.*)&quot; controller with &quot;(.*)&quot; action$/ do |controller, actio
5 5 end
6 6  
7 7 Then /^a standard "index" functional test for "posts" should be generated$/ do
8   - assert_generated_functional_test_for("posts") do |body|
9   - expected = " context 'GET to index' do\n" <<
10   - " setup { get :index }\n\n" <<
11   - " should_render_template :index\n" <<
12   - " should_respond_with :success\n" <<
13   - " end"
14   - assert body.include?(expected),
15   - "expected #{expected} but was #{body.inspect}"
  8 + assert_generated_file("test/functional/posts_controller_test.rb") do
  9 + " context 'GET to index' do\n" <<
  10 + " setup { get :index }\n\n" <<
  11 + " should_render_template :index\n" <<
  12 + " should_respond_with :success\n" <<
  13 + " end"
  14 + end
  15 +end
  16 +
  17 +Then /^an empty "index" controller action for "posts" should be generated$/ do
  18 + assert_generated_file("app/controllers/posts_controller.rb") do
  19 + " def index\n" <<
  20 + " end"
16 21 end
17 22 end
18 23  
19 24 Then /^a standard "new" functional test for "posts" should be generated$/ do
20   - assert_generated_functional_test_for("posts") do |body|
21   - expected = " context 'GET to new' do\n" <<
22   - " setup { get :new }\n\n" <<
23   - " should_assign_to :post\n" <<
24   - " should_render_template :new\n" <<
25   - " should_respond_with :success\n" <<
26   - " end"
27   - assert body.include?(expected),
28   - "expected #{expected} but was #{body.inspect}"
  25 + assert_generated_file("test/functional/posts_controller_test.rb") do
  26 + " context 'GET to new' do\n" <<
  27 + " setup { get :new }\n\n" <<
  28 + " should_assign_to :post\n" <<
  29 + " should_render_template :new\n" <<
  30 + " should_respond_with :success\n" <<
  31 + " end"
29 32 end
30 33 end
31 34  
32 35 Then /^a standard "create" functional test for "posts" should be generated$/ do
33   - assert_generated_functional_test_for("posts") do |body|
34   - expected = " context 'POST to create with valid parameters' do\n" <<
35   - " setup do\n" <<
36   - " post :create, :post => Factory.attributes_for(:post)\n" <<
37   - " end\n\n" <<
38   - " should_set_the_flash_to /created/i\n" <<
39   - " should_redirect_to('posts index') { posts_path }\n" <<
40   - " end"
41   - assert body.include?(expected),
42   - "expected #{expected} but was #{body.inspect}"
  36 + assert_generated_file("test/functional/posts_controller_test.rb") do
  37 + " context 'POST to create with valid parameters' do\n" <<
  38 + " setup do\n" <<
  39 + " post :create, :post => Factory.attributes_for(:post)\n" <<
  40 + " end\n\n" <<
  41 + " should_set_the_flash_to /created/i\n" <<
  42 + " should_redirect_to('posts index') { posts_path }\n" <<
  43 + " end"
43 44 end
44 45 end
45 46  
46 47 Then /^a standard "show" functional test for "posts" should be generated$/ do
47   - assert_generated_functional_test_for("posts") do |body|
48   - expected = " context 'GET to show for existing post' do\n" <<
49   - " setup do\n" <<
50   - " @post = Factory(:post)\n" <<
51   - " get :show, :id => @post.to_param\n" <<
52   - " end\n\n" <<
53   - " should_assign_to :post, :equals => '@post'\n" <<
54   - " should_render_template :show\n" <<
55   - " should_respond_with :success\n" <<
56   - " end"
57   - assert body.include?(expected),
58   - "expected #{expected} but was #{body.inspect}"
  48 + assert_generated_file("test/functional/posts_controller_test.rb") do
  49 + " context 'GET to show for existing post' do\n" <<
  50 + " setup do\n" <<
  51 + " @post = Factory(:post)\n" <<
  52 + " get :show, :id => @post.to_param\n" <<
  53 + " end\n\n" <<
  54 + " should_assign_to :post, :equals => '@post'\n" <<
  55 + " should_render_template :show\n" <<
  56 + " should_respond_with :success\n" <<
  57 + " end"
59 58 end
60 59 end
61 60  
62 61 Then /^a standard "edit" functional test for "posts" should be generated$/ do
63   - assert_generated_functional_test_for("posts") do |body|
64   - expected = " context 'GET to edit for existing post' do\n" <<
65   - " setup do\n" <<
66   - " @post = Factory(:post)\n" <<
67   - " get :edit, :id => @post.to_param\n" <<
68   - " end\n\n" <<
69   - " should_assign_to :post, :equals => '@post'\n" <<
70   - " should_render_template :edit\n" <<
71   - " should_respond_with :success\n" <<
72   - " end"
73   - assert body.include?(expected),
74   - "expected #{expected} but was #{body.inspect}"
  62 + assert_generated_file("test/functional/posts_controller_test.rb") do
  63 + " context 'GET to edit for existing post' do\n" <<
  64 + " setup do\n" <<
  65 + " @post = Factory(:post)\n" <<
  66 + " get :edit, :id => @post.to_param\n" <<
  67 + " end\n\n" <<
  68 + " should_assign_to :post, :equals => '@post'\n" <<
  69 + " should_render_template :edit\n" <<
  70 + " should_respond_with :success\n" <<
  71 + " end"
75 72 end
76 73 end
77 74  
78 75 Then /^a standard "update" functional test for "posts" should be generated$/ do
79   - assert_generated_functional_test_for("posts") do |body|
80   - expected = " context 'PUT to update for existing post' do\n" <<
81   - " setup do\n" <<
82   - " @post = Factory(:post)\n" <<
83   - " put :update, :id => @post.to_param,\n" <<
84   - " :post => Factory.attributes_for(:post)\n" <<
85   - " end\n\n" <<
86   - " should_set_the_flash_to /updated/i\n" <<
87   - " should_redirect_to('posts index') { posts_path }\n" <<
88   - " end"
89   - assert body.include?(expected),
90   - "expected #{expected} but was #{body.inspect}"
  76 + assert_generated_file("test/functional/posts_controller_test.rb") do
  77 + " context 'PUT to update for existing post' do\n" <<
  78 + " setup do\n" <<
  79 + " @post = Factory(:post)\n" <<
  80 + " put :update, :id => @post.to_param,\n" <<
  81 + " :post => Factory.attributes_for(:post)\n" <<
  82 + " end\n\n" <<
  83 + " should_set_the_flash_to /updated/i\n" <<
  84 + " should_redirect_to('posts index') { posts_path }\n" <<
  85 + " end"
91 86 end
92 87 end
93 88  
94 89 Then /^a standard "destroy" functional test for "posts" should be generated$/ do
95   - assert_generated_functional_test_for("posts") do |body|
96   - expected = " context 'given a post' do\n" <<
97   - " setup { @post = Factory(:post) }\n\n" <<
98   - " context 'DELETE to destroy' do\n" <<
99   - " setup { delete :destroy, :id => @post.to_param }\n\n" <<
100   - " should_destroy :post\n" <<
101   - " should_set_the_flash_to /deleted/i\n" <<
102   - " should_redirect_to('posts index') { posts_path }\n" <<
103   - " end\n" <<
104   - " end"
105   - assert body.include?(expected),
106   - "expected #{expected} but was #{body.inspect}"
  90 + assert_generated_file("test/functional/posts_controller_test.rb") do
  91 + " context 'given a post' do\n" <<
  92 + " setup { @post = Factory(:post) }\n\n" <<
  93 + " context 'DELETE to destroy' do\n" <<
  94 + " setup { delete :destroy, :id => @post.to_param }\n\n" <<
  95 + " should_destroy :post\n" <<
  96 + " should_set_the_flash_to /deleted/i\n" <<
  97 + " should_redirect_to('posts index') { posts_path }\n" <<
  98 + " end\n" <<
  99 + " end"
107 100 end
108 101 end
109 102  
110 103 Then /^a "new" controller action for "posts" should be generated$/ do
111   - assert_generated_controller_for("posts") do |body|
112   - expected = " def new\n" <<
113   - " @post = Post.new\n" <<
114   - " end"
115   - assert body.include?(expected),
116   - "expected #{expected} but was #{body.inspect}"
  104 + assert_generated_file("app/controllers/posts_controller.rb") do
  105 + " def new\n" <<
  106 + " @post = Post.new\n" <<
  107 + " end"
117 108 end
118 109 end
119 110  
120 111 Then /^a "create" controller action for "posts" should be generated$/ do
121   - assert_generated_controller_for("posts") do |body|
122   - expected = " def create\n" <<
123   - " @post = Post.new(params[:post])\n" <<
124   - " @post.save\n" <<
125   - " flash[:success] = 'Post created.'\n" <<
126   - " redirect_to posts_path\n" <<
127   - " end"
128   - assert body.include?(expected),
129   - "expected #{expected} but was #{body.inspect}"
  112 + assert_generated_file("app/controllers/posts_controller.rb") do
  113 + " def create\n" <<
  114 + " @post = Post.new(params[:post])\n" <<
  115 + " @post.save\n" <<
  116 + " flash[:success] = 'Post created.'\n" <<
  117 + " redirect_to posts_path\n" <<
  118 + " end"
130 119 end
131 120 end
132 121  
133 122 Then /^a "show" controller action for "posts" should be generated$/ do
134   - assert_generated_controller_for("posts") do |body|
135   - expected = " def show\n" <<
136   - " @post = Post.find(params[:id])\n" <<
137   - " end"
138   - assert body.include?(expected),
139   - "expected #{expected} but was #{body.inspect}"
  123 + assert_generated_file("app/controllers/posts_controller.rb") do
  124 + " def show\n" <<
  125 + " @post = Post.find(params[:id])\n" <<
  126 + " end"
140 127 end
141 128 end
142 129  
143 130 Then /^a "edit" controller action for "posts" should be generated$/ do
144   - assert_generated_controller_for("posts") do |body|
145   - expected = " def edit\n" <<
146   - " @post = Post.find(params[:id])\n" <<
147   - " end"
148   - assert body.include?(expected),
149   - "expected #{expected} but was #{body.inspect}"
  131 + assert_generated_file("app/controllers/posts_controller.rb") do
  132 + " def edit\n" <<
  133 + " @post = Post.find(params[:id])\n" <<
  134 + " end"
150 135 end
151 136 end
152 137  
153 138 Then /^a "update" controller action for "posts" should be generated$/ do
154   - assert_generated_controller_for("posts") do |body|
155   - expected = " def update\n" <<
156   - " @post = Post.find(params[:id])\n" <<
157   - " @post.update_attributes(params[:post])\n" <<
158   - " flash[:success] = 'Post updated.'\n" <<
159   - " redirect_to posts_path\n" <<
160   - " end"
161   - assert body.include?(expected),
162   - "expected #{expected} but was #{body.inspect}"
  139 + assert_generated_file("app/controllers/posts_controller.rb") do
  140 + " def update\n" <<
  141 + " @post = Post.find(params[:id])\n" <<
  142 + " @post.update_attributes(params[:post])\n" <<
  143 + " flash[:success] = 'Post updated.'\n" <<
  144 + " redirect_to posts_path\n" <<
  145 + " end"
163 146 end
164 147 end
165 148  
166 149 Then /^a "destroy" controller action for "posts" should be generated$/ do
167   - assert_generated_controller_for("posts") do |body|
168   - expected = " def destroy\n" <<
169   - " @post = Post.find(params[:id])\n" <<
170   - " @post.destroy\n" <<
171   - " flash[:success] = 'Post deleted.'\n" <<
172   - " redirect_to posts_path\n" <<
173   - " end"
174   - assert body.include?(expected),
175   - "expected #{expected} but was #{body.inspect}"
176   - end
177   -end
178   -
179   -Then /^an empty "(.*)" controller action for "(.*)" should be generated$/ do |action, controller|
180   - assert_generated_controller_for(controller) do |body|
181   - assert_has_empty_method(body, action)
  150 + assert_generated_file("app/controllers/posts_controller.rb") do
  151 + " def destroy\n" <<
  152 + " @post = Post.find(params[:id])\n" <<
  153 + " @post.destroy\n" <<
  154 + " flash[:success] = 'Post deleted.'\n" <<
  155 + " redirect_to posts_path\n" <<
  156 + " end"
182 157 end
183 158 end
184 159  
... ...
vendor/plugins/coulda/features/step_definitions/cucumber_steps.rb
... ... @@ -2,20 +2,39 @@ Given /^a Rails app with Cucumber$/ do
2 2 system "rails rails_root"
3 3 @rails_root = File.join(File.dirname(__FILE__), "..", "..", "rails_root")
4 4 require 'cucumber'
  5 + system "cd #{@rails_root} && ruby script/generate cucumber"
5 6 end
6 7  
7   -Then /^a Cucumber "([^\"]*)" functional test for "([^\"]*)" should be generated$/ do |arg1, arg2|
8   - pending
  8 +When /^I generate a "([^\"]*)" feature for "([^\"]*)"$/ do |feature, resource|
  9 + system "cd #{@rails_root} && " <<
  10 + "script/generate feature #{resource} #{feature} && " <<
  11 + "cd .."
9 12 end
10 13  
11   -Then /^a standard "posts" feature for the "new" scenario should be generated$/ do
12   - assert_generated_file("features/posts.feature") do |body|
13   - expected = " Scenario: Create a new 'post'\n" <<
14   - " Given I am on the new post page\n" <<
15   - " When I create a 'post' named 'A new post'\n" <<
16   - " Then I should see 'A new post'"
17   - assert body.include?(expected),
18   - "expected #{expected} but was #{body.inspect}"
  14 +Then /^a "posts" feature for the "([^\"]*)" scenario should be generated$/ do |action|
  15 + if %w(new create).include?(action)
  16 + assert_generated_file("features/posts.feature") do
  17 + " Scenario: Create a new post\n" <<
  18 + " Given I am on the new post page\n" <<
  19 + " When I create a post named \"A new post\"\n" <<
  20 + " Then I should see \"A new post\""
  21 + end
  22 + end
  23 +end
  24 +
  25 +Then /^a "posts" step definition should be generated$/ do
  26 + assert_generated_file("features/step_definitions/posts_steps.rb") do
  27 + "When /^I create a post named \"([^\\\"]*)\"$/ do |name|\n" <<
  28 + " fills_in :name, :with => name\n" <<
  29 + " click_button 'Create'\n"
  30 + "end"
  31 + end
  32 +end
  33 +
  34 +Then /^a new post page path should be generated$/ do
  35 + assert_generated_file("features/support/paths.rb") do
  36 + " when /the new post page/i\n" <<
  37 + " new_post_path"
19 38 end
20 39 end
21 40  
... ...
vendor/plugins/coulda/features/step_definitions/helper_steps.rb
... ... @@ -5,10 +5,10 @@ When /^I generate a helper named &quot;(.*)&quot;$/ do |name|
5 5 end
6 6  
7 7 Then /^a helper should be generated for "(.*)"$/ do |name|
8   - assert_generated_helper_for(name)
  8 + assert_generated_file("app/helpers/#{name}_helper.rb")
9 9 end
10 10  
11 11 Then /^a helper test should be generated for "(.*)"$/ do |name|
12   - assert_generated_helper_test_for(name)
  12 + assert_generated_file("test/unit/helpers/#{name}_helper_test.rb")
13 13 end
14 14  
... ...
vendor/plugins/coulda/features/step_definitions/model_steps.rb
... ... @@ -28,26 +28,10 @@ end
28 28  
29 29 # MODEL
30 30  
31   -Then /^a model with comments should be generated for "(.*)"$/ do |model|
32   - model.downcase!
33   - assert_generated_model_for(model) do |body|
34   - comments = []
35   - comments << "# includes: mixed in behavior" <<
36   - "# properties: attributes, associations" <<
37   - "# lifecycle: validations, callbacks" <<
38   - "# class methods: self.method, named_scopes" <<
39   - "# instance methods" <<
40   - "# non-public interface: protected helpers"
41   - comments.each do |comment|
42   - assert body.include?(comment), body.inspect
43   - end
44   - end
45   -end
46   -
47 31 Then /^the "(.*)" model should have "(.*)" macro$/ do |model, macro|
48 32 model.downcase!
49   - assert_generated_model_for(model) do |body|
50   - assert body.include?(macro), body.inspect
  33 + assert_generated_file("app/models/#{model}.rb") do
  34 + macro
51 35 end
52 36 end
53 37  
... ... @@ -55,31 +39,28 @@ end
55 39  
56 40 Then /^a factory should be generated for "(.*)"$/ do |model|
57 41 model.downcase!
58   - assert_generated_factory_for(model) do |body|
59   - expected = "Factory.define :#{model.downcase} do |#{model.downcase}|\n" <<
60   - "end\n"
61   - assert_equal expected, body
  42 + assert_generated_file("test/factories/#{model}.rb") do
  43 + "Factory.define :#{model.downcase} do |#{model.downcase}|\n" <<
  44 + "end\n"
62 45 end
63 46 end
64 47  
65 48 Then /^a factory for "(.*)" should have an? "(.*)" (.*)$/ do |model, attr_name, attr_type|
66 49 model.downcase!
67   - assert_generated_factory_for(model) do |body|
68   - expected = "Factory.define :#{model} do |#{model}|\n" <<
69   - " #{model}.#{attr_name} { '#{attr_type}' }\n" <<
70   - "end\n"
71   - assert_equal expected, body
  50 + assert_generated_file("test/factories/#{model}.rb") do
  51 + "Factory.define :#{model} do |#{model}|\n" <<
  52 + " #{model}.#{attr_name} { '#{attr_type}' }\n" <<
  53 + "end\n"
72 54 end
73 55 end
74 56  
75 57 Then /^a factory for "(.*)" should have an association to "(.*)"$/ do |model, associated_model|
76 58 model.downcase!
77 59 associated_model.downcase!
78   - assert_generated_factory_for(model) do |body|
79   - expected = "Factory.define :#{model} do |#{model}|\n" <<
80   - " #{model}.association(:#{associated_model})\n" <<
81   - "end\n"
82   - assert_equal expected, body
  60 + assert_generated_file("test/factories/#{model}.rb") do
  61 + "Factory.define :#{model} do |#{model}|\n" <<
  62 + " #{model}.association(:#{associated_model})\n" <<
  63 + "end\n"
83 64 end
84 65 end
85 66  
... ... @@ -87,35 +68,32 @@ end
87 68  
88 69 Then /^a unit test should be generated for "(.*)"$/ do |model|
89 70 model.downcase!
90   - assert_generated_unit_test_for(model) do |body|
91   - match = "assert_valid Factory.build(:#{model})"
92   - assert body.include?(match), body.inspect
  71 + assert_generated_file("test/unit/#{model}_test.rb") do
  72 + "assert_valid Factory.build(:#{model})"
93 73 end
94 74 end
95 75  
96 76 Then /^the "(.*)" unit test should have "(.*)" macro$/ do |model, macro|
97 77 model.downcase!
98   - assert_generated_unit_test_for(model) do |body|
99   - assert body.include?(macro), body.inspect
  78 + assert_generated_file("test/unit/#{model}_test.rb") do
  79 + macro
100 80 end
101 81 end
102 82  
103 83 # MIGRATION
104 84  
105 85 Then /^the "(.*)" table should have db index on "(.*)"$/ do |table, foreign_key|
106   - assert_generated_migration(table) do |body|
107   - index = "add_index :#{table}, :#{foreign_key}"
108   - assert body.include?(index), body.inspect
  86 + assert_generated_migration(table) do
  87 + "add_index :#{table}, :#{foreign_key}"
109 88 end
110 89 end
111 90  
112 91 Then /^the "(.*)" table should have paperclip columns for "(.*)"$/ do |table, attr|
113   - up = " table.string :#{attr}_file_name\n" <<
114   - " table.string :#{attr}_content_type\n" <<
115   - " table.integer :#{attr}_file_size\n" <<
116   - " table.datetime :#{attr}_updated_at"
117   - assert_generated_migration(table) do |body|
118   - assert body.include?(up), body.inspect
  92 + assert_generated_migration(table) do
  93 + " table.string :#{attr}_file_name\n" <<
  94 + " table.string :#{attr}_content_type\n" <<
  95 + " table.integer :#{attr}_file_size\n" <<
  96 + " table.datetime :#{attr}_updated_at"
119 97 end
120 98 end
121 99  
... ...
vendor/plugins/coulda/features/step_definitions/view_steps.rb
... ... @@ -5,14 +5,12 @@ When /^I generate a &quot;([^\&quot;]*)&quot; view for &quot;([^\&quot;]*)&quot;$/ do |view, resource|
5 5 end
6 6  
7 7 When /^a standard "new" view for "posts" should be generated$/ do
8   - assert_generated_file("app/views/posts/new.html.erb") do |body|
9   - expected = "<h1>New post</h1>\n\n" <<
10   - "<% form_for(@post) do |form| %>\n" <<
11   - " <%= form.error_messages %>\n" <<
12   - " <%= form.submit 'Create', :disable_with => 'Please wait...' %>\n" <<
13   - "<% end %>"
14   - assert body.include?(expected),
15   - "expected #{expected} but was #{body.inspect}"
  8 + assert_generated_file("app/views/posts/new.html.erb") do
  9 + "<h1>New post</h1>\n\n" <<
  10 + "<% form_for(@post) do |form| %>\n" <<
  11 + " <%= form.error_messages %>\n" <<
  12 + " <%= form.submit 'Create', :disable_with => 'Please wait...' %>\n" <<
  13 + "<% end %>"
16 14 end
17 15 end
18 16  
... ...
vendor/plugins/coulda/features/support/env.rb
... ... @@ -2,52 +2,15 @@ require &#39;test/unit&#39;
2 2  
3 3 module Test::Unit::Assertions
4 4  
5   - def assert_generated_controller_for(name)
6   - assert_generated_file "app/controllers/#{name}_controller.rb" do |body|
7   - yield body if block_given?
8   - end
9   - end
10   -
11   - def assert_generated_model_for(name)
12   - assert_generated_file "app/models/#{name}.rb" do |body|
13   - yield body if block_given?
14   - end
15   - end
16   -
17   - def assert_generated_helper_for(name)
18   - assert_generated_file "app/helpers/#{name}_helper.rb" do |body|
19   - yield body if block_given?
20   - end
21   - end
22   -
23   - def assert_generated_factory_for(name)
24   - assert_generated_file "test/factories/#{name}.rb" do |body|
25   - yield body if block_given?
26   - end
27   - end
28   -
29   - def assert_generated_functional_test_for(name)
30   - assert_generated_file "test/functional/#{name}_controller_test.rb" do |body|
31   - yield body if block_given?
32   - end
33   - end
34   -
35   - def assert_generated_unit_test_for(name)
36   - assert_generated_file "test/unit/#{name}_test.rb" do |body|
37   - yield body if block_given?
38   - end
39   - end
40   -
41   - def assert_generated_helper_test_for(name)
42   - assert_generated_file "test/unit/helpers/#{name}_helper_test.rb" do |body|
43   - yield body if block_given?
44   - end
45   - end
46   -
47 5 def assert_generated_file(path)
48 6 assert_file_exists(path)
49   - File.open(File.join(@rails_root, path)) do |file|
50   - yield file.read if block_given?
  7 + if block_given?
  8 + File.open(File.join(@rails_root, path)) do |file|
  9 + expected = yield
  10 + body = file.read
  11 + assert body.include?(expected),
  12 + "expected #{expected} but was #{body.inspect}"
  13 + end
51 14 end
52 15 end
53 16  
... ... @@ -60,8 +23,8 @@ module Test::Unit::Assertions
60 23  
61 24 def assert_generated_views_for(name, *actions)
62 25 actions.each do |action|
63   - assert_generated_file("app/views/#{name}/#{action}.html.erb") do |body|
64   - yield body if block_given?
  26 + assert_generated_file("app/views/#{name}/#{action}.html.erb") do
  27 + yield if block_given?
65 28 end
66 29 end
67 30 end
... ... @@ -69,18 +32,14 @@ module Test::Unit::Assertions
69 32 def assert_generated_migration(name)
70 33 file = Dir.glob("#{@rails_root}/db/migrate/*_#{name}.rb").first
71 34 file = file.match(/db\/migrate\/[0-9]+_\w+/).to_s << ".rb"
72   - assert_generated_file file do |body|
73   - assert_match /timestamps/, body, "should have timestamps defined"
74   - yield body if block_given?
75   - end
  35 + assert_generated_file(file) { "timestamps" }
  36 + assert_generated_file(file) { yield if block_given? }
76 37 end
77 38  
78 39 def assert_generated_route_for(name, *actions)
79   - assert_generated_file("config/routes.rb") do |body|
80   - routeable_actions = actions.collect { |action| ":#{action}" }.join(", ")
81   - expected = " map.resources :#{name.to_s}, :only => [#{routeable_actions}]"
82   - assert body.include?(expected),
83   - "expected #{expected} but was #{body.inspect}"
  40 + routeable_actions = actions.collect { |action| ":#{action}" }.join(", ")
  41 + assert_generated_file("config/routes.rb") do
  42 + " map.resources :#{name.to_s}, :only => [#{routeable_actions}]"
84 43 end
85 44 end
86 45  
... ...
vendor/plugins/coulda/features/view_generator.feature
1   -Feature: Rails controller generator
2   - In order to better do Test-Driven Development with Rails
3   - As a user
4   - I want to generate Shoulda & Factory Girl tests for only RESTful actions I need.
  1 +Feature: Rails view generator
  2 + In order to do Test-Driven Development with Rails
  3 + As a developer
  4 + I want to generate a view to make a functional test pass
5 5  
6   - Scenario: View generator for new action when Cucumber is installed
7   - Given a Rails app with Cucumber
  6 + Scenario: View generator for new action
  7 + Given a Rails app
8 8 And the coulda plugin is installed
9 9 When I generate a "new" view for "Posts"
10 10 Then a standard "new" view for "posts" should be generated
11   - And a standard "posts" feature for the "new" scenario should be generated
12 11  
... ...
vendor/plugins/coulda/generators/controller/controller_generator.rb
1   -require File.join(File.dirname(__FILE__), "..", "support", "insert_commands")
  1 +require File.join(File.dirname(__FILE__), "..", "support", "generator_helper")
2 2  
3 3 class ControllerGenerator < Rails::Generator::NamedBase
4 4 def manifest
... ... @@ -17,9 +17,6 @@ class ControllerGenerator &lt; Rails::Generator::NamedBase
17 17 File.join('test/functional',
18 18 class_path,
19 19 "#{file_name}_controller_test.rb")
20   -
21   - m.insert_into "config/routes.rb",
22   - "map.resources :#{file_name}, :only => [#{routeable_actions}]"
23 20 end
24 21 end
25 22  
... ...
vendor/plugins/coulda/generators/controller/templates/controller.rb
1 1 class <%= class_name %>Controller < ApplicationController
2   -<% resource = file_name.singularize -%>
3   -<% resources = file_name.pluralize -%>
4   -<% resource_class = class_name.singularize -%>
5   -
6 2 <% if actions.include?("index") -%>
7 3 def index
8 4 end
... ...
vendor/plugins/coulda/generators/controller/templates/functional_test.rb
1 1 require 'test_helper'
2 2  
3 3 class <%= class_name %>ControllerTest < ActionController::TestCase
4   -<% resource = file_name.singularize -%>
5   -<% resources = file_name.pluralize -%>
6   -<% resource_class = class_name.singularize -%>
7   -
8 4 <% if actions.include?("index") -%>
9 5 context 'GET to index' do
10 6 setup { get :index }
... ...
vendor/plugins/coulda/generators/feature/feature_generator.rb 0 → 100644
... ... @@ -0,0 +1,28 @@
  1 +require File.join(File.dirname(__FILE__), "..", "support", "generator_helper")
  2 +
  3 +class FeatureGenerator < Rails::Generator::NamedBase
  4 + def manifest
  5 + record do |m|
  6 + m.directory 'features'
  7 + m.directory 'features/step_definitions'
  8 + m.directory 'features/support'
  9 +
  10 + path = File.join('features', "#{resources}.feature")
  11 + m.template 'feature.feature', path
  12 +
  13 + path = File.join('features', 'step_definitions', "#{resources}_steps.rb")
  14 + m.template 'step_definition.rb', path
  15 +
  16 + path = File.join('features', 'support', "paths.rb")
  17 + m.insert_into path, insertable_path
  18 + end
  19 + end
  20 +
  21 + def insertable_path
  22 + if %w(new create).any? { |action| actions.include?(action) }
  23 + " when /the new #{resource} page/i\n" <<
  24 + " new_#{resource}_path\n"
  25 + end
  26 + end
  27 +end
  28 +
... ...
vendor/plugins/coulda/generators/feature/templates/feature.feature 0 → 100644
... ... @@ -0,0 +1,6 @@
  1 +<% if %w(new create).any? { |action| actions.include?(action) } -%>
  2 + Scenario: Create a new <%= resource %>
  3 + Given I am on the new <%= resource %> page
  4 + When I create a <%= resource %> named "A new <%= resource %>"
  5 + Then I should see "A new <%= resource %>"
  6 +<% end -%>
... ...
vendor/plugins/coulda/generators/feature/templates/step_definition.rb 0 → 100644
... ... @@ -0,0 +1,4 @@
  1 +When /^I create a <%= resource %> named "([^\"]*)"$/ do |name|
  2 + fills_in :name, :with => name
  3 + click_button 'Create'
  4 +end
... ...
vendor/plugins/coulda/generators/helper/helper_generator.rb
  1 +require File.join(File.dirname(__FILE__), "..", "support", "generator_helper")
  2 +
1 3 class HelperGenerator < Rails::Generator::NamedBase
2 4 def manifest
3 5 record do |m|
... ...
vendor/plugins/coulda/generators/model/model_generator.rb
  1 +require File.join(File.dirname(__FILE__), "..", "support", "generator_helper")
  2 +
1 3 class ModelGenerator < Rails::Generator::NamedBase
2 4 default_options :skip_timestamps => false,
3 5 :skip_migration => false,
... ...
vendor/plugins/coulda/generators/model/templates/unit_test.rb
1   -require File.dirname(__FILE__) + '/../test_helper'
  1 +require 'test_helper'
2 2  
3 3 class <%= class_name %>Test < ActiveSupport::TestCase
4 4 should "be valid with factory" do
... ... @@ -12,5 +12,5 @@ class &lt;%= class_name %&gt;Test &lt; ActiveSupport::TestCase
12 12 <% if attribute.type == :paperclip -%>
13 13 should_have_attached_file :<%= attribute.name %>
14 14 <% end -%>
15   -<% end -%>
  15 +<% end -%>
16 16 end
... ...
vendor/plugins/coulda/generators/support/generator_helper.rb 0 → 100644
... ... @@ -0,0 +1,31 @@
  1 +require File.join(File.dirname(__FILE__), "insert_commands")
  2 +
  3 +module Coulda
  4 + module GeneratorHelper
  5 + REMOVABLE_COLUMNS = ["created_at", "updated_at", "email_confirmed",
  6 + "encrypted_password", "salt", "token", "token_expires_at"]
  7 +
  8 + def resource
  9 + file_name.singularize
  10 + end
  11 +
  12 + def resources
  13 + file_name.pluralize
  14 + end
  15 +
  16 + def resource_class
  17 + class_name.singularize
  18 + end
  19 +
  20 + def columns_for_form
  21 + resource_class.content_columns.
  22 + collect { |column| [column.name, column.type] }.
  23 + delete_if { |column| REMOVABLE_COLUMNS.include?(column.first) }
  24 + end
  25 + end
  26 +end
  27 +
  28 +class Rails::Generator::NamedBase
  29 + include Coulda::GeneratorHelper
  30 +end
  31 +
... ...
vendor/plugins/coulda/generators/support/insert_commands.rb
... ... @@ -9,10 +9,15 @@ end
9 9 Rails::Generator::Commands::Create.class_eval do
10 10 def insert_into(file, line)
11 11 logger.insert "#{line} into #{file}"
12   - unless options[:pretend] || file_contains?(file, line)
13   - start_of_routes_file = "ActionController::Routing::Routes.draw"
14   - gsub_file file, /^(class|module|#{start_of_routes_file}) .+$/ do |match|
15   - "#{match}\n #{line}"
  12 + unless file_contains?(file, line)
  13 + if file =~ /^module NavigationHelpers/
  14 + gsub_file file, /#{Coulda::Insertable.cucumber_paths}/ do |match|
  15 + "#{match}\n#{line}"
  16 + end
  17 + else
  18 + gsub_file file, /^(class|module|#{Coulda::Insertable.routes}) .+$/ do |match|
  19 + "#{match}\n #{line}"
  20 + end
16 21 end
17 22 end
18 23 end
... ... @@ -21,9 +26,7 @@ end
21 26 Rails::Generator::Commands::Destroy.class_eval do
22 27 def insert_into(file, line)
23 28 logger.remove "#{line} from #{file}"
24   - unless options[:pretend]
25   - gsub_file file, "\n #{line}", ''
26   - end
  29 + gsub_file file, "\n #{line}", ''
27 30 end
28 31 end
29 32  
... ... @@ -33,3 +36,15 @@ Rails::Generator::Commands::List.class_eval do
33 36 end
34 37 end
35 38  
  39 +module Coulda
  40 + module Insertable
  41 + def self.routes
  42 + "ActionController::Routing::Routes.draw"
  43 + end
  44 +
  45 + def self.cucumber_paths
  46 + "case page_name\n"
  47 + end
  48 + end
  49 +end
  50 +
... ...
vendor/plugins/coulda/generators/view/templates/feature.feature
... ... @@ -1,10 +0,0 @@
1   -<% resource = file_name.singularize -%>
2   -<% resources = file_name.pluralize -%>
3   -<% resource_class = class_name.singularize -%>
4   -
5   -<% if %w(new create).any? { |action| actions.include?(action) } -%>
6   - Scenario: Create a new '<%= resource %>'
7   - Given I am on the new <%= resource %> page
8   - When I create a '<%= resource %>' named 'A new <%= resource %>'
9   - Then I should see 'A new <%= resource %>'
10   -<% end -%>
vendor/plugins/coulda/generators/view/templates/view_new.html.erb
1   -<% resource = file_name.singularize -%>
2 1 <h1>New <%= resource %></h1>
3 2  
4 3 <%% form_for(@<%= resource %>) do |form| %>
... ...
vendor/plugins/coulda/generators/view/templates/view_show.html.erb
1   -<h1><%= singular_name %></h1>
  1 +<h1><%= resource %></h1>
2 2  
3   -<%%= link_to 'Edit', edit_<%= singular_name %>_path(@<%= singular_name %>) %>
  3 +<%%= link_to 'Edit', edit_<%= resource %>_path(@<%= resource %>) %>
4 4  
... ...
vendor/plugins/coulda/generators/view/view_generator.rb
  1 +require File.join(File.dirname(__FILE__), "..", "support", "generator_helper")
  2 +
1 3 class ViewGenerator < Rails::Generator::NamedBase
2 4 def manifest
3 5 record do |m|
4 6 m.directory File.join('app/views', class_path, file_name)
5   - m.directory 'features'
6 7  
7 8 if actions.include?("new")
8 9 path = File.join('app/views', class_path, file_name, "new.html.erb")
9 10 m.template 'view_new.html.erb', path
10   -
11   - path = File.join('features', "#{file_name.pluralize}.feature")
12   - m.template 'feature.feature', path
13 11 end
14 12 end
15 13 end
... ...