paid_up 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (149) hide show
  1. checksums.yaml +7 -0
  2. data/.rspec +2 -0
  3. data/.travis.yml +3 -0
  4. data/Gemfile +46 -0
  5. data/LICENSE.txt +20 -0
  6. data/MIT-LICENSE +20 -0
  7. data/README.md +64 -0
  8. data/Rakefile +48 -0
  9. data/VERSION +1 -0
  10. data/app/controllers/paid_up/paid_up_controller.rb +12 -0
  11. data/app/controllers/paid_up/plans_controller.rb +7 -0
  12. data/app/controllers/paid_up/subscriptions_controller.rb +37 -0
  13. data/app/helpers/paid_up/features_helper.rb +65 -0
  14. data/app/helpers/paid_up/paid_up_helper.rb +14 -0
  15. data/app/helpers/paid_up/plans_helper.rb +53 -0
  16. data/app/helpers/paid_up/subscriptions_helper.rb +21 -0
  17. data/app/models/ability.rb +37 -0
  18. data/app/models/paid_up/feature.rb +19 -0
  19. data/app/models/paid_up/features_plan.rb +14 -0
  20. data/app/models/paid_up/plan.rb +99 -0
  21. data/app/views/devise/confirmations/new.html.haml +13 -0
  22. data/app/views/devise/passwords/edit.html.haml +19 -0
  23. data/app/views/devise/passwords/new.html.haml +14 -0
  24. data/app/views/devise/registrations/_new_form.html.haml +23 -0
  25. data/app/views/devise/registrations/edit.html.haml +39 -0
  26. data/app/views/devise/registrations/new.html.haml +11 -0
  27. data/app/views/devise/sessions/_new_form.html.haml +21 -0
  28. data/app/views/devise/sessions/new.html.haml +11 -0
  29. data/app/views/devise/shared/_links.html.haml +14 -0
  30. data/app/views/devise/unlocks/new.html.haml +14 -0
  31. data/app/views/paid_up/features/_abilities_table.html.haml +22 -0
  32. data/app/views/paid_up/features/_table.html.haml +16 -0
  33. data/app/views/paid_up/plans/index.html.haml +18 -0
  34. data/app/views/paid_up/subscriptions/index.html.haml +16 -0
  35. data/app/views/paid_up/subscriptions/new.html.haml +101 -0
  36. data/bin/rails +12 -0
  37. data/config/initializers/stripe.rb +6 -0
  38. data/config/locales/en.yml +85 -0
  39. data/config/routes.rb +7 -0
  40. data/coverage/.last_run.json +5 -0
  41. data/coverage/.resultset.json +1488 -0
  42. data/coverage/.resultset.json.lock +0 -0
  43. data/db/migrate/20150407105900_create_paid_up_features_plans_table.rb +9 -0
  44. data/db/migrate/20150407110100_create_paid_up_features_table.rb +11 -0
  45. data/db/migrate/20150407110101_create_paid_up_plans_table.rb +14 -0
  46. data/lib/generators/paid_up/install/install_generator.rb +59 -0
  47. data/lib/generators/paid_up/install/templates/initializer.rb.erb +5 -0
  48. data/lib/generators/paid_up/utils.rb +16 -0
  49. data/lib/paid_up/configuration.rb +22 -0
  50. data/lib/paid_up/engine.rb +17 -0
  51. data/lib/paid_up/integer.rb +9 -0
  52. data/lib/paid_up/localization.rb +31 -0
  53. data/lib/paid_up/mixins.rb +139 -0
  54. data/lib/paid_up/railtie.rb +4 -0
  55. data/lib/paid_up/stripe_extensions.rb +17 -0
  56. data/lib/paid_up/table_validator.rb +9 -0
  57. data/lib/paid_up/unlimited.rb +17 -0
  58. data/lib/paid_up/version.rb +7 -0
  59. data/lib/paid_up.rb +27 -0
  60. data/paid_up.gemspec +248 -0
  61. data/spec/controllers/paid_up/plans_spec.rb +26 -0
  62. data/spec/controllers/paid_up/subscriptions_spec.rb +187 -0
  63. data/spec/dummy/README.rdoc +28 -0
  64. data/spec/dummy/Rakefile +6 -0
  65. data/spec/dummy/app/assets/javascripts/application.js +16 -0
  66. data/spec/dummy/app/assets/stylesheets/application.css.scss +16 -0
  67. data/spec/dummy/app/controllers/application_controller.rb +3 -0
  68. data/spec/dummy/app/models/group.rb +3 -0
  69. data/spec/dummy/app/models/user.rb +9 -0
  70. data/spec/dummy/app/views/layouts/application.html.haml +31 -0
  71. data/spec/dummy/app/views/pages/index.html.haml +1 -0
  72. data/spec/dummy/bin/bundle +3 -0
  73. data/spec/dummy/bin/rails +4 -0
  74. data/spec/dummy/bin/rake +4 -0
  75. data/spec/dummy/bin/setup +29 -0
  76. data/spec/dummy/config/application.rb +32 -0
  77. data/spec/dummy/config/boot.rb +5 -0
  78. data/spec/dummy/config/database.yml +25 -0
  79. data/spec/dummy/config/environment.rb +5 -0
  80. data/spec/dummy/config/environments/development.rb +46 -0
  81. data/spec/dummy/config/environments/production.rb +79 -0
  82. data/spec/dummy/config/environments/test.rb +45 -0
  83. data/spec/dummy/config/initializers/assets.rb +11 -0
  84. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  85. data/spec/dummy/config/initializers/cookies_serializer.rb +3 -0
  86. data/spec/dummy/config/initializers/devise.rb +259 -0
  87. data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  88. data/spec/dummy/config/initializers/high_voltage.rb +3 -0
  89. data/spec/dummy/config/initializers/inflections.rb +16 -0
  90. data/spec/dummy/config/initializers/mime_types.rb +4 -0
  91. data/spec/dummy/config/initializers/paid_up.rb +5 -0
  92. data/spec/dummy/config/initializers/session_store.rb +3 -0
  93. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  94. data/spec/dummy/config/locales/devise.en.yml +60 -0
  95. data/spec/dummy/config/locales/en.yml +23 -0
  96. data/spec/dummy/config/routes.rb +4 -0
  97. data/spec/dummy/config/secrets.yml +22 -0
  98. data/spec/dummy/config.ru +4 -0
  99. data/spec/dummy/db/development.sqlite3 +0 -0
  100. data/spec/dummy/db/migrate/20150406154440_create_users_table.rb +7 -0
  101. data/spec/dummy/db/migrate/20150517175135_create_groups_table.rb +11 -0
  102. data/spec/dummy/db/migrate/20150518000915_add_devise_to_users.rb +49 -0
  103. data/spec/dummy/db/migrate/20150518000917_create_paid_up_features_plans_table.paid_up.rb +10 -0
  104. data/spec/dummy/db/migrate/20150518000918_create_paid_up_features_table.paid_up.rb +12 -0
  105. data/spec/dummy/db/migrate/20150518000919_create_paid_up_plans_table.paid_up.rb +15 -0
  106. data/spec/dummy/db/migrate/20150518000920_add_stripe_id_column_to_user.rb +6 -0
  107. data/spec/dummy/db/schema.rb +75 -0
  108. data/spec/dummy/db/seeds/features.seeds.rb +19 -0
  109. data/spec/dummy/db/seeds/features_plans.seeds.rb +51 -0
  110. data/spec/dummy/db/seeds/plans.seeds.rb +91 -0
  111. data/spec/dummy/db/seeds.rb +0 -0
  112. data/spec/dummy/db/test.sqlite3 +0 -0
  113. data/spec/dummy/lib/assets/.keep +0 -0
  114. data/spec/dummy/log/.keep +0 -0
  115. data/spec/dummy/log/development.log +108393 -0
  116. data/spec/dummy/public/404.html +67 -0
  117. data/spec/dummy/public/422.html +67 -0
  118. data/spec/dummy/public/500.html +66 -0
  119. data/spec/dummy/public/assets/.sprockets-manifest-34b01376fc56586f4f4fd19e7b1c0e35.json +1 -0
  120. data/spec/dummy/public/assets/application-27f004bb902952dbbaad25f0f28c312f29ffee315c94fa51dea6b5ec6dc993e6.css +13 -0
  121. data/spec/dummy/public/assets/application-3a226fbacd7ba9a2b9f7972fafdd7b2486c34707d96a60c26f3bbe4579c29ca6.js +116 -0
  122. data/spec/dummy/public/assets/bootstrap/glyphicons-halflings-regular-13634da87d9e23f8c3ed9108ce1724d183a39ad072e73e1b3d8cbf646d2d0407.eot +0 -0
  123. data/spec/dummy/public/assets/bootstrap/glyphicons-halflings-regular-42f60659d265c1a3c30f9fa42abcbb56bd4a53af4d83d316d6dd7a36903c43e5.svg +288 -0
  124. data/spec/dummy/public/assets/bootstrap/glyphicons-halflings-regular-a26394f7ede100ca118eff2eda08596275a9839b959c226e15439557a5a80742.woff +0 -0
  125. data/spec/dummy/public/assets/bootstrap/glyphicons-halflings-regular-e395044093757d82afcb138957d06a1ea9361bdcf0b442d06a18a8051af57456.ttf +0 -0
  126. data/spec/dummy/public/assets/bootstrap/glyphicons-halflings-regular-fe185d11a49676890d47bb783312a0cda5a44c4039214094e7957b4c040ef11c.woff2 +0 -0
  127. data/spec/dummy/public/favicon.ico +0 -0
  128. data/spec/dummy/test/controllers/plans_controller_controller_test.rb +7 -0
  129. data/spec/factories/feature.rb +7 -0
  130. data/spec/factories/features_plan.rb +7 -0
  131. data/spec/factories/plan.rb +7 -0
  132. data/spec/factories/user.rb +7 -0
  133. data/spec/models/paid_up/feature_spec.rb +21 -0
  134. data/spec/models/paid_up/features_plan_spec.rb +7 -0
  135. data/spec/models/paid_up/plan_spec.rb +156 -0
  136. data/spec/models/user_spec.rb +304 -0
  137. data/spec/paid_up_spec.rb +7 -0
  138. data/spec/rails_helper.rb +65 -0
  139. data/spec/routing/paid_up/plans_spec.rb +11 -0
  140. data/spec/routing/paid_up/subscription_spec.rb +23 -0
  141. data/spec/spec_helper.rb +87 -0
  142. data/spec/support/controller_macros.rb +12 -0
  143. data/spec/support/factory_girl.rb +3 -0
  144. data/spec/support/plans_and_features.rb +209 -0
  145. data/spec/support/stripe.rb +23 -0
  146. data/spec/support/subscribers.rb +44 -0
  147. data/spec/views/paid_up/plans_spec.rb +54 -0
  148. data/spec/views/paid_up/subscriptions_spec.rb +58 -0
  149. metadata +488 -0
