diff --git a/lib/stripe.rb b/lib/stripe.rb index a06e84a7..b954297f 100644 --- a/lib/stripe.rb +++ b/lib/stripe.rb @@ -43,6 +43,7 @@ require 'stripe/recipient' require 'stripe/bank_account' require 'stripe/card' require 'stripe/subscription' +require 'stripe/subscription_item' require 'stripe/application_fee' require 'stripe/refund' require 'stripe/reversal' diff --git a/lib/stripe/subscription_item.rb b/lib/stripe/subscription_item.rb new file mode 100644 index 00000000..13dcc3ba --- /dev/null +++ b/lib/stripe/subscription_item.rb @@ -0,0 +1,12 @@ +module Stripe + class SubscriptionItem < APIResource + extend Stripe::APIOperations::Create + include Stripe::APIOperations::Delete + extend Stripe::APIOperations::List + include Stripe::APIOperations::Save + + def self.resource_url + '/v1/subscription_items' + end + end +end diff --git a/lib/stripe/util.rb b/lib/stripe/util.rb index df43e9a4..48e8749d 100644 --- a/lib/stripe/util.rb +++ b/lib/stripe/util.rb @@ -42,6 +42,7 @@ module Stripe 'recipient' => Recipient, 'refund' => Refund, 'subscription' => Subscription, + 'subscription_item' => SubscriptionItem, 'file_upload' => FileUpload, 'token' => Token, 'transfer' => Transfer, diff --git a/test/stripe/invoice_test.rb b/test/stripe/invoice_test.rb index 42d16091..0fc06bd2 100644 --- a/test/stripe/invoice_test.rb +++ b/test/stripe/invoice_test.rb @@ -44,5 +44,23 @@ module Stripe i.pay assert_equal nil, i.next_payment_attempt end + + should "be able to retrieve upcoming invoices" do + base = "#{Stripe.api_base}/v1/invoices/upcoming?" + cus_sub = "customer=c_test_customer&subscription=s_test_subscription&" + item0 = "subscription_items[][plan]=gold&subscription_items[][quantity]=1&" + item1 = "subscription_items[][plan]=silver&subscription_items[][quantity]=2" + @mock.expects(:get).once.with(base + cus_sub + item0 + item1, nil, nil). + returns(make_response(make_invoice(:customer => 'c_test_customer', :subscription => 's_test_subscription'))) + + i = Stripe::Invoice.upcoming( + :customer => 'c_test_customer', + :subscription => 's_test_subscription', + :subscription_items => [{:plan => 'gold', :quantity =>1}, {:plan => 'silver', :quantity =>2}] + ) + + assert_equal 'c_test_customer', i.customer + assert_equal 's_test_subscription', i.subscription + end end end diff --git a/test/stripe/subscription_item_test.rb b/test/stripe/subscription_item_test.rb new file mode 100644 index 00000000..e06fb05f --- /dev/null +++ b/test/stripe/subscription_item_test.rb @@ -0,0 +1,76 @@ +require File.expand_path('../../test_helper', __FILE__) + +module Stripe + class SubscriptionItemTest < Test::Unit::TestCase + should "subscription items should be retrievable" do + @mock.expects(:get).once.with("#{Stripe.api_base}/v1/subscription_items/si_test_subscription_item", nil, nil). + returns(make_response(make_subscription_item)) + + sub_item = Stripe::SubscriptionItem.retrieve('si_test_subscription_item') + + assert sub_item.kind_of?(Stripe::SubscriptionItem) + end + + should "subscription items should be listable" do + @mock.expects(:get).once.with("#{Stripe.api_base}/v1/subscription_items?subscription=s_test_subscription&limit=3", nil, nil). + returns(make_response(make_subscription_item_array)) + sub_items = Stripe::SubscriptionItem.list(:subscription => 's_test_subscription', :limit => 3).data + + assert sub_items.kind_of? Array + assert sub_items[0].kind_of? Stripe::SubscriptionItem + end + + should "subscription items should be deletable" do + @mock.expects(:get).once.returns(make_response(make_subscription_item)) + sub_item = Stripe::SubscriptionItem.retrieve('si_test_subscription_item') + + @mock.expects(:delete).once.with("#{Stripe.api_base}/v1/subscription_items/#{sub_item.id}", nil, nil). + returns(make_response(make_subscription_item)) + sub_item.delete + end + + should "subscription items should be updateable" do + sid = 'si_test_subscription_item' + @mock.expects(:post).once.with do |url, api_key, params| + url == "#{Stripe.api_base}/v1/subscription_items/#{sid}" && + api_key.nil? && + CGI.parse(params) == {'plan' => ['silver'], 'quantity' => ['3']} + end.returns(make_response(make_subscription_item(:plan => 'silver', :quantity => 3))) + + sub_item = Stripe::SubscriptionItem.update(sid, {:plan => 'silver', :quantity => 3}) + + assert_equal 'silver', sub_item.plan.id + assert_equal 3, sub_item.quantity + end + + should "subscription items should be saveable" do + @mock.expects(:get).once.returns(make_response(make_subscription_item)) + sub_item = Stripe::SubscriptionItem.retrieve('si_test_subscription_item') + + @mock.expects(:post).once.with do |url, api_key, params| + url == "#{Stripe.api_base}/v1/subscription_items/#{sub_item.id}" && + api_key.nil? && + CGI.parse(params) == {'plan' => ['silver'], 'quantity' => ['3']} + end.returns(make_response(make_subscription_item(:plan => 'silver', :quantity => 3))) + + sub_item.plan = 'silver' + sub_item.quantity = 3 + sub_item.save + + assert_equal 'silver', sub_item.plan.id + assert_equal 3, sub_item.quantity + end + + should "create should return a new subscription item" do + @mock.expects(:post).once.with do |url, api_key, params| + url == "#{Stripe.api_base}/v1/subscription_items" && api_key.nil? && + CGI.parse(params) == {'plan' => ['silver'], 'quantity' => ['3']} + end.returns(make_response(make_subscription_item(:plan => 'silver', :quantity => 3))) + + sub_item = Stripe::SubscriptionItem.create(:plan => 'silver', :quantity => 3) + + assert_equal 'silver', sub_item.plan.id + assert_equal 3, sub_item.quantity + end + end +end diff --git a/test/stripe/subscription_test.rb b/test/stripe/subscription_test.rb index e53a7d13..b0e85f06 100644 --- a/test/stripe/subscription_test.rb +++ b/test/stripe/subscription_test.rb @@ -87,6 +87,27 @@ module Stripe assert_equal 'active', sub.status end + should "subscription items should be updateable" do + sid = 's_test_subscription' + items = {:data => [{:plan => {:id =>'gold'}, :quantity => 1}, {:plan => {:id =>'silver'}, :quantity => 2}]} + + @mock.expects(:post).once.with do |url, api_key, params| + url == "#{Stripe.api_base}/v1/subscriptions/#{sid}" && + api_key.nil? && + CGI.parse(params) == { + 'items[][plan]'=>['gold', 'silver'], + 'items[][quantity]'=>['1', '2'], + } + end.returns(make_response(make_subscription(:items => items))) + + sub = Stripe::Subscription.update(sid, :items => [{:plan => 'gold', :quantity =>1}, {:plan => 'silver', :quantity =>2}]) + + assert_equal 'gold', sub.items.data[0].plan.id + assert_equal 1, sub.items.data[0].quantity + assert_equal 'silver', sub.items.data[1].plan.id + assert_equal 2, sub.items.data[1].quantity + end + should "subscriptions should be saveable" do @mock.expects(:get).once.returns(make_response(make_subscription)) sub = Stripe::Subscription.retrieve('s_test_subscription') @@ -113,6 +134,28 @@ module Stripe assert_equal 'gold', sub.plan.identifier end + should "create with items should return a new subscription" do + items = {:data => [{:plan => {:id =>'gold'}, :quantity => 1}, {:plan => {:id =>'silver'}, :quantity => 2}]} + + @mock.expects(:post).once.with do |url, api_key, params| + url == "#{Stripe.api_base}/v1/subscriptions" && + api_key.nil? && + CGI.parse(params) == { + 'customer' => ['c_test_customer'], + 'items[][plan]'=>['gold', 'silver'], + 'items[][quantity]'=>['1', '2'], + } + end.returns(make_response(make_subscription(:items => items, :id => 'test_new_subscription'))) + + sub = Stripe::Subscription.create(:customer => 'c_test_customer', :items => [{:plan => 'gold', :quantity =>1}, {:plan => 'silver', :quantity =>2}]) + + assert_equal 'test_new_subscription', sub.id + assert_equal 'gold', sub.items.data[0].plan.id + assert_equal 1, sub.items.data[0].quantity + assert_equal 'silver', sub.items.data[1].plan.id + assert_equal 2, sub.items.data[1].quantity + end + should "be able to delete a subscriptions's discount" do @mock.expects(:post).once.returns(make_response(make_subscription)) sub = Stripe::Subscription.create(:plan => 'gold', :customer => 'c_test_customer', coupon: 'forever') diff --git a/test/test_data.rb b/test/test_data.rb index 816676d7..2e40c574 100644 --- a/test/test_data.rb +++ b/test/test_data.rb @@ -277,6 +277,24 @@ module Stripe }.merge(params) end + def make_subscription_item(params = {}) + plan = params.delete(:plan) || 'gold' + { + :id => "si_test_subscription_item", + :object => "subscription_item", + :created => 1473875521, + :plan => { + :id => plan, + :object => "plan", + :amount => 1000, + :created => 1468349629, + :currency => "usd", + :interval => "month", + }, + :quantity => 1 + }.merge(params) + end + def make_refund(params = {}) { :object => 'refund', @@ -297,6 +315,14 @@ module Stripe } end + def make_subscription_item_array + { + :data => [make_subscription_item, make_subscription_item, make_subscription_item], + :object => 'list', + :resource_url => '/v1/subscription_items' + } + end + def make_customer_subscription_array(customer_id) { :data => [make_subscription, make_subscription, make_subscription],