saucy 0.8.5 → 0.9.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.
- data/CHANGELOG.md +21 -0
- data/app/controllers/accounts_controller.rb +4 -4
- data/app/controllers/plans_controller.rb +5 -5
- data/lib/saucy/configuration.rb +1 -14
- data/lib/saucy/notifications.rb +21 -0
- data/lib/saucy/subscription.rb +1 -0
- data/lib/saucy.rb +1 -0
- data/spec/models/invitation_spec.rb +4 -4
- data/spec/models/subscription_spec.rb +73 -56
- data/spec/{saucy_spec.rb → saucy/configuration_spec.rb} +0 -23
- data/spec/saucy/notifications_spec.rb +50 -0
- data/spec/support/notifications.rb +13 -3
- metadata +32 -28
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,24 @@
|
|
1
|
+
0.9.0
|
2
|
+
|
3
|
+
Added billed observer event.
|
4
|
+
|
5
|
+
Extracted and renamed the observer/notification code.
|
6
|
+
If you register any observers, you should update your code from:
|
7
|
+
|
8
|
+
Saucy::Configuration.observe(my_observer)
|
9
|
+
|
10
|
+
to:
|
11
|
+
|
12
|
+
Saucy::Notifications.register_observer(my_observer)
|
13
|
+
|
14
|
+
0.8.6
|
15
|
+
|
16
|
+
For each notification event, only notify observers that respond_to that event.
|
17
|
+
|
18
|
+
0.8.5
|
19
|
+
|
20
|
+
Added plan_downgraded observer event.
|
21
|
+
|
1
22
|
0.8.3
|
2
23
|
|
3
24
|
Added coupon support. In your app, add the following migration:
|
@@ -9,8 +9,8 @@ class AccountsController < ApplicationController
|
|
9
9
|
def new
|
10
10
|
@plan = Plan.find(params[:plan_id])
|
11
11
|
@signup = Signup.new
|
12
|
-
Saucy::
|
13
|
-
|
12
|
+
Saucy::Notifications.notify_observers("plan_viewed", :request => request,
|
13
|
+
:plan => @plan)
|
14
14
|
end
|
15
15
|
|
16
16
|
def create
|
@@ -22,8 +22,8 @@ class AccountsController < ApplicationController
|
|
22
22
|
@signup.plan = @plan
|
23
23
|
|
24
24
|
if @signup.save
|
25
|
-
Saucy::
|
26
|
-
|
25
|
+
Saucy::Notifications.notify_observers("account_created", :request => request,
|
26
|
+
:account => @signup.account)
|
27
27
|
flash[:success] = "Account was created."
|
28
28
|
sign_in @signup.user
|
29
29
|
redirect_to new_account_project_path(@signup.account)
|
@@ -32,10 +32,10 @@ class PlansController < ApplicationController
|
|
32
32
|
end
|
33
33
|
|
34
34
|
def notify_observers(event_name, from_plan, to_plan)
|
35
|
-
Saucy::
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
35
|
+
Saucy::Notifications.notify_observers(event_name,
|
36
|
+
:account => @account,
|
37
|
+
:request => request,
|
38
|
+
:from_plan => from_plan,
|
39
|
+
:to_plan => to_plan)
|
40
40
|
end
|
41
41
|
end
|
data/lib/saucy/configuration.rb
CHANGED
@@ -6,24 +6,11 @@ module Saucy
|
|
6
6
|
cattr_accessor :manager_email_address
|
7
7
|
cattr_accessor :support_email_address
|
8
8
|
cattr_accessor :merchant_account_id
|
9
|
-
cattr_accessor :observers
|
10
9
|
|
11
10
|
def initialize
|
12
11
|
@@manager_email_address = 'manager@example.com'
|
13
12
|
@@support_email_address = 'support@example.com'
|
14
|
-
@@layouts
|
15
|
-
@@observers = []
|
16
|
-
end
|
17
|
-
|
18
|
-
def self.observe(observer)
|
19
|
-
@@observers << observer
|
20
|
-
end
|
21
|
-
|
22
|
-
def self.notify(event, data)
|
23
|
-
@@observers.each do |observer|
|
24
|
-
observer.send(event, data)
|
25
|
-
end
|
13
|
+
@@layouts = Layouts.new
|
26
14
|
end
|
27
15
|
end
|
28
16
|
end
|
29
|
-
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'saucy/layouts'
|
2
|
+
|
3
|
+
module Saucy
|
4
|
+
module Notifications
|
5
|
+
@@observers = []
|
6
|
+
|
7
|
+
def self.clear_observers
|
8
|
+
@@observers = []
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.register_observer(observer)
|
12
|
+
@@observers << observer
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.notify_observers(event, data)
|
16
|
+
@@observers.each do |observer|
|
17
|
+
observer.send(event, data) if observer.respond_to?(event)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
data/lib/saucy/subscription.rb
CHANGED
@@ -229,6 +229,7 @@ module Saucy
|
|
229
229
|
BillingMailer.problem(account, account.subscription.transactions.last).deliver!
|
230
230
|
else
|
231
231
|
BillingMailer.receipt(account, account.subscription.transactions.last).deliver!
|
232
|
+
Saucy::Notifications.notify_observers("billed", :account => account)
|
232
233
|
end
|
233
234
|
end
|
234
235
|
end
|
data/lib/saucy.rb
CHANGED
@@ -39,11 +39,11 @@ describe Invitation, "saved" do
|
|
39
39
|
subject.account_name.should == subject.account.name
|
40
40
|
end
|
41
41
|
|
42
|
-
it "
|
42
|
+
it "defaults new user email to invited email" do
|
43
43
|
subject.new_user_email.should == subject.email
|
44
44
|
end
|
45
45
|
|
46
|
-
it "
|
46
|
+
it "defaults existing user email to invited email" do
|
47
47
|
subject.authenticating_user_email.should == subject.email
|
48
48
|
end
|
49
49
|
|
@@ -211,11 +211,11 @@ describe Invitation, "saved" do
|
|
211
211
|
subject.account_name.should == subject.account.name
|
212
212
|
end
|
213
213
|
|
214
|
-
it "
|
214
|
+
it "defaults new user email to invited email" do
|
215
215
|
subject.new_user_email.should == subject.email
|
216
216
|
end
|
217
217
|
|
218
|
-
it "
|
218
|
+
it "defaults existing user email to invited email" do
|
219
219
|
subject.authenticating_user_email.should == subject.email
|
220
220
|
end
|
221
221
|
|
@@ -306,78 +306,95 @@ describe Account, "with a paid subscription" do
|
|
306
306
|
end
|
307
307
|
end
|
308
308
|
|
309
|
-
|
310
|
-
subscription
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
Account.update_subscriptions!
|
319
|
-
subject.reload.subscription_status.should == Braintree::Subscription::Status::Active
|
320
|
-
subject.next_billing_date.to_s.should == subscription["next_billing_date"].to_s
|
309
|
+
context "when billing didn't work" do
|
310
|
+
let(:subscription) { FakeBraintree.subscriptions[subject.subscription_token] }
|
311
|
+
|
312
|
+
before do
|
313
|
+
subscription["status"] = Braintree::Subscription::Status::PastDue
|
314
|
+
subscription["next_billing_date"] = 2.months.from_now
|
315
|
+
FakeBraintree.transaction = { :status => Braintree::Transaction::Status::Failed,
|
316
|
+
:subscription_id => subject.subscription_token }
|
317
|
+
subscription["transactions"] = [FakeBraintree.generated_transaction]
|
321
318
|
end
|
322
|
-
end
|
323
319
|
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
subscription["next_billing_date"] = 2.months.from_now
|
328
|
-
FakeBraintree.transaction = { :status => Braintree::Transaction::Status::Settled,
|
329
|
-
:subscription_id => subject.subscription_token }
|
330
|
-
subscription["transactions"] = [FakeBraintree.generated_transaction]
|
320
|
+
it "receives a receipt email at it's billing email with a notice that it failed when billing didn't work" do
|
321
|
+
Timecop.travel(subject.next_billing_date + 1.day) do
|
322
|
+
ActionMailer::Base.deliveries.clear
|
331
323
|
|
332
|
-
|
333
|
-
ActionMailer::Base.deliveries.clear
|
324
|
+
Account.update_subscriptions!
|
334
325
|
|
335
|
-
|
326
|
+
ActionMailer::Base.deliveries.any? do |email|
|
327
|
+
email.to == [subject.billing_email] &&
|
328
|
+
email.subject =~ /problem/i
|
329
|
+
end.should be
|
330
|
+
end
|
331
|
+
end
|
336
332
|
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
333
|
+
it "does not notify observers of billing when billing didn't work" do
|
334
|
+
Timecop.travel(subject.next_billing_date + 1.day) do
|
335
|
+
Account.update_subscriptions!
|
336
|
+
should_not notify_observers("billed", :account => subject)
|
337
|
+
end
|
341
338
|
end
|
342
339
|
end
|
343
340
|
|
344
|
-
|
345
|
-
subscription
|
346
|
-
subscription["status"] = Braintree::Subscription::Status::Active
|
347
|
-
subscription["next_billing_date"] = 2.months.from_now
|
348
|
-
FakeBraintree.transaction = { :status => Braintree::Transaction::Status::Settled,
|
349
|
-
:subscription_id => subject.subscription_token }
|
350
|
-
subscription["transactions"] = [FakeBraintree.generated_transaction]
|
341
|
+
context "and an active subscription due 2 months from now" do
|
342
|
+
let(:subscription) { FakeBraintree.subscriptions[subject.subscription_token] }
|
351
343
|
|
352
|
-
|
353
|
-
|
344
|
+
before do
|
345
|
+
subscription["status"] = Braintree::Subscription::Status::Active
|
346
|
+
subscription["next_billing_date"] = 2.months.from_now
|
347
|
+
FakeBraintree.transaction = { :status => Braintree::Transaction::Status::Settled,
|
348
|
+
:subscription_id => subject.subscription_token }
|
349
|
+
subscription["transactions"] = [FakeBraintree.generated_transaction]
|
350
|
+
end
|
354
351
|
|
355
|
-
|
352
|
+
it "gets marked as not past due and updates its next_billing_date when the subscription is active after its billing date" do
|
353
|
+
Timecop.travel(subject.next_billing_date + 1.day) do
|
354
|
+
Account.update_subscriptions!
|
355
|
+
subject.reload.subscription_status.should == Braintree::Subscription::Status::Active
|
356
|
+
subject.next_billing_date.to_s.should == subscription["next_billing_date"].to_s
|
357
|
+
end
|
358
|
+
end
|
359
|
+
|
360
|
+
it "receives a receipt email at it's billing email with transaction details" do
|
361
|
+
Timecop.travel(subject.next_billing_date + 1.day) do
|
362
|
+
ActionMailer::Base.deliveries.clear
|
363
|
+
|
364
|
+
Account.update_subscriptions!
|
356
365
|
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
366
|
+
ActionMailer::Base.deliveries.any? do |email|
|
367
|
+
email.to == [subject.billing_email] &&
|
368
|
+
email.subject =~ /receipt/i
|
369
|
+
end.should be
|
370
|
+
end
|
361
371
|
end
|
362
|
-
end
|
363
372
|
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
subscription["transactions"] = [FakeBraintree.generated_transaction]
|
373
|
+
it "notifies observers of billing" do
|
374
|
+
Timecop.travel(subject.next_billing_date + 1.day) do
|
375
|
+
Account.update_subscriptions!
|
376
|
+
should notify_observers("billed", :account => subject)
|
377
|
+
end
|
378
|
+
end
|
371
379
|
|
372
|
-
|
373
|
-
|
380
|
+
it "doesn't receive a receipt email when it's already been billed" do
|
381
|
+
Timecop.travel(subject.next_billing_date - 1.day) do
|
382
|
+
ActionMailer::Base.deliveries.clear
|
374
383
|
|
375
|
-
|
384
|
+
Account.update_subscriptions!
|
385
|
+
|
386
|
+
ActionMailer::Base.deliveries.select do |email|
|
387
|
+
email.to == [subject.billing_email] &&
|
388
|
+
email.subject =~ /receipt/i
|
389
|
+
end.should be_empty
|
390
|
+
end
|
391
|
+
end
|
376
392
|
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
393
|
+
it "does not notify observers of billing when it's already been billed" do
|
394
|
+
Timecop.travel(subject.next_billing_date - 1.day) do
|
395
|
+
Account.update_subscriptions!
|
396
|
+
should_not notify_observers("billed", :account => subject)
|
397
|
+
end
|
381
398
|
end
|
382
399
|
end
|
383
400
|
end
|
@@ -17,23 +17,6 @@ describe Saucy::Configuration do
|
|
17
17
|
subject.merchant_account_id.should be_nil
|
18
18
|
end
|
19
19
|
|
20
|
-
it "can listen for events" do
|
21
|
-
observer = stub("an observer")
|
22
|
-
cleanup_observers do
|
23
|
-
Saucy::Configuration.observe(observer)
|
24
|
-
Saucy::Configuration.observers.should include(observer)
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
it "can notify observers" do
|
29
|
-
observer = stub("an observer", :some_event => nil)
|
30
|
-
cleanup_observers do
|
31
|
-
Saucy::Configuration.observe(observer)
|
32
|
-
Saucy::Configuration.notify("some_event", "some_data")
|
33
|
-
observer.should have_received("some_event").with("some_data")
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
20
|
it "can assign a manager email address" do
|
38
21
|
old_address = subject.manager_email_address
|
39
22
|
begin
|
@@ -53,10 +36,4 @@ describe Saucy::Configuration do
|
|
53
36
|
subject.support_email_address = old_address
|
54
37
|
end
|
55
38
|
end
|
56
|
-
|
57
|
-
def cleanup_observers
|
58
|
-
yield
|
59
|
-
ensure
|
60
|
-
subject.observers.clear
|
61
|
-
end
|
62
39
|
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Saucy::Notifications do
|
4
|
+
let(:observer_class) do
|
5
|
+
Class.new do
|
6
|
+
def some_event(*args)
|
7
|
+
end
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
it "can notify observers" do
|
12
|
+
observer = observer_class.new
|
13
|
+
observer.stubs(:some_event => true)
|
14
|
+
|
15
|
+
cleanup_observers do
|
16
|
+
Saucy::Notifications.register_observer(observer)
|
17
|
+
Saucy::Notifications.notify_observers("some_event", "some_data")
|
18
|
+
observer.should have_received("some_event").with("some_data")
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
it "only notifies observers that respond to a given event" do
|
23
|
+
observer = Object.new
|
24
|
+
|
25
|
+
cleanup_observers do
|
26
|
+
expect do
|
27
|
+
Saucy::Notifications.register_observer(observer)
|
28
|
+
Saucy::Notifications.notify_observers("some_event", "some_data")
|
29
|
+
end.should_not raise_error
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
it "can clear its observers" do
|
34
|
+
observer = observer_class.new
|
35
|
+
observer.stubs(:some_event => true)
|
36
|
+
|
37
|
+
cleanup_observers do
|
38
|
+
Saucy::Notifications.register_observer(observer)
|
39
|
+
Saucy::Notifications.clear_observers
|
40
|
+
Saucy::Notifications.notify_observers("some_event", "some_data")
|
41
|
+
observer.should_not have_received("some_event").with("some_data")
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def cleanup_observers
|
46
|
+
yield
|
47
|
+
ensure
|
48
|
+
subject.clear_observers
|
49
|
+
end
|
50
|
+
end
|
@@ -24,12 +24,20 @@ class RecordedEvent
|
|
24
24
|
end
|
25
25
|
|
26
26
|
class RecordingObserver
|
27
|
-
|
27
|
+
def self.instance
|
28
|
+
@@instance ||= self.new
|
29
|
+
end
|
30
|
+
|
31
|
+
attr_accessor :events
|
28
32
|
|
29
33
|
def initialize
|
30
34
|
@events = []
|
31
35
|
end
|
32
36
|
|
37
|
+
def respond_to?(message)
|
38
|
+
true
|
39
|
+
end
|
40
|
+
|
33
41
|
def method_missing(name, data)
|
34
42
|
@events << RecordedEvent.new(name, data)
|
35
43
|
end
|
@@ -46,12 +54,14 @@ RSpec::Matchers.define :notify_observers do |event_name, data|
|
|
46
54
|
end
|
47
55
|
|
48
56
|
def recorder
|
49
|
-
|
57
|
+
RecordingObserver.instance
|
50
58
|
end
|
51
59
|
end
|
52
60
|
|
53
61
|
RSpec.configure do |config|
|
54
62
|
config.before do
|
55
|
-
Saucy::
|
63
|
+
Saucy::Notifications.clear_observers
|
64
|
+
Saucy::Notifications.register_observer(RecordingObserver.instance)
|
65
|
+
RecordingObserver.instance.events = []
|
56
66
|
end
|
57
67
|
end
|
metadata
CHANGED
@@ -1,19 +1,21 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: saucy
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 59
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
-
|
10
|
-
version: 0.
|
8
|
+
- 9
|
9
|
+
- 0
|
10
|
+
version: 0.9.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- thoughtbot, inc.
|
14
14
|
- Joe Ferris
|
15
15
|
- Mike Burns
|
16
16
|
- Chad Pytel
|
17
|
+
- Jason Morrison
|
18
|
+
- Ben Orenstein
|
17
19
|
autorequire:
|
18
20
|
bindir: bin
|
19
21
|
cert_chain: []
|
@@ -22,9 +24,7 @@ date: 2011-06-28 00:00:00 -04:00
|
|
22
24
|
default_executable:
|
23
25
|
dependencies:
|
24
26
|
- !ruby/object:Gem::Dependency
|
25
|
-
|
26
|
-
type: :runtime
|
27
|
-
requirement: &id001 !ruby/object:Gem::Requirement
|
27
|
+
version_requirements: &id001 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ~>
|
@@ -35,12 +35,12 @@ dependencies:
|
|
35
35
|
- 11
|
36
36
|
- 0
|
37
37
|
version: 0.11.0
|
38
|
+
requirement: *id001
|
38
39
|
name: clearance
|
39
|
-
version_requirements: *id001
|
40
|
-
- !ruby/object:Gem::Dependency
|
41
40
|
prerelease: false
|
42
41
|
type: :runtime
|
43
|
-
|
42
|
+
- !ruby/object:Gem::Dependency
|
43
|
+
version_requirements: &id002 !ruby/object:Gem::Requirement
|
44
44
|
none: false
|
45
45
|
requirements:
|
46
46
|
- - ">="
|
@@ -50,12 +50,12 @@ dependencies:
|
|
50
50
|
- 1
|
51
51
|
- 2
|
52
52
|
version: "1.2"
|
53
|
+
requirement: *id002
|
53
54
|
name: formtastic
|
54
|
-
version_requirements: *id002
|
55
|
-
- !ruby/object:Gem::Dependency
|
56
55
|
prerelease: false
|
57
56
|
type: :runtime
|
58
|
-
|
57
|
+
- !ruby/object:Gem::Dependency
|
58
|
+
version_requirements: &id003 !ruby/object:Gem::Requirement
|
59
59
|
none: false
|
60
60
|
requirements:
|
61
61
|
- - ">="
|
@@ -66,12 +66,12 @@ dependencies:
|
|
66
66
|
- 0
|
67
67
|
- 3
|
68
68
|
version: 3.0.3
|
69
|
+
requirement: *id003
|
69
70
|
name: railties
|
70
|
-
version_requirements: *id003
|
71
|
-
- !ruby/object:Gem::Dependency
|
72
71
|
prerelease: false
|
73
72
|
type: :runtime
|
74
|
-
|
73
|
+
- !ruby/object:Gem::Dependency
|
74
|
+
version_requirements: &id004 !ruby/object:Gem::Requirement
|
75
75
|
none: false
|
76
76
|
requirements:
|
77
77
|
- - ">="
|
@@ -82,12 +82,12 @@ dependencies:
|
|
82
82
|
- 6
|
83
83
|
- 2
|
84
84
|
version: 2.6.2
|
85
|
+
requirement: *id004
|
85
86
|
name: braintree
|
86
|
-
version_requirements: *id004
|
87
|
-
- !ruby/object:Gem::Dependency
|
88
87
|
prerelease: false
|
89
88
|
type: :runtime
|
90
|
-
|
89
|
+
- !ruby/object:Gem::Dependency
|
90
|
+
version_requirements: &id005 !ruby/object:Gem::Requirement
|
91
91
|
none: false
|
92
92
|
requirements:
|
93
93
|
- - "="
|
@@ -98,12 +98,12 @@ dependencies:
|
|
98
98
|
- 3
|
99
99
|
- 3
|
100
100
|
version: 1.3.3
|
101
|
+
requirement: *id005
|
101
102
|
name: sham_rack
|
102
|
-
version_requirements: *id005
|
103
|
-
- !ruby/object:Gem::Dependency
|
104
103
|
prerelease: false
|
105
104
|
type: :runtime
|
106
|
-
|
105
|
+
- !ruby/object:Gem::Dependency
|
106
|
+
version_requirements: &id006 !ruby/object:Gem::Requirement
|
107
107
|
none: false
|
108
108
|
requirements:
|
109
109
|
- - ">="
|
@@ -114,12 +114,12 @@ dependencies:
|
|
114
114
|
- 1
|
115
115
|
- 2
|
116
116
|
version: 1.1.2
|
117
|
+
requirement: *id006
|
117
118
|
name: sinatra
|
118
|
-
version_requirements: *id006
|
119
|
-
- !ruby/object:Gem::Dependency
|
120
119
|
prerelease: false
|
121
|
-
type: :
|
122
|
-
|
120
|
+
type: :runtime
|
121
|
+
- !ruby/object:Gem::Dependency
|
122
|
+
version_requirements: &id007 !ruby/object:Gem::Requirement
|
123
123
|
none: false
|
124
124
|
requirements:
|
125
125
|
- - "="
|
@@ -130,8 +130,10 @@ dependencies:
|
|
130
130
|
- 2
|
131
131
|
- 6
|
132
132
|
version: 0.2.6
|
133
|
+
requirement: *id007
|
133
134
|
name: aruba
|
134
|
-
|
135
|
+
prerelease: false
|
136
|
+
type: :development
|
135
137
|
description: Clearance-based Rails engine for Software as a Service (Saas) that provides account and project management
|
136
138
|
email: support@thoughtbot.com
|
137
139
|
executables: []
|
@@ -231,6 +233,7 @@ files:
|
|
231
233
|
- lib/saucy/engine.rb
|
232
234
|
- lib/saucy/fake_braintree.rb
|
233
235
|
- lib/saucy/layouts.rb
|
236
|
+
- lib/saucy/notifications.rb
|
234
237
|
- lib/saucy/plan.rb
|
235
238
|
- lib/saucy/project.rb
|
236
239
|
- lib/saucy/projects_controller.rb
|
@@ -283,7 +286,8 @@ files:
|
|
283
286
|
- spec/models/subscription_spec.rb
|
284
287
|
- spec/models/user_spec.rb
|
285
288
|
- spec/route_extensions_spec.rb
|
286
|
-
- spec/
|
289
|
+
- spec/saucy/configuration_spec.rb
|
290
|
+
- spec/saucy/notifications_spec.rb
|
287
291
|
- spec/scaffold/config/routes.rb
|
288
292
|
- spec/spec_helper.rb
|
289
293
|
- spec/support/authentication_helpers.rb
|