saasy 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (146) hide show
  1. data/CHANGELOG.md +114 -0
  2. data/Gemfile +26 -0
  3. data/README.md +118 -0
  4. data/Rakefile +38 -0
  5. data/app/controllers/accounts_controller.rb +68 -0
  6. data/app/controllers/billings_controller.rb +25 -0
  7. data/app/controllers/invitations_controller.rb +65 -0
  8. data/app/controllers/memberships_controller.rb +45 -0
  9. data/app/controllers/plans_controller.rb +24 -0
  10. data/app/controllers/profiles_controller.rb +19 -0
  11. data/app/helpers/limits_helper.rb +13 -0
  12. data/app/mailers/billing_mailer.rb +53 -0
  13. data/app/mailers/invitation_mailer.rb +18 -0
  14. data/app/models/invitation.rb +113 -0
  15. data/app/models/limit.rb +49 -0
  16. data/app/models/membership.rb +26 -0
  17. data/app/models/permission.rb +19 -0
  18. data/app/models/signup.rb +163 -0
  19. data/app/views/accounts/_account.html.erb +9 -0
  20. data/app/views/accounts/_blank_slate.html.erb +6 -0
  21. data/app/views/accounts/_projects.html.erb +12 -0
  22. data/app/views/accounts/_subnav.html.erb +10 -0
  23. data/app/views/accounts/edit.html.erb +34 -0
  24. data/app/views/accounts/index.html.erb +9 -0
  25. data/app/views/accounts/new.html.erb +36 -0
  26. data/app/views/billing_mailer/completed_trial.text.erb +13 -0
  27. data/app/views/billing_mailer/expiring_trial.text.erb +15 -0
  28. data/app/views/billing_mailer/new_unactivated.text.erb +1 -0
  29. data/app/views/billing_mailer/problem.html.erb +13 -0
  30. data/app/views/billing_mailer/problem.text.erb +14 -0
  31. data/app/views/billing_mailer/receipt.html.erb +41 -0
  32. data/app/views/billing_mailer/receipt.text.erb +25 -0
  33. data/app/views/billings/_form.html.erb +8 -0
  34. data/app/views/billings/edit.html.erb +13 -0
  35. data/app/views/billings/show.html.erb +29 -0
  36. data/app/views/invitation_mailer/invitation.text.erb +6 -0
  37. data/app/views/invitations/new.html.erb +17 -0
  38. data/app/views/invitations/show.html.erb +22 -0
  39. data/app/views/layouts/saucy.html.erb +36 -0
  40. data/app/views/limits/_meter.html.erb +13 -0
  41. data/app/views/memberships/edit.html.erb +21 -0
  42. data/app/views/memberships/index.html.erb +17 -0
  43. data/app/views/plans/_plan.html.erb +32 -0
  44. data/app/views/plans/_terms.html.erb +15 -0
  45. data/app/views/plans/edit.html.erb +33 -0
  46. data/app/views/plans/index.html.erb +12 -0
  47. data/app/views/profiles/_inputs.html.erb +5 -0
  48. data/app/views/profiles/edit.html.erb +36 -0
  49. data/app/views/projects/_form.html.erb +36 -0
  50. data/app/views/projects/edit.html.erb +22 -0
  51. data/app/views/projects/index.html.erb +28 -0
  52. data/app/views/projects/new.html.erb +13 -0
  53. data/app/views/projects/show.html.erb +0 -0
  54. data/app/views/shared/_project_dropdown.html.erb +55 -0
  55. data/app/views/shared/_saucy_javascript.html.erb +33 -0
  56. data/config/locales/en.yml +37 -0
  57. data/config/routes.rb +19 -0
  58. data/features/run_features.feature +83 -0
  59. data/features/step_definitions/clearance_steps.rb +45 -0
  60. data/features/step_definitions/rails_steps.rb +73 -0
  61. data/features/step_definitions/saucy_steps.rb +8 -0
  62. data/features/support/env.rb +4 -0
  63. data/features/support/file.rb +11 -0
  64. data/lib/generators/saucy/base.rb +18 -0
  65. data/lib/generators/saucy/features/features_generator.rb +91 -0
  66. data/lib/generators/saucy/features/templates/README +3 -0
  67. data/lib/generators/saucy/features/templates/factories.rb +71 -0
  68. data/lib/generators/saucy/features/templates/features/edit_profile.feature +9 -0
  69. data/lib/generators/saucy/features/templates/features/edit_project_permissions.feature +37 -0
  70. data/lib/generators/saucy/features/templates/features/edit_user_permissions.feature +47 -0
  71. data/lib/generators/saucy/features/templates/features/manage_account.feature +35 -0
  72. data/lib/generators/saucy/features/templates/features/manage_billing.feature +93 -0
  73. data/lib/generators/saucy/features/templates/features/manage_plan.feature +143 -0
  74. data/lib/generators/saucy/features/templates/features/manage_projects.feature +139 -0
  75. data/lib/generators/saucy/features/templates/features/manage_users.feature +142 -0
  76. data/lib/generators/saucy/features/templates/features/new_account.feature +33 -0
  77. data/lib/generators/saucy/features/templates/features/project_dropdown.feature +77 -0
  78. data/lib/generators/saucy/features/templates/features/sign_up.feature +32 -0
  79. data/lib/generators/saucy/features/templates/features/sign_up_paid.feature +65 -0
  80. data/lib/generators/saucy/features/templates/features/trial_plans.feature +82 -0
  81. data/lib/generators/saucy/features/templates/step_definitions/account_steps.rb +30 -0
  82. data/lib/generators/saucy/features/templates/step_definitions/braintree_steps.rb +25 -0
  83. data/lib/generators/saucy/features/templates/step_definitions/cron_steps.rb +23 -0
  84. data/lib/generators/saucy/features/templates/step_definitions/email_steps.rb +40 -0
  85. data/lib/generators/saucy/features/templates/step_definitions/factory_girl_steps.rb +1 -0
  86. data/lib/generators/saucy/features/templates/step_definitions/html_steps.rb +51 -0
  87. data/lib/generators/saucy/features/templates/step_definitions/plan_steps.rb +16 -0
  88. data/lib/generators/saucy/features/templates/step_definitions/project_steps.rb +4 -0
  89. data/lib/generators/saucy/features/templates/step_definitions/session_steps.rb +37 -0
  90. data/lib/generators/saucy/features/templates/step_definitions/user_steps.rb +100 -0
  91. data/lib/generators/saucy/features/templates/support/braintree.rb +5 -0
  92. data/lib/generators/saucy/install/install_generator.rb +40 -0
  93. data/lib/generators/saucy/install/templates/controllers/projects_controller.rb +3 -0
  94. data/lib/generators/saucy/install/templates/create_saucy_tables.rb +115 -0
  95. data/lib/generators/saucy/install/templates/models/account.rb +3 -0
  96. data/lib/generators/saucy/install/templates/models/plan.rb +3 -0
  97. data/lib/generators/saucy/install/templates/models/project.rb +3 -0
  98. data/lib/generators/saucy/specs/specs_generator.rb +20 -0
  99. data/lib/generators/saucy/specs/templates/support/braintree.rb +5 -0
  100. data/lib/generators/saucy/views/views_generator.rb +23 -0
  101. data/lib/saucy.rb +10 -0
  102. data/lib/saucy/account.rb +132 -0
  103. data/lib/saucy/account_authorization.rb +67 -0
  104. data/lib/saucy/configuration.rb +29 -0
  105. data/lib/saucy/engine.rb +35 -0
  106. data/lib/saucy/fake_braintree.rb +134 -0
  107. data/lib/saucy/layouts.rb +36 -0
  108. data/lib/saucy/plan.rb +54 -0
  109. data/lib/saucy/project.rb +125 -0
  110. data/lib/saucy/projects_controller.rb +94 -0
  111. data/lib/saucy/railties/tasks.rake +28 -0
  112. data/lib/saucy/routing_extensions.rb +121 -0
  113. data/lib/saucy/subscription.rb +237 -0
  114. data/lib/saucy/user.rb +30 -0
  115. data/spec/controllers/accounts_controller_spec.rb +228 -0
  116. data/spec/controllers/application_controller_spec.rb +32 -0
  117. data/spec/controllers/invitations_controller_spec.rb +215 -0
  118. data/spec/controllers/memberships_controller_spec.rb +117 -0
  119. data/spec/controllers/plans_controller_spec.rb +13 -0
  120. data/spec/controllers/profiles_controller_spec.rb +48 -0
  121. data/spec/controllers/projects_controller_spec.rb +216 -0
  122. data/spec/environment.rb +95 -0
  123. data/spec/layouts_spec.rb +21 -0
  124. data/spec/mailers/billing_mailer_spec.rb +68 -0
  125. data/spec/mailers/invitiation_mailer_spec.rb +19 -0
  126. data/spec/models/account_spec.rb +218 -0
  127. data/spec/models/invitation_spec.rb +320 -0
  128. data/spec/models/limit_spec.rb +70 -0
  129. data/spec/models/membership_spec.rb +37 -0
  130. data/spec/models/permission_spec.rb +30 -0
  131. data/spec/models/plan_spec.rb +81 -0
  132. data/spec/models/project_spec.rb +223 -0
  133. data/spec/models/signup_spec.rb +177 -0
  134. data/spec/models/subscription_spec.rb +481 -0
  135. data/spec/models/user_spec.rb +72 -0
  136. data/spec/route_extensions_spec.rb +51 -0
  137. data/spec/saucy_spec.rb +62 -0
  138. data/spec/scaffold/config/routes.rb +5 -0
  139. data/spec/spec_helper.rb +39 -0
  140. data/spec/support/authentication_helpers.rb +81 -0
  141. data/spec/support/authorization_helpers.rb +56 -0
  142. data/spec/support/braintree.rb +7 -0
  143. data/spec/support/clearance_matchers.rb +55 -0
  144. data/spec/support/notifications.rb +57 -0
  145. data/spec/views/accounts/_account.html.erb_spec.rb +37 -0
  146. metadata +325 -0
