Skip to content

Commit

Permalink
Continues organizing API and tests all existing methods
Browse files Browse the repository at this point in the history
  • Loading branch information
jasoncharnes committed Jun 11, 2017
1 parent 130052a commit 2cfd1fb
Show file tree
Hide file tree
Showing 11 changed files with 334 additions and 53 deletions.
Binary file added .DS_Store
Binary file not shown.
5 changes: 5 additions & 0 deletions .rubocop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ AllCops:
- db/migrate/*
- lib/pay/version.rb
- test/dummy/**/*
- test/models/subscription_test.rb
- test/pay/billable_test.rb
- test/test_helper.rb

Documentation:
Expand All @@ -16,3 +18,6 @@ ClassVars:

SpecialGlobalVars:
Enabled: false

AmbiguousBlockAssociation:
Enabled: false
4 changes: 4 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -67,12 +67,15 @@ GEM
nokogiri (>= 1.5.9)
mail (2.6.6)
mime-types (>= 1.16, < 4)
metaclass (0.0.4)
method_source (0.8.2)
mime-types (3.1)
mime-types-data (~> 3.2015)
mime-types-data (3.2016.0521)
mini_portile2 (2.2.0)
minitest (5.10.2)
mocha (1.2.1)
metaclass (~> 0.0.1)
multi_json (1.12.1)
netrc (0.11.0)
nio4r (2.1.0)
Expand Down Expand Up @@ -157,6 +160,7 @@ PLATFORMS

DEPENDENCIES
byebug
mocha
pay!
pry
rubocop
Expand Down
7 changes: 3 additions & 4 deletions app/models/subscription.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ class Subscription < ApplicationRecord
validates :processor_plan, presence: true
validates :quantity, presence: true

# Scopes
scope :for_name, ->(name) { where(name: name) }

def on_trial?
trial_ends_at? && Time.zone.now < trial_ends_at
end
Expand Down Expand Up @@ -53,8 +56,4 @@ def resume
def processor_subscription
owner.processor_subscription(processor_id)
end

def find_trial_ends_at(subscription)
subscription.trial_end.present? ? Time.at(subscription.trial_end) : nil
end
end
16 changes: 12 additions & 4 deletions lib/pay/billable.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ module Billable
end

def customer(token = nil)
check_for_processor
send("#{processor}_customer", token)
end

Expand All @@ -26,10 +27,15 @@ def subscribe(name = 'default', plan = 'default', processor = 'stripe')
end

def update_card(token)
raise StandardError, 'No processor selected' unless processor
check_for_processor
send("update_#{processor}_card", token)
end

def processor_subscription(subscription_id)
check_for_processor
send("#{processor}_subscription", subscription_id)
end

def subscribed?(name = 'default', plan = nil)
subscription = subscription(name)

Expand All @@ -40,11 +46,13 @@ def subscribed?(name = 'default', plan = nil)
end

def subscription(name = 'default')
subscriptions.where(name: name).last
subscriptions.for_name(name).last
end

def processor_subscription(subscription_id)
send("#{processor}_subscription", subscription_id)
private

def check_for_processor
raise StandardError, 'No processor selected' unless processor
end
end
end
2 changes: 1 addition & 1 deletion lib/pay/billable/stripe.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ def update_stripe_card(token)
end

def stripe_subscription(subscription_id)
Stripe::Subscription.retrieve(subscription_id)
::Stripe::Subscription.retrieve(subscription_id)
end

private
Expand Down
5 changes: 3 additions & 2 deletions pay.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ Gem::Specification.new do |s|
s.authors = ['Jason Charnes']
s.email = ['[email protected]']
s.homepage = 'https://github.com/jasoncharnes/pay'
s.summary = 'A wrapper for handing subscriptions in Rails.'
s.description = 'A wrapper for handing subscriptions in Rails.'
s.summary = 'A Ruby on Rails subscription engine.'
s.description = 'A Ruby on Rails subscription engine.'
s.license = 'MIT'