@@ -0,0 +1,156 @@
1
+ require 'rails_helper'
2
+
3
+ describe PaidUp::Plan do
4
+ it { should have_many(:features_plans).class_name('PaidUp::FeaturesPlan') }
5
+ it { should have_many(:features).class_name('PaidUp::Feature').through(:features_plans) }
6
+
7
+ it { should validate_presence_of(:description) }
8
+ it { should validate_presence_of(:name) }
9
+
10
+ include_context 'plans and features'
11
+
12
+ describe '.subscribable' do
13
+ context 'returns all subscribable plans' do
14
+ subject { PaidUp::Plan.subscribable }
15
+ it { should eq [free_plan, no_ads_plan, group_leader_plan, professional_plan]}
16
+ end
17
+ end
18
+
19
+ describe '.free' do
20
+ context 'returns the free plan' do
21
+ subject { PaidUp::Plan.free }
22
+ it { should eq free_plan}
23
+ end
24
+ end
25
+
26
+ describe '#feature_setting' do
27
+ describe 'when setting_type is integer' do
28
+ context 'returns the setting value if available' do
29
+ subject { group_leader_plan.feature_setting(groups_feature.id) }
30
+ it { should eq(1) }
31
+ end
32
+ context 'returns 0 if not available' do
33
+ subject { free_plan.feature_setting(groups_feature.id) }
34
+ it { should eq(0) }
35
+ end
36
+ end
37
+
38
+ describe 'when setting_type is boolean' do
39
+ context 'returns the setting value if available' do
40
+ subject { group_leader_plan.feature_setting(configuration_feature.id) }
41
+ it { should eq(true) }
42
+ end
43
+ context 'returns false if not available' do
44
+ subject { free_plan.feature_setting(configuration_feature.id) }
45
+ it { should eq(false) }
46
+ end
47
+ end
48
+ end
49
+
50
+ describe '#feature_setting_by_name' do
51
+ describe 'when setting_type is integer' do
52
+ context 'returns the setting value if available' do
53
+ subject { group_leader_plan.feature_setting_by_name('groups') }
54
+ it { should eq(1) }
55
+ end
56
+ context 'returns 0 if not available' do
57
+ subject { free_plan.feature_setting_by_name('groups') }
58
+ it { should eq(0) }
59
+ end
60
+ end
61
+
62
+ describe 'when setting_type is boolean' do
63
+ context 'returns the setting value if available' do
64
+ subject { group_leader_plan.feature_setting_by_name('ad_free') }
65
+ it { should eq(true) }
66
+ end
67
+ context 'returns false if not available' do
68
+ subject { free_plan.feature_setting_by_name('ad_free') }
69
+ it { should eq(false) }
70
+ end
71
+ end
72
+ end
73
+
74
+ describe '#feature_unlimited?' do
75
+ context 'returns true if unlimited' do
76
+ subject { professional_plan.feature_unlimited?(groups_feature.id) }
77
+ it { should eq(true) }
78
+ end
79
+ context 'returns false if an integer' do
80
+ subject { group_leader_plan.feature_unlimited?(groups_feature.id) }
81
+ it { should eq(false) }
82
+ end
83
+ context 'returns false if not found' do
84
+ subject { free_plan.feature_unlimited?(groups_feature.id) }
85
+ it { should eq(false) }
86
+ end
87
+ end
88
+
89
+ describe '#interval' do
90
+ context 'on free plan' do
91
+ subject { free_plan.interval }
92
+ it { should eq 'month' }
93
+ end
94
+ context 'on a regular plan' do
95
+ subject { no_ads_plan.interval }
96
+ it { should eq 'month' }
97
+ end
98
+ end
99
+
100
+ describe '#interval_count' do
101
+ context 'on free plan' do
102
+ subject { free_plan.interval_count }
103
+ it { should eq 1 }
104
+ end
105
+ context 'on a regular plan' do
106
+ subject { no_ads_plan.interval_count }
107
+ it { should eq 1 }
108
+ end
109
+ end
110
+
111
+ describe '#amount' do
112
+ context 'on default plan' do
113
+ subject { free_plan.amount }
114
+ it { should eq 0 }
115
+ end
116
+ context 'on a regular plan' do
117
+ subject { no_ads_plan.amount }
118
+ it { should eq 100 }
119
+ end
120
+ end
121
+
122
+ describe '#money' do
123
+ context 'on default plan' do
124
+ subject { free_plan.money }
125
+ it { should be_a Money }
126
+ end
127
+ context 'on a regular plan' do
128
+ subject { no_ads_plan.money }
129
+ it { should be_a Money }
130
+ end
131
+ end
132
+
133
+ describe '#charge' do
134
+ context 'on default plan' do
135
+ subject { free_plan.charge }
136
+ it { should eq 0 }
137
+ end
138
+ context 'on a regular plan' do
139
+ subject { no_ads_plan.charge }
140
+ it { should eq 1 }
141
+ end
142
+ end
143
+
144
+ describe '#currency' do
145
+ context 'on default plan' do
146
+ subject { free_plan.currency }
147
+ it { should eq 'USD' }
148
+ end
149
+ context 'on a regular plan' do
150
+ subject { no_ads_plan.currency }
151
+ it { should eq 'USD' }
152
+ end
153
+ end
154
+
155
+
156
+ end
@@ -0,0 +1,304 @@
1
+ require 'rails_helper'
2
+ require "cancan/matchers"
3
+
4
+ describe User do
5
+ include_context 'subscribers'
6
+
7
+ context '#stripe_data' do
8
+ subject { no_ads_subscriber.stripe_data }
9
+ it { should be_a Stripe::Customer }
10
+ end
11
+
12
+ context '#cards' do
13
+ subject { professional_subscriber.cards.first }
14
+ it { should be_a Stripe::Card }
15
+ end
16
+
17
+ context '#subscribe_to_plan' do
18
+ context 'starting from no subscription' do
19
+ before do
20
+ token = working_stripe_token free_subscriber
21
+ free_subscriber.subscribe_to_plan no_ads_plan, token
22
+ end
23
+ subject { free_subscriber.plan }
24
+ it { should eq(no_ads_plan) }
25
+ end
26
+
27
+ context 'starting from lower subscription' do
28
+ context 'with saved card' do
29
+ before do
30
+ no_ads_subscriber.subscribe_to_plan group_leader_plan
31
+ end
32
+ subject { no_ads_subscriber.plan }
33
+ it { should eq(group_leader_plan) }
34
+ end
35
+ context 'with new token' do
36
+ before do
37
+ token = working_stripe_token no_ads_subscriber
38
+ no_ads_subscriber.subscribe_to_plan group_leader_plan, token
39
+ end
40
+ subject { no_ads_subscriber.plan }
41
+ it { should eq(group_leader_plan) }
42
+ end
43
+ end
44
+
45
+ context '#subscribe_to_free_plan' do
46
+ context 'starting from no subscription' do
47
+ let(:test_user) {
48
+ user = FactoryGirl.create(
49
+ :user,
50
+ name: 'Test User'
51
+ )
52
+ user.subscribe_to_free_plan
53
+ user
54
+ }
55
+ subject { test_user.plan }
56
+ it { should eq(free_plan) }
57
+ end
58
+
59
+ context 'starting from higher subscription' do
60
+ before do
61
+ professional_subscriber.subscribe_to_free_plan
62
+ end
63
+ subject { professional_subscriber.plan }
64
+ it { should eq(free_plan) }
65
+ end
66
+ end
67
+ end
68
+
69
+ context '#plan' do
70
+ context 'when using free plan' do
71
+ subject { free_subscriber.plan }
72
+ it { should eq free_plan }
73
+ end
74
+ context 'when subscribed to a plan' do
75
+ subject { no_ads_subscriber.plan }
76
+ it { should eq no_ads_plan }
77
+ end
78
+ end
79
+
80
+ context '#table_rows_remaining' do
81
+ context 'when using a plan without the feature' do
82
+ subject { no_ads_subscriber.table_rows_remaining 'groups' }
83
+ it { should eq 0 }
84
+ end
85
+ context 'when subscribed to a plan with the feature limited' do
86
+ subject { group_leader_subscriber.table_rows_remaining 'groups' }
87
+ it { should eq 1 }
88
+ end
89
+ context 'when subscribed to a plan with the feature unlimited' do
90
+ subject { professional_subscriber.table_rows_remaining 'groups' }
91
+ it { should eq PaidUp::Unlimited.to_i }
92
+ end
93
+ end
94
+
95
+ context '#table_rows_unlimited?' do
96
+ context 'when using a plan without the feature' do
97
+ subject { no_ads_subscriber.table_rows_unlimited? 'groups' }
98
+ it { should eq false }
99
+ end
100
+ context 'when subscribed to a plan with the feature limited' do
101
+ subject { group_leader_subscriber.table_rows_unlimited? 'groups' }
102
+ it { should eq false }
103
+ end
104
+ context 'when subscribed to a plan with the feature unlimited' do
105
+ subject { professional_subscriber.table_rows_unlimited? 'groups' }
106
+ it { should eq true }
107
+ end
108
+ end
109
+
110
+ context '#table_rows_allowed' do
111
+ context 'when using a plan without the feature' do
112
+ subject { no_ads_subscriber.table_rows_allowed 'groups' }
113
+ it { should eq 0 }
114
+ end
115
+ context 'when subscribed to a plan with the feature limited' do
116
+ subject { group_leader_subscriber.table_rows_allowed 'groups' }
117
+ it { should eq 1 }
118
+ end
119
+ context 'when subscribed to a plan with the feature unlimited' do
120
+ subject { professional_subscriber.table_rows_allowed 'groups' }
121
+ it { should eq PaidUp::Unlimited.to_i }
122
+ end
123
+ end
124
+
125
+ context '#table_rows' do
126
+ context 'when possessing no rows' do
127
+ subject { professional_subscriber.table_rows 'groups' }
128
+ it { should eq 0 }
129
+ end
130
+ context 'when possessing 3 rows' do
131
+ subject {
132
+ professional_subscriber.groups.create! name: 'Test Group'
133
+ professional_subscriber.groups.create! name: 'Test Group'
134
+ professional_subscriber.groups.create! name: 'Test Group'
135
+ professional_subscriber.table_rows 'groups'
136
+ }
137
+ it { should eq 3 }
138
+ end
139
+ end
140
+
141
+ context '#plan_stripe_id' do
142
+ context 'when using free plan' do
143
+ subject { free_subscriber.plan_stripe_id }
144
+ it { should eq 'free-plan' }
145
+ end
146
+ context 'when subscribed to a plan' do
147
+ subject { no_ads_subscriber.plan_stripe_id }
148
+ it { should eq 'no-ads-plan' }
149
+ end
150
+ end
151
+
152
+ context '#subscription' do
153
+ context 'when using free plan' do
154
+ subject { free_subscriber.subscription }
155
+ it { should be_a Stripe::Subscription }
156
+ end
157
+ context 'when subscribed to a plan' do
158
+ subject { no_ads_subscriber.subscription }
159
+ it { should be_a Stripe::Subscription }
160
+ end
161
+ end
162
+
163
+ context '#is_subscribed_to?' do
164
+ context 'when using free plan' do
165
+ subject { free_subscriber.is_subscribed_to? free_plan }
166
+ it { should be true }
167
+ end
168
+ context 'when true' do
169
+ subject { professional_subscriber.is_subscribed_to? professional_plan }
170
+ it { should be true }
171
+ end
172
+ context 'when false' do
173
+ subject { no_ads_subscriber.is_subscribed_to? professional_plan }
174
+ it { should be false }
175
+ end
176
+ end
177
+
178
+ context '#can_upgrade_to?' do
179
+ context 'when using free plan' do
180
+ context 'checking against free plan' do
181
+ subject { free_subscriber.can_upgrade_to? free_plan }
182
+ it { should be false }
183
+ end
184
+ context 'checking against another plan' do
185
+ subject { free_subscriber.can_upgrade_to? no_ads_plan }
186
+ it { should be true }
187
+ end
188
+ end
189
+ context 'when true' do
190
+ subject { no_ads_subscriber.can_upgrade_to? professional_plan }
191
+ it { should be true }
192
+ end
193
+ context 'when false' do
194
+ subject { professional_subscriber.can_upgrade_to? no_ads_plan }
195
+ it { should be false }
196
+ end
197
+ end
198
+
199
+ context '#can_downgrade_to?' do
200
+ context 'when using free plan' do
201
+ context 'checking against free plan' do
202
+ subject { free_subscriber.can_downgrade_to? free_plan }
203
+ it { should be false }
204
+ end
205
+ context 'checking against another plan' do
206
+ subject { free_subscriber.can_downgrade_to? no_ads_plan }
207
+ it { should be false }
208
+ end
209
+ end
210
+ context 'when false' do
211
+ subject { no_ads_subscriber.can_downgrade_to? professional_plan }
212
+ it { should be false }
213
+ end
214
+ context 'when true' do
215
+ subject { professional_subscriber.can_downgrade_to? no_ads_plan }
216
+ it { should be true }
217
+ end
218
+ end
219
+
220
+ context '#using_free_plan?' do
221
+ context 'when false' do
222
+ subject { no_ads_subscriber.using_free_plan? }
223
+ it { should be false }
224
+ end
225
+ context 'when true' do
226
+ subject { free_subscriber.using_free_plan? }
227
+ it { should be true }
228
+ end
229
+ end
230
+
231
+ ####################
232
+ # Abilities #
233
+ ####################
234
+
235
+
236
+ describe "Abilities" do
237
+ subject(:ability){ Ability.new(user) }
238
+
239
+ context "when anonymous" do
240
+ let(:user){ User.new }
241
+ it{ should be_able_to(:read, Group) }
242
+ it{ should_not be_able_to(:manage, Group) }
243
+ it{ should_not be_able_to(:own, Group) }
244
+ it{ should_not be_able_to(:create, Group) }
245
+ it{ should_not be_able_to(:use, :ad_free) }
246
+ it{ should_not be_able_to(:use, :calendar) }
247
+ end
248
+ context "when on free plan" do
249
+ let(:user){ free_subscriber }
250
+ it{ should be_able_to(:read, Group) }
251
+ it{ should_not be_able_to(:manage, Group) }
252
+ it{ should_not be_able_to(:own, Group) }
253
+ it{ should_not be_able_to(:create, Group) }
254
+ it{ should_not be_able_to(:use, :ad_free) }
255
+ it{ should_not be_able_to(:use, :calendar) }
256
+ end
257
+ context "when on group plan" do
258
+ context "given no groups are owned" do
259
+ let(:user){ group_leader_subscriber }
260
+ it{ should be_able_to(:read, Group) }
261
+ it{ should be_able_to(:manage, Group) }
262
+ it{ should be_able_to(:own, Group) }
263
+ it{ should be_able_to(:create, Group) }
264
+ it{ should be_able_to(:use, :ad_free) }
265
+ it{ should_not be_able_to(:use, :calendar) }
266
+ end
267
+ context "given one group is owned" do
268
+ let(:user){
269
+ group_leader_subscriber.groups.create!(name: 'Test Group')
270
+ group_leader_subscriber.reload
271
+ }
272
+ it{ should be_able_to(:read, Group) }
273
+ it{ should be_able_to(:manage, Group) }
274
+ it{ should be_able_to(:own, Group) }
275
+ it{ should_not be_able_to(:create, Group) }
276
+ it{ should be_able_to(:use, :ad_free) }
277
+ it{ should_not be_able_to(:use, :calendar) }
278
+ end
279
+ end
280
+ context "when on professional plan" do
281
+ context "given no groups are owned" do
282
+ let(:user){ professional_subscriber }
283
+ it{ should be_able_to(:read, Group) }
284
+ it{ should be_able_to(:manage, Group) }
285
+ it{ should be_able_to(:own, Group) }
286
+ it{ should be_able_to(:create, Group) }
287
+ it{ should be_able_to(:use, :ad_free) }
288
+ it{ should be_able_to(:use, :calendar) }
289
+ end
290
+ context "given one group is owned" do
291
+ let(:user){
292
+ professional_subscriber.groups.create!(name: 'Test Group')
293
+ professional_subscriber.reload
294
+ }
295
+ it{ should be_able_to(:read, Group) }
296
+ it{ should be_able_to(:manage, Group) }
297
+ it{ should be_able_to(:own, Group) }
298
+ it{ should be_able_to(:create, Group) }
299
+ it{ should be_able_to(:use, :ad_free) }
300
+ it{ should be_able_to(:use, :calendar) }
301
+ end
302
+ end
303
+ end
304
+ end
@@ -0,0 +1,7 @@
1
+ require 'rails_helper'
2
+
3
+ describe "PaidUp" do
4
+ it 'should return correct version string' do
5
+ PaidUp.version_string.should == "PaidUp version #{PaidUp::VERSION}"
6
+ end
7
+ end
@@ -0,0 +1,65 @@
1
+ require 'coveralls'
2
+ Coveralls.wear!
3
+
4
+ # This file is copied to spec/ when you run 'rails generate rspec:install'
5
+ ENV['RAILS_ENV'] ||= 'test'
6
+ require 'spec_helper'
7
+ require File.expand_path('../dummy/config/environment', __FILE__)
8
+ require 'rspec/rails'
9
+ # Add additional requires below this line. Rails is not loaded until this point!
10
+ require 'shoulda/matchers'
11
+ require 'factory_girl_rails'
12
+
13
+ # Requires supporting ruby files with custom matchers and macros, etc, in
14
+ # spec/support/ and its subdirectories. Files matching `spec/**/*_spec.rb` are
15
+ # run as spec files by default. This means that files in spec/support that end
16
+ # in _spec.rb will both be required and run as specs, causing the specs to be
17
+ # run twice. It is recommended that you do not name files matching this glob to
18
+ # end with _spec.rb. You can configure this pattern with the --pattern
19
+ # option on the command line or in ~/.rspec, .rspec or `.rspec-local`.
20
+ #
21
+ # The following line is provided for convenience purposes. It has the downside
22
+ # of increasing the boot-up time by auto-requiring all files in the support
23
+ # directory. Alternatively, in the individual `*_spec.rb` files, manually
24
+ # require only the support files necessary.
25
+ #
26
+ Dir["./spec/support/**/*.rb"].sort.each { |f| require f}
27
+
28
+ # Checks for pending migrations before tests are run.
29
+ # If you are not using ActiveRecord, you can remove this line.
30
+ # ActiveRecord::Migration.maintain_test_schema!
31
+
32
+ RSpec.configure do |config|
33
+ # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
34
+ # config.fixture_path = "#{::Rails.root}/spec/fixtures
35
+
36
+ config.expect_with(:rspec) { |c| c.syntax = :should }
37
+
38
+ # If you're not using ActiveRecord, or you'd prefer not to run each of your
39
+ # examples within a transaction, remove the following line or assign false
40
+ # instead of true.
41
+ config.use_transactional_fixtures = true
42
+
43
+ # RSpec Rails can automatically mix in different behaviours to your tests
44
+ # based on their file location, for example enabling you to call `get` and
45
+ # `post` in specs under `spec/controllers`.
46
+ #
47
+ # You can disable this behaviour by removing the line below, and instead
48
+ # explicitly tag your specs with their type, e.g.:
49
+ #
50
+ # RSpec.describe UsersController, :type => :controller do
51
+ # # ...
52
+ # end
53
+ #
54
+ # The different available types are documented in the features, such as in
55
+ # https://relishapp.com/rspec/rspec-rails/docs
56
+ config.infer_spec_type_from_file_location!
57
+
58
+ config.before(:each) { @routes = PaidUp::Engine.routes }
59
+ config.include PaidUp::Engine.routes.url_helpers
60
+
61
+ config.include Devise::TestHelpers, type: :controller
62
+ config.include Devise::TestHelpers, type: :view
63
+ config.include ControllerMacros, type: :controller
64
+ config.include ControllerMacros, type: :view
65
+ end
@@ -0,0 +1,11 @@
1
+ require 'rails_helper'
2
+
3
+ describe 'PaidUp::Routing' do
4
+ include_context 'plans and features'
5
+ routes { PaidUp::Engine.routes }
6
+
7
+ describe "routes to the list of all plans" do
8
+ subject { get plans_path }
9
+ it { should route_to(:controller => "paid_up/plans", :action => "index")}
10
+ end
11
+ end
@@ -0,0 +1,23 @@
1
+ require 'rails_helper'
2
+
3
+ describe 'PaidUp::Routing' do
4
+ include_context 'plans and features'
5
+ routes { PaidUp::Engine.routes }
6
+
7
+ describe 'nested resource' do
8
+ context "routes to a new subscription for a plan" do
9
+ subject { get new_plan_subscription_path(professional_plan) }
10
+ it { should route_to(:controller => "paid_up/subscriptions", :action => "new", :plan_id => professional_plan.id.to_s) }
11
+ end
12
+ context "routes to create a subscription for a plan" do
13
+ subject { post plan_subscriptions_path(professional_plan) }
14
+ it { should route_to(:controller => "paid_up/subscriptions", :action => "create", :plan_id => professional_plan.id.to_s) }
15
+ end
16
+ end
17
+ describe 'top-level resource' do
18
+ context "routes to a display of subscriptions for a user" do
19
+ subject { get subscriptions_path }
20
+ it { should route_to(:controller => "paid_up/subscriptions", :action => "index") }
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,87 @@
1
+ # This file was generated by the `rails generate rspec:install` command. Conventionally, all
2
+ # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
3
+ # The generated `.rspec` file contains `--require spec_helper` which will cause
4
+ # this file to always be loaded, without a need to explicitly require it in any
5
+ # files.
6
+ #
7
+ # Given that it is always loaded, you are encouraged to keep this file as
8
+ # light-weight as possible. Requiring heavyweight dependencies from this file
9
+ # will add to the boot time of your test suite on EVERY test run, even for an
10
+ # individual file that may not need all of that loaded. Instead, consider making
11
+ # a separate helper file that requires the additional dependencies and performs
12
+ # the additional setup, and require it from the spec files that actually need
13
+ # it.
14
+ #
15
+ # The `.rspec` file also contains a few flags that are not defaults but that
16
+ # users commonly want.
17
+ #
18
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
19
+ RSpec.configure do |config|
20
+ # rspec-expectations config goes here. You can use an alternate
21
+ # assertion/expectation library such as wrong or the stdlib/minitest
22
+ # assertions if you prefer.
23
+ config.expect_with :rspec do |expectations|
24
+ # This option will default to `true` in RSpec 4. It makes the `description`
25
+ # and `failure_message` of custom matchers include text for helper methods
26
+ # defined using `chain`, e.g.:
27
+ # be_bigger_than(2).and_smaller_than(4).description
28
+ # # => "be bigger than 2 and smaller than 4"
29
+ # ...rather than:
30
+ # # => "be bigger than 2"
31
+ expectations.include_chain_clauses_in_custom_matcher_descriptions = true
32
+ end
33
+
34
+ # rspec-mocks config goes here. You can use an alternate test double
35
+ # library (such as bogus or mocha) by changing the `mock_with` option here.
36
+ config.mock_with :rspec do |mocks|
37
+ # Prevents you from mocking or stubbing a method that does not exist on
38
+ # a real object. This is generally recommended, and will default to
39
+ # `true` in RSpec 4.
40
+ mocks.verify_partial_doubles = true
41
+ end
42
+
43
+ # The settings below are suggested to provide a good initial experience
44
+ # with RSpec, but feel free to customize to your heart's content.
45
+ =begin
46
+ # These two settings work together to allow you to limit a spec run
47
+ # to individual examples or groups you care about by tagging them with
48
+ # `:focus` metadata. When nothing is tagged with `:focus`, all examples
49
+ # get run.
50
+ config.filter_run :focus
51
+ config.run_all_when_everything_filtered = true
52
+
53
+ # Limits the available syntax to the non-monkey patched syntax that is
54
+ # recommended. For more details, see:
55
+ # - http://myronmars.to/n/dev-blog/2012/06/rspecs-new-expectation-syntax
56
+ # - http://teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
57
+ # - http://myronmars.to/n/dev-blog/2014/05/notable-changes-in-rspec-3#new__config_option_to_disable_rspeccore_monkey_patching
58
+ config.disable_monkey_patching!
59
+
60
+ # Many RSpec users commonly either run the entire suite or an individual
61
+ # file, and it's useful to allow more verbose output when running an
62
+ # individual spec file.
63
+ if config.files_to_run.one?
64
+ # Use the documentation formatter for detailed output,
65
+ # unless a formatter has already been configured
66
+ # (e.g. via a command-line flag).
67
+ config.default_formatter = 'doc'
68
+ end
69
+
70
+ # Print the 10 slowest examples and example groups at the
71
+ # end of the spec run, to help surface which specs are running
72
+ # particularly slow.
73
+ config.profile_examples = 10
74
+
75
+ # Run specs in random order to surface order dependencies. If you find an
76
+ # order dependency and want to debug it, you can fix the order by providing
77
+ # the seed, which is printed after each run.
78
+ # --seed 1234
79
+ config.order = :random
80
+
81
+ # Seed global randomization in this process using the `--seed` CLI option.
82
+ # Setting this allows you to use `--seed` to deterministically reproduce
83
+ # test failures related to randomization by passing the same `--seed` value
84
+ # as the one that triggered the failure.
85
+ Kernel.srand config.seed
86
+ =end
87
+ end
@@ -0,0 +1,12 @@
1
+ module ControllerMacros
2
+ def access_anonymous
3
+ sign_out :user
4
+ User.new
5
+ end
6
+
7
+ def login_subscriber(subscriber)
8
+ @request.env["devise.mapping"] = Devise.mappings[:user]
9
+ sign_in subscriber
10
+ subscriber
11
+ end
12
+ end
@@ -0,0 +1,3 @@
1
+ RSpec.configure do |config|
2
+ config.include FactoryGirl::Syntax::Methods
3
+ end