@@ -0,0 +1,30 @@
1
+ module Saucy
2
+ module User
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ attr_accessible :name, :project_ids, :email, :password
7
+ has_many :memberships
8
+ has_many :accounts, :through => :memberships
9
+ has_many :permissions
10
+ has_many :projects, :through => :permissions
11
+ validates_presence_of :name
12
+ end
13
+
14
+ module InstanceMethods
15
+ def admin_of?(account)
16
+ memberships.exists?(:account_id => account.id, :admin => true)
17
+ end
18
+
19
+ def member_of?(account_or_project)
20
+ account_or_project.has_member?(self)
21
+ end
22
+ end
23
+
24
+ module ClassMethods
25
+ def by_name
26
+ order('users.name')
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,228 @@
1
+ require 'spec_helper'
2
+
3
+ describe AccountsController, "routes" do
4
+ it { should route(:get, "/plans/abc/accounts/new").
5
+ to(:action => :new, :plan_id => :abc) }
6
+ it { should route(:get, "/accounts").to(:action => :index) }
7
+ it { should route(:post, "/plans/abc/accounts").
8
+ to(:action => :create, :plan_id => :abc) }
9
+ it { should route(:put, "/accounts/1").to(:action => :update, :id => 1) }
10
+ it { should route(:get, "/accounts/1/edit").to(:action => :edit, :id => 1) }
11
+ it { should route(:delete, "/accounts/1").to(:action => :destroy, :id => 1) }
12
+ end
13
+
14
+ describe AccountsController, "new" do
15
+ let(:signup) { stub('signup') }
16
+ let(:plan) { Factory(:plan) }
17
+
18
+ before do
19
+ Signup.stubs(:new => signup)
20
+ get :new, :plan_id => plan.to_param
21
+ end
22
+
23
+ it "renders the new account form" do
24
+ should respond_with(:success)
25
+ should render_template(:new)
26
+ end
27
+
28
+ it "assigns a new signup" do
29
+ Signup.should have_received(:new)
30
+ should assign_to(:signup).with(signup)
31
+ end
32
+
33
+ it "notifies observers" do
34
+ should notify_observers("plan_viewed", :plan => plan, :request => request)
35
+ end
36
+ end
37
+
38
+ describe AccountsController, "successful create for a confirmed user" do
39
+ let(:user) { Factory.stub(:user) }
40
+ let(:account) { Factory.stub(:account) }
41
+ let(:signup) { stub('signup', :user => user,
42
+ :user= => nil,
43
+ :plan= => plan,
44
+ :account => account) }
45
+ let(:signup_attributes) { "attributes" }
46
+ let(:plan) { Factory(:plan) }
47
+
48
+ before do
49
+ Signup.stubs(:new => signup)
50
+ signup.stubs(:save => true)
51
+ sign_in_as user
52
+ post :create, :signup => signup_attributes, :plan_id => plan.to_param
53
+ end
54
+
55
+ it "creates an signup" do
56
+ Signup.should have_received(:new).with(signup_attributes)
57
+ signup.should have_received(:save)
58
+ end
59
+
60
+ it "redirects to the root" do
61
+ should redirect_to(new_account_project_url(signup.account))
62
+ end
63
+
64
+ it "sets the current user" do
65
+ signup.should have_received(:user=).with(user)
66
+ end
67
+
68
+ it { should set_the_flash.to(/created/i) }
69
+ it { should_not set_the_flash.to(/confirm/i) }
70
+ it { should be_signed_in.as(user) }
71
+
72
+ it "notifies observers" do
73
+ should notify_observers("account_created", :account => signup.account,
74
+ :request => request)
75
+ end
76
+ end
77
+
78
+ describe AccountsController, "failed create" do
79
+ let(:signup) { stub('signup', :user= => nil, :plan= => plan) }
80
+ let(:signup_attributes) { "attributes" }
81
+ let(:plan) { Factory(:plan) }
82
+
83
+ before do
84
+ Signup.stubs(:new => signup)
85
+ signup.stubs(:save => false)
86
+ post :create, :signup => signup_attributes, :plan_id => plan.to_param
87
+ end
88
+
89
+ it "creates an signup" do
90
+ Signup.should have_received(:new).with(signup_attributes)
91
+ signup.should have_received(:save)
92
+ end
93
+
94
+ it "renders the new signup form" do
95
+ should respond_with(:success)
96
+ should render_template(:new)
97
+ end
98
+
99
+ it "assigns a new signup" do
100
+ Signup.should have_received(:new)
101
+ should assign_to(:signup).with(signup)
102
+ end
103
+ end
104
+
105
+ describe AccountsController, "index with multiple projects" do
106
+ let(:user) { Factory.stub(:user) }
107
+ let(:accounts) { %w(one two) }
108
+ let(:projects) { %w(one two) }
109
+
110
+ before do
111
+ user.stubs(:accounts => accounts)
112
+ user.stubs(:projects => projects)
113
+ sign_in_as user
114
+ get :index
115
+ end
116
+
117
+ it "renders the dashboard page" do
118
+ should respond_with(:success)
119
+ should render_template(:index)
120
+ end
121
+
122
+ it "assigns the user's accounts" do
123
+ user.should have_received(:accounts)
124
+ should assign_to(:accounts).with(accounts)
125
+ end
126
+ end
127
+
128
+ describe AccountsController, "signed out" do
129
+ it "redirects to sign_in on index" do
130
+ get :index
131
+ should redirect_to(sign_in_path)
132
+ end
133
+ it "redirects to sign_in on edit" do
134
+ get :edit, :id => 1
135
+ should redirect_to(sign_in_path)
136
+ end
137
+ it "redirects to sign_in on update" do
138
+ put :update, :id => 1, :account => {}
139
+ should redirect_to(sign_in_path)
140
+ end
141
+ end
142
+
143
+ describe AccountsController, "index with one project" do
144
+ let(:user) { Factory.stub(:user) }
145
+ let(:accounts) { %w(one two) }
146
+ let(:projects) { [Factory.stub(:project)] }
147
+
148
+ before do
149
+ user.stubs(:accounts => accounts)
150
+ user.stubs(:projects => projects)
151
+ sign_in_as user
152
+ get :index
153
+ end
154
+
155
+ it "redirects to the project" do
156
+ should redirect_to(controller.project_url(projects.first))
157
+ end
158
+ end
159
+
160
+ describe AccountsController, "valid update", :as => :account_admin do
161
+ before do
162
+ put :update,
163
+ :account => Factory.attributes_for(:account),
164
+ :id => account.to_param
165
+ end
166
+
167
+ it "redirects to settings" do
168
+ should redirect_to(edit_profile_url)
169
+ end
170
+
171
+ it { should set_the_flash.to(/updated/) }
172
+ end
173
+
174
+ describe AccountsController, "invalid update", :as => :account_admin do
175
+ before do
176
+ put :update,
177
+ :account => {:name => ""},
178
+ :id => account.to_param
179
+ end
180
+
181
+ it { should respond_with(:success) }
182
+ it { should render_template(:edit) }
183
+ end
184
+
185
+ describe AccountsController, "edit", :as => :account_admin do
186
+ before do
187
+ get :edit, :id => account.to_param
188
+ end
189
+
190
+ it "renders the edit template" do
191
+ should respond_with(:success)
192
+ should render_template(:edit)
193
+ end
194
+
195
+ it "assigns the account" do
196
+ should assign_to(:account).with(account)
197
+ end
198
+ end
199
+
200
+ describe AccountsController, "destroy", :as => :account_admin do
201
+ before do
202
+ Account.stubs(:find_by_keyword! => account)
203
+ account.stubs(:destroy)
204
+ delete :destroy, :id => account.to_param
205
+ end
206
+
207
+ it "redirects to the root url" do
208
+ should redirect_to("/")
209
+ end
210
+
211
+ it "sets the flash" do
212
+ should set_the_flash.to(/deleted/i)
213
+ end
214
+
215
+ it "deletes the account" do
216
+ account.should have_received(:destroy)
217
+ end
218
+ end
219
+
220
+ describe AccountsController, "permissions", :as => :account_member do
221
+ it { should deny_access.
222
+ on(:get, :edit, :id => account.to_param).
223
+ flash(/admin/) }
224
+ it { should deny_access.
225
+ on(:put, :update, :id => account.to_param).
226
+ flash(/admin/) }
227
+ end
228
+
@@ -0,0 +1,32 @@
1
+ require 'spec_helper'
2
+
3
+ describe ApplicationController do
4
+
5
+ describe "with a valid account id in the params" do
6
+ before do
7
+ @account = Factory(:account)
8
+ @controller.stubs(:params).returns(:account_id => @account.to_param)
9
+ end
10
+
11
+ it "should return the corresponding account from current_account" do
12
+ @controller.__send__(:current_account).should == @account
13
+ end
14
+ end
15
+
16
+ describe "with an invalid account id in the params" do
17
+ before do
18
+ @controller.stubs(:params).returns(:account_id => "invalid")
19
+ end
20
+
21
+ it "should return the corresponding account from current_account" do
22
+ expect { @controller.__send__(:current_account) }.
23
+ to raise_error(ActiveRecord::RecordNotFound)
24
+ end
25
+ end
26
+
27
+ it { should filter_param(:card_number) }
28
+ it { should filter_param(:cardholder_name) }
29
+ it { should filter_param(:verification_code) }
30
+ it { should filter_param(:expiration_month) }
31
+ it { should filter_param(:expiration_year) }
32
+ end
@@ -0,0 +1,215 @@
1
+ require 'spec_helper'
2
+
3
+ describe InvitationsController, "routes" do
4
+ it { should route(:get, "/accounts/abc/invitations/new").
5
+ to(:action => :new, :account_id => 'abc') }
6
+ it { should route(:post, "/accounts/abc/invitations").
7
+ to(:action => :create, :account_id => 'abc') }
8
+ it { should route(:get, "/accounts/abc/invitations/xyz").
9
+ to(:action => :show, :account_id => 'abc', :id => 'xyz') }
10
+ it { should route(:put, "/accounts/abc/invitations/xyz").
11
+ to(:action => :update, :account_id => 'abc', :id => 'xyz') }
12
+ end
13
+
14
+ describe InvitationsController, "permissions" do
15
+ let(:account) { Factory(:account) }
16
+ before { sign_in }
17
+ it { should deny_access.
18
+ on(:get, :new, :account_id => account.to_param).
19
+ flash(/admin/) }
20
+ it { should deny_access.
21
+ on(:post, :create, :account_id => account.to_param).
22
+ flash(/admin/) }
23
+ end
24
+
25
+ describe InvitationsController, "new", :as => :account_admin do
26
+ let(:invitation) { Invitation.new }
27
+ let(:projects) { ['one', 'two'] }
28
+
29
+ before do
30
+ Account.stubs(:find_by_keyword! => account)
31
+ account.stubs(:projects_by_name => projects)
32
+ Invitation.stubs(:new => invitation)
33
+ get :new, :account_id => account.to_param
34
+ end
35
+
36
+ it "renders the new template" do
37
+ should respond_with(:success)
38
+ should render_template(:new)
39
+ end
40
+
41
+ it "assigns an invitation" do
42
+ Invitation.should have_received(:new)
43
+ should assign_to(:invitation).with(invitation)
44
+ end
45
+
46
+ it "assigns projects" do
47
+ should assign_to(:projects).with(projects)
48
+ end
49
+ end
50
+
51
+ describe InvitationsController, "valid create", :as => :account_admin do
52
+ let(:invitation) { Factory.stub(:invitation) }
53
+ let(:attributes) { 'attributes' }
54
+
55
+ before do
56
+ Invitation.stubs(:new => invitation)
57
+ invitation.stubs(:account=)
58
+ invitation.stubs(:sender=)
59
+ invitation.stubs(:save => true)
60
+ post :create, :account_id => account.to_param, :invitation => attributes
61
+ end
62
+
63
+ it "redirects to the membership index" do
64
+ should redirect_to(account_memberships_url(account))
65
+ end
66
+
67
+ it "saves an invitation" do
68
+ Invitation.should have_received(:new).with(attributes)
69
+ invitation.should have_received(:account=).with(account)
70
+ invitation.should have_received(:sender=).with(current_user)
71
+ invitation.should have_received(:save)
72
+ end
73
+
74
+ it "sets a flash message" do
75
+ should set_the_flash.to(/invited/i)
76
+ end
77
+ end
78
+
79
+ describe InvitationsController, "invalid create", :as => :account_admin do
80
+ let(:invitation) { Factory.stub(:invitation) }
81
+ let(:projects) { ['one', 'two'] }
82
+
83
+ before do
84
+ Invitation.stubs(:new => invitation)
85
+ invitation.stubs(:save => false)
86
+ Account.stubs(:find_by_keyword! => account)
87
+ account.stubs(:projects_by_name => projects)
88
+ post :create, :account_id => account.to_param, :invitation => {}
89
+ end
90
+
91
+ it "renders the new template" do
92
+ should respond_with(:success)
93
+ should render_template(:new)
94
+ end
95
+
96
+ it "doesn't set a flash message" do
97
+ should_not set_the_flash
98
+ end
99
+
100
+ it "assigns projects" do
101
+ should assign_to(:projects).with(projects)
102
+ end
103
+ end
104
+
105
+ describe InvitationsController, "show" do
106
+ let(:invitation) { Factory.stub(:invitation, :code => 'abc') }
107
+ let(:account) { invitation.account }
108
+
109
+ before do
110
+ Invitation.stubs(:find_by_code! => invitation)
111
+ get :show, :id => invitation.to_param, :account_id => account.to_param
112
+ end
113
+
114
+ it "renders the show template" do
115
+ should respond_with(:success)
116
+ should render_template(:show)
117
+ end
118
+
119
+ it "assigns the invitation" do
120
+ Invitation.should have_received(:find_by_code!).with(invitation.to_param)
121
+ should assign_to(:invitation).with(invitation)
122
+ end
123
+ end
124
+
125
+ describe InvitationsController, "show for a used invitation" do
126
+ let(:invitation) { Factory.stub(:invitation, :code => 'abc', :used => true) }
127
+ let(:account) { invitation.account }
128
+
129
+ before do
130
+ Invitation.stubs(:find_by_code! => invitation)
131
+ get :show, :id => invitation.to_param, :account_id => account.to_param
132
+ end
133
+
134
+ it "redirects to the root url" do
135
+ should redirect_to("/")
136
+ end
137
+
138
+ it "sets a flash message" do
139
+ should set_the_flash.to(/used/i)
140
+ end
141
+ end
142
+
143
+ describe InvitationsController, "valid update" do
144
+ let(:invitation) { Factory.stub(:invitation, :code => 'abc') }
145
+ let(:account) { invitation.account }
146
+ let(:attributes) { 'attributes' }
147
+ let(:user) { Factory.stub(:user) }
148
+
149
+ before do
150
+ Invitation.stubs(:find_by_code! => invitation)
151
+ invitation.stubs(:accept => true)
152
+ invitation.stubs(:user => user)
153
+ put :update, :id => invitation.to_param,
154
+ :account_id => account.to_param,
155
+ :invitation => attributes
156
+ end
157
+
158
+ it "signs the user in" do
159
+ should be_signed_in.as(user)
160
+ end
161
+
162
+ it "accepts the invitation" do
163
+ Invitation.should have_received(:find_by_code!).with(invitation.to_param)
164
+ invitation.should have_received(:accept).with(attributes)
165
+ end
166
+
167
+ it "redirects to the root page" do
168
+ should redirect_to(root_url)
169
+ end
170
+ end
171
+
172
+ describe InvitationsController, "invalid update" do
173
+ let(:invitation) { Factory.stub(:invitation, :code => 'abc') }
174
+ let(:account) { invitation.account }
175
+
176
+ before do
177
+ Invitation.stubs(:find_by_code! => invitation)
178
+ invitation.stubs(:accept => false)
179
+ put :update, :id => invitation.to_param,
180
+ :account_id => account.to_param,
181
+ :invitation => {}
182
+ end
183
+
184
+ it "doesn't sign in" do
185
+ should_not be_signed_in
186
+ end
187
+
188
+ it "renders the show template" do
189
+ should respond_with(:success)
190
+ should render_template(:show)
191
+ end
192
+
193
+ it "assigns the invitation" do
194
+ should assign_to(:invitation).with(invitation)
195
+ end
196
+ end
197
+
198
+ describe InvitationsController, "update for a used invitation" do
199
+ let(:invitation) { Factory.stub(:invitation, :code => 'abc', :used => true) }
200
+ let(:account) { invitation.account }
201
+
202
+ before do
203
+ Invitation.stubs(:find_by_code! => invitation)
204
+ put :update, :id => invitation.to_param, :account_id => account.to_param
205
+ end
206
+
207
+ it "redirects to the root url" do
208
+ should redirect_to("/")
209
+ end
210
+
211
+ it "sets a flash message" do
212
+ should set_the_flash.to(/used/i)
213
+ end
214
+ end
215
+