s.files = Dir[
Expand All @@ -26,6 +26,7 @@ Gem::Specification.new do |s|
s.add_dependency 'braintree', '~> 2.75'

s.add_development_dependency 'byebug'
s.add_development_dependency 'mocha'
s.add_development_dependency 'pry'
s.add_development_dependency 'rubocop'
s.add_development_dependency 'sqlite3'
Expand Down
101 changes: 101 additions & 0 deletions test/models/subscription_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,31 @@ class Pay::Subscription::Test < ActiveSupport::TestCase
assert klass, 'User'
end

test '.for_name(name) scope' do
owner = User.create

subscription1 = Subscription.create!(
name: 'default',
owner: owner,
processor: 'stripe',
processor_id: '1',
processor_plan: 'default',
quantity: '1'
)

subscription2 = Subscription.create!(
name: 'superior',
owner: owner,
processor: 'stripe',
processor_id: '1',
processor_plan: 'superior',
quantity: '1'
)

assert_includes Subscription.for_name('default'), subscription1
refute_includes Subscription.for_name('default'), subscription2
end

test 'active trial' do
@subscription.trial_ends_at = 5.minutes.from_now
assert @subscription.on_trial?
Expand All @@ -25,6 +50,16 @@ class Pay::Subscription::Test < ActiveSupport::TestCase
refute @subscription.on_trial?
end

test 'cancelled' do
@subscription.ends_at = 1.week.ago
assert @subscription.cancelled?
end

test 'not cancelled' do
@subscription.ends_at = nil
refute @subscription.cancelled?
end

test 'on grace period' do
@subscription.ends_at = 5.minutes.from_now
assert @subscription.on_grace_period?
Expand All @@ -51,4 +86,70 @@ class Pay::Subscription::Test < ActiveSupport::TestCase
@subscription.trial_ends_at = nil
refute @subscription.active?
end

test 'cancel' do
expiration = 2.weeks.from_now

cancelled_stripe = mock('cancelled_stripe_subscription')
cancelled_stripe.expects(:current_period_end).returns(expiration)

stripe_sub = mock('stripe_subscription')
stripe_sub.expects(:delete).returns(cancelled_stripe)

@subscription.stubs(:processor_subscription).returns(stripe_sub)
@subscription.cancel

assert @subscription.ends_at, expiration
end

test 'cancel_now!' do
expiration = DateTime.now

cancelled_stripe = mock('cancelled_stripe_subscription')
cancelled_stripe.expects(:current_period_end).returns(expiration)

stripe_sub = mock('stripe_subscription')
stripe_sub.expects(:delete).returns(cancelled_stripe)

@subscription.stubs(:processor_subscription).returns(stripe_sub)
@subscription.cancel_now!

assert @subscription.ends_at, expiration
end

test 'resume on grace period' do
@subscription.ends_at = 2.weeks.from_now

stripe_sub = mock('stripe_subscription')
stripe_sub.expects(:plan=)
stripe_sub.expects(:trial_end=)
stripe_sub.expects(:save).returns(true)

@subscription.processor_plan = 'default'

@subscription.stubs(:on_grace_period?).returns(true)
@subscription.stubs(:processor_subscription).returns(stripe_sub)
@subscription.stubs(:on_trial?).returns(false)

@subscription.resume

assert_nil @subscription.ends_at
end

test 'resume off grace period' do
@subscription.stubs(:on_grace_period?).returns(false)

assert_raises StandardError do
@subscription.resume
end
end

test 'processor subscription' do
user = mock('user')
user.expects(:processor_subscription).returns(:result)

@subscription.stubs(:owner).returns(user)

assert :result, @subscription.processor_subscription
end
end
99 changes: 99 additions & 0 deletions test/pay/billable/stripe_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
require 'test_helper'
require 'stripe_mock'
require 'minitest/mock'

class Pay::Billable::Stripe::Test < ActiveSupport::TestCase
setup do
StripeMock.start

@billable = User.new

@stripe_helper = StripeMock.create_test_helper
@stripe_helper.create_plan(id: 'test-monthly', amount: 1500)
end

teardown do
StripeMock.stop
end

test 'getting a stripe customer with a processor id' do
customer = Stripe::Customer.create(
email: '[email protected]',
card: @stripe_helper.generate_card_token
)

@billable.processor_id = customer.id

assert_equal @billable.stripe_customer, customer
end

test 'getting a stripe customer without a processor id' do
assert_nil @billable.processor
assert_nil @billable.processor_id

@billable.email = '[email protected]'
@billable.card_token = @stripe_helper.generate_card_token(
brand: 'Visa',
last4: '9191',
exp_year: 1984
)

@billable.stripe_customer

assert_equal @billable.processor, 'stripe'
assert_not_nil @billable.processor_id
end

test 'can create a subscription' do
@billable.card_token = @stripe_helper.generate_card_token(
brand: 'Visa',
last4: '9191',
exp_year: 1984
)
@billable.subscribe('default', 'test-monthly')

assert @billable.subscribed?
assert_equal 'default', @billable.subscription.name
assert_equal 'test-monthly', @billable.subscription.processor_plan
end

test 'can update their card' do
customer = Stripe::Customer.create(
email: '[email protected]',
card: @stripe_helper.generate_card_token
)

@billable.stubs(:customer).returns(customer)
card = @stripe_helper.generate_card_token(brand: 'Visa', last4: '4242')
@billable.processor = 'stripe'
@billable.update_card(card)

assert @billable.card_brand == 'Visa'
assert @billable.card_last4 == '4242'

card = @stripe_helper.generate_card_token(
brand: 'Discover',
last4: '1117'
)
@billable.update_card(card)

assert @billable.card_brand == 'Discover'
assert @billable.card_last4 == '1117'
end

test 'retriving a stripe subscription' do
@stripe_helper.create_plan(id: 'default', amount: 1500)

customer = Stripe::Customer.create(
email: '[email protected]',
source: @stripe_helper.generate_card_token(brand: 'Visa', last4: '4242')
)

subscription = Stripe::Subscription.create(
plan: 'default',
customer: customer.id
)

assert_equal @billable.stripe_subscription(subscription.id), subscription
end
end
Loading

0 comments on commit 2cfd1fb

Please sign in to comment.