vitalish-chargify_api_ares 0.3.9

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,51 @@
1
+ $: << File.expand_path(File.dirname(__FILE__) + '/../lib')
2
+
3
+ require 'chargify_api_ares'
4
+
5
+ # You could load your credentials from a file...
6
+ chargify_config = YAML::load_file(File.join(File.dirname(__FILE__), '..', 'config', 'chargify.yml'))
7
+
8
+ Chargify.configure do |c|
9
+ c.subdomain = chargify_config['subdomain']
10
+ c.api_key = chargify_config['api_key']
11
+ end
12
+
13
+
14
+ # Retrieve a list of all your customers
15
+ Chargify::Customer.find(:all)
16
+ # => [#<Chargify::Customer:0x102d0cef8 @prefix_options={}, @attributes={"reference"=>"moklett", "updated_at"=>Mon Nov 16 23:19:25 UTC 2009, "id"=>325, "first_name"=>"Michael", "organization"=>"Chargify", "last_name"=>"Klett", "email"=>"moklett@example.com", "created_at"=>Mon Nov 16 23:19:25 UTC 2009}>]
17
+
18
+
19
+ customer = Chargify::Customer.find(325)
20
+
21
+ customer.first_name
22
+ # => Michael
23
+
24
+ customer.last_name
25
+ # => Klett
26
+
27
+ # Update a customer - success!
28
+ customer.first_name = "Miguel"
29
+ customer.save
30
+ # => true
31
+
32
+ customer.first_name
33
+ # => Miguel
34
+
35
+ # Update a customer - fail!
36
+ customer.first_name = ""
37
+ customer.save
38
+ # => false
39
+
40
+ customer.errors.full_messages.inspect
41
+ # => ["First name: cannot be blank."]
42
+
43
+
44
+ # Create a new customer - success!
45
+ Chargify::Customer.create(
46
+ :first_name => "Charlie",
47
+ :last_name => "Bull",
48
+ :email => "charlie@example.com",
49
+ :organization => "Chargify"
50
+ )
51
+ # => #<Chargify::Customer:0x102c27970 @prefix_options={}, @attributes={"reference"=>nil, "updated_at"=>Mon Nov 16 23:43:33 UTC 2009, "id"=>327, "organization"=>"Chargify", "first_name"=>"Charlie", "last_name"=>"Bull", "created_at"=>Mon Nov 16 23:43:33 UTC 2009, "email"=>"charlie@example.com"}>
@@ -0,0 +1,35 @@
1
+ $: << File.expand_path(File.dirname(__FILE__) + '/../lib')
2
+
3
+ require 'chargify_api_ares'
4
+
5
+ # You could load your credentials from a file...
6
+ chargify_config = YAML::load_file(File.join(File.dirname(__FILE__), '..', 'config', 'chargify.yml'))
7
+
8
+ Chargify.configure do |c|
9
+ c.subdomain = chargify_config['subdomain']
10
+ c.api_key = chargify_config['api_key']
11
+ if chargify_config['site']
12
+ c.site = chargify_config['site']
13
+ end
14
+ end
15
+
16
+ #
17
+ # This assumes you have a product family with a metered component setup
18
+ #
19
+ product_family = Chargify::ProductFamily.find(:first)
20
+ component = Chargify::Component.find(:first, :params => {:product_family_id => product_family.id})
21
+ subscription = Chargify::Subscription.find(:first)
22
+
23
+
24
+ u = Chargify::Usage.new
25
+ u.subscription_id = subscription.id
26
+ u.component_id = component.id
27
+ u.quantity = 5
28
+ d = DateTime.now.to_s
29
+ u.memo = d
30
+ puts d
31
+ u.save
32
+
33
+
34
+ x = Chargify::Usage.find(:last, :params => {:subscription_id => subscription.id, :component_id => component.id})
35
+ puts x.memo == d
@@ -0,0 +1,24 @@
1
+ $: << File.expand_path(File.dirname(__FILE__) + '/../lib')
2
+
3
+ require 'chargify_api_ares'
4
+
5
+ # You could load your credentials from a file...
6
+ chargify_config = YAML::load_file(File.join(File.dirname(__FILE__), '..', 'config', 'chargify.yml'))
7
+
8
+ Chargify.configure do |c|
9
+ c.subdomain = chargify_config['subdomain']
10
+ c.api_key = chargify_config['api_key']
11
+ end
12
+
13
+
14
+ # Retrieve a list of all your products
15
+ products = Chargify::Product.find(:all)
16
+ # => [#<Chargify::Product:0x102cdcac8 @prefix_options={}, @attributes={"name"=>"Chargify API Ares Test", "price_in_cents"=>0, "handle"=>"chargify-api-ares-test", "product_family"=>#<Chargify::Product::ProductFamily:0x102cdbad8 @prefix_options={}, @attributes={"name"=>"Chargify API ARes Test", "handle"=>"chargify-api-ares-test", "id"=>78, "accounting_code"=>nil}>, "id"=>152, "accounting_code"=>nil, "interval_unit"=>"month", "interval"=>1}>]
17
+
18
+ # Find a single product by id
19
+ product = Chargify::Product.find(products.first.id)
20
+ # => #<Chargify::Product:0x102ce7540 @prefix_options={}, @attributes={"price_in_cents"=>0, "name"=>"Chargify API Ares Test", "handle"=>"chargify-api-ares-test", "product_family"=>#<Chargify::Product::ProductFamily:0x102ce6ca8 @prefix_options={}, @attributes={"name"=>"Chargify API ARes Test", "handle"=>"chargify-api-ares-test", "id"=>78, "accounting_code"=>nil}>, "id"=>152, "accounting_code"=>nil, "interval_unit"=>"month", "interval"=>1}>
21
+
22
+ # Find a single product by its handle
23
+ product = Chargify::Product.find_by_handle(products.first.handle)
24
+ # => #<Chargify::Product:0x102c7a828 @prefix_options={}, @attributes={"price_in_cents"=>0, "name"=>"Chargify API Ares Test", "handle"=>"chargify-api-ares-test", "product_family"=>#<Chargify::Product::ProductFamily:0x102c798b0 @prefix_options={}, @attributes={"name"=>"Chargify API ARes Test", "handle"=>"chargify-api-ares-test", "id"=>78, "accounting_code"=>nil}>, "id"=>152, "accounting_code"=>nil, "interval_unit"=>"month", "interval"=>1}>
@@ -0,0 +1,53 @@
1
+ $: << File.expand_path(File.dirname(__FILE__) + '/../lib')
2
+
3
+ require 'chargify_api_ares'
4
+
5
+ # You could load your credentials from a file...
6
+ chargify_config = YAML::load_file(File.join(File.dirname(__FILE__), '..', 'config', 'chargify.yml'))
7
+
8
+ Chargify.configure do |c|
9
+ c.subdomain = chargify_config['subdomain']
10
+ c.api_key = chargify_config['api_key']
11
+ end
12
+
13
+
14
+ # Retrieve a list of all your customers
15
+ subscription = Chargify::Subscription.find(:all)
16
+ # => [#<Chargify::Subscription:0x1020fff70 @prefix_options={}, @attributes={"cancellation_message"=>nil, "activated_at"=>Tue Nov 17 15:51:42 UTC 2009, "expires_at"=>nil, "updated_at"=>Tue Nov 17 15:51:41 UTC 2009, "credit_card"=>#<Chargify::Subscription::CreditCard:0x1020f24d8 @prefix_options={}, @attributes={"card_type"=>"bogus", "expiration_year"=>2015, "masked_card_number"=>"XXXX-XXXX-XXXX-2", "first_name"=>"Michael", "expiration_month"=>1, "last_name"=>"Klett"}>, "product"=>#<Chargify::Product:0x1020f5a70 @prefix_options={}, @attributes={"price_in_cents"=>0, "name"=>"Chargify API Ares Test", "handle"=>"chargify-api-ares-test", "product_family"=>#<Chargify::Product::ProductFamily:0x1020f48f0 @prefix_options={}, @attributes={"name"=>"Chargify API ARes Test", "handle"=>"chargify-api-ares-test", "id"=>79, "accounting_code"=>nil}>, "id"=>153, "accounting_code"=>nil, "interval_unit"=>"month", "interval"=>1}>, "trial_ended_at"=>nil, "id"=>328, "current_period_ends_at"=>Thu Dec 17 15:51:41 UTC 2009, "trial_started_at"=>nil, "customer"=>#<Chargify::Customer:0x1020f6d80 @prefix_options={}, @attributes={"reference"=>"moklett", "updated_at"=>Tue Nov 17 15:51:02 UTC 2009, "id"=>331, "first_name"=>"Michael", "organization"=>"Chargify", "last_name"=>"Klett", "email"=>"moklett@example.com", "created_at"=>Tue Nov 17 15:51:02 UTC 2009}>, "balance_in_cents"=>0, "current_period_started_at"=>Tue Nov 17 15:51:41 UTC 2009, "state"=>"canceled", "created_at"=>Tue Nov 17 15:51:41 UTC 2009}>]]
17
+
18
+
19
+ # Create a subscription from a customer reference
20
+ subscription = Chargify::Subscription.create(
21
+ :customer_reference => 'moklett',
22
+ :product_handle => 'chargify-api-ares-test',
23
+ :credit_card_attributes => {
24
+ :first_name => "Michael",
25
+ :last_name => "Klett",
26
+ :expiration_month => 1,
27
+ :expiration_year => 2020,
28
+ :full_number => "1"
29
+ }
30
+ )
31
+ # => #<Chargify::Subscription:0x1020ed4b0 @prefix_options={}, @attributes={"cancellation_message"=>nil, "activated_at"=>Tue Nov 17 16:00:17 UTC 2009, "expires_at"=>nil, "updated_at"=>Tue Nov 17 16:00:17 UTC 2009, "credit_card"=>#<Chargify::Subscription::CreditCard:0x102046b10 @prefix_options={}, @attributes={"card_type"=>"bogus", "expiration_year"=>2020, "masked_card_number"=>"XXXX-XXXX-XXXX-1", "first_name"=>"Michael", "expiration_month"=>1, "last_name"=>"Klett"}>, "product"=>#<Chargify::Product:0x10204a2d8 @prefix_options={}, @attributes={"price_in_cents"=>0, "name"=>"Chargify API Ares Test", "handle"=>"chargify-api-ares-test", "product_family"=>#<Chargify::Product::ProductFamily:0x1020490b8 @prefix_options={}, @attributes={"name"=>"Chargify API ARes Test", "handle"=>"chargify-api-ares-test", "id"=>79, "accounting_code"=>nil}>, "id"=>153, "accounting_code"=>nil, "interval_unit"=>"month", "interval"=>1}>, "credit_card_attributes"=>#<Chargify::Subscription::CreditCardAttributes:0x1020ecab0 @prefix_options={}, @attributes={"expiration_year"=>2020, "full_number"=>"1", "first_name"=>"Michael", "expiration_month"=>1, "last_name"=>"Klett"}>, "trial_ended_at"=>nil, "id"=>331, "current_period_ends_at"=>Thu Dec 17 16:00:17 UTC 2009, "product_handle"=>"chargify-api-ares-test", "trial_started_at"=>nil, "customer"=>#<Chargify::Customer:0x10204b688 @prefix_options={}, @attributes={"reference"=>"moklett", "updated_at"=>Tue Nov 17 15:51:02 UTC 2009, "id"=>331, "first_name"=>"Michael", "organization"=>"Chargify", "last_name"=>"Klett", "email"=>"moklett@example.com", "created_at"=>Tue Nov 17 15:51:02 UTC 2009}>, "balance_in_cents"=>0, "current_period_started_at"=>Tue Nov 17 16:00:17 UTC 2009, "state"=>"active", "created_at"=>Tue Nov 17 16:00:17 UTC 2009, "customer_reference"=>"moklett"}>
32
+
33
+
34
+ # Lookup up existing Subscription using the Customer's reference
35
+ Subscription.find_by_customer_reference('moklett')
36
+ # => #<Chargify::Subscription:0x1020ed4b0 @prefix_options={}, @attributes={"cancellation_message"=>nil, "activated_at"=>Tue Nov 17 16:00:17 UTC 2009, "expires_at"=>nil, "updated_at"=>Tue Nov 17 16:00:17 UTC 2009, "credit_card"=>#<Chargify::Subscription::CreditCard:0x102046b10 @prefix_options={}, @attributes={"card_type"=>"bogus", "expiration_year"=>2020, "masked_card_number"=>"XXXX-XXXX-XXXX-1", "first_name"=>"Michael", "expiration_month"=>1, "last_name"=>"Klett"}>, "product"=>#<Chargify::Product:0x10204a2d8 @prefix_options={}, @attributes={"price_in_cents"=>0, "name"=>"Chargify API Ares Test", "handle"=>"chargify-api-ares-test", "product_family"=>#<Chargify::Product::ProductFamily:0x1020490b8 @prefix_options={}, @attributes={"name"=>"Chargify API ARes Test", "handle"=>"chargify-api-ares-test", "id"=>79, "accounting_code"=>nil}>, "id"=>153, "accounting_code"=>nil, "interval_unit"=>"month", "interval"=>1}>, "trial_ended_at"=>nil, "id"=>331, "current_period_ends_at"=>Thu Dec 17 16:00:17 UTC 2009, "product_handle"=>"chargify-api-ares-test", "trial_started_at"=>nil, "customer"=>#<Chargify::Customer:0x10204b688 @prefix_options={}, @attributes={"reference"=>"moklett", "updated_at"=>Tue Nov 17 15:51:02 UTC 2009, "id"=>331, "first_name"=>"Michael", "organization"=>"Chargify", "last_name"=>"Klett", "email"=>"moklett@example.com", "created_at"=>Tue Nov 17 15:51:02 UTC 2009}>, "balance_in_cents"=>0, "current_period_started_at"=>Tue Nov 17 16:00:17 UTC 2009, "state"=>"active", "created_at"=>Tue Nov 17 16:00:17 UTC 2009, "customer_reference"=>"moklett"}>
37
+
38
+
39
+ # Update credit card information
40
+ subscription.credit_card_attributes = {:full_number => "2", :expiration_year => "2015"}
41
+ subscription.save
42
+ # => #<Chargify::Subscription:0x1020ed4b0 @prefix_options={}, @attributes={"cancellation_message"=>nil, "activated_at"=>Tue Nov 17 16:00:17 UTC 2009, "expires_at"=>nil, "updated_at"=>Tue Nov 17 16:00:17 UTC 2009, "credit_card"=>#<Chargify::Subscription::CreditCard:0x1023ba878 @prefix_options={}, @attributes={"card_type"=>"bogus", "expiration_year"=>2015, "masked_card_number"=>"XXXX-XXXX-XXXX-2", "first_name"=>"Michael", "expiration_month"=>1, "last_name"=>"Klett"}>, "product"=>#<Chargify::Product:0x1023baa80 @prefix_options={}, @attributes={"price_in_cents"=>0, "name"=>"Chargify API Ares Test", "handle"=>"chargify-api-ares-test", "product_family"=>#<Chargify::Product::ProductFamily:0x1023c04d0 @prefix_options={}, @attributes={"name"=>"Chargify API ARes Test", "handle"=>"chargify-api-ares-test", "id"=>79, "accounting_code"=>nil}>, "id"=>153, "accounting_code"=>nil, "interval_unit"=>"month", "interval"=>1}>, "credit_card_attributes"=>{:full_number=>"2", :expiration_year=>"2015"}, "trial_ended_at"=>nil, "id"=>331, "current_period_ends_at"=>Thu Dec 17 16:00:17 UTC 2009, "product_handle"=>"chargify-api-ares-test", "customer"=>#<Chargify::Customer:0x1023bae40 @prefix_options={}, @attributes={"reference"=>"moklett", "updated_at"=>Tue Nov 17 15:51:02 UTC 2009, "id"=>331, "first_name"=>"Michael", "organization"=>"Chargify", "last_name"=>"Klett", "email"=>"moklett@example.com", "created_at"=>Tue Nov 17 15:51:02 UTC 2009}>, "trial_started_at"=>nil, "balance_in_cents"=>0, "current_period_started_at"=>Tue Nov 17 16:00:17 UTC 2009, "state"=>"active", "created_at"=>Tue Nov 17 16:00:17 UTC 2009, "customer_reference"=>"moklett"}>
43
+
44
+
45
+ # Perform a one-time charge against an existing subscription
46
+ subscription.charge(:amount => 10.00, :memo => 'Extra service')
47
+ # => #<Net::HTTPCreated>
48
+
49
+
50
+ # Cancel a subscription
51
+ subscription.cancel
52
+ subscription.reload
53
+ # => #<Chargify::Subscription:0x1020ed4b0 @prefix_options={}, @attributes={"cancellation_message"=>nil, "activated_at"=>Tue Nov 17 16:00:17 UTC 2009, "expires_at"=>nil, "updated_at"=>Tue Nov 17 16:00:17 UTC 2009, "credit_card"=>#<Chargify::Subscription::CreditCard:0x10234f168 @prefix_options={}, @attributes={"card_type"=>"bogus", "expiration_year"=>2015, "masked_card_number"=>"XXXX-XXXX-XXXX-2", "first_name"=>"Michael", "expiration_month"=>1, "last_name"=>"Klett"}>, "product"=>#<Chargify::Product:0x10234f370 @prefix_options={}, @attributes={"price_in_cents"=>0, "name"=>"Chargify API Ares Test", "handle"=>"chargify-api-ares-test", "product_family"=>#<Chargify::Product::ProductFamily:0x102354708 @prefix_options={}, @attributes={"name"=>"Chargify API ARes Test", "handle"=>"chargify-api-ares-test", "id"=>79, "accounting_code"=>nil}>, "id"=>153, "accounting_code"=>nil, "interval_unit"=>"month", "interval"=>1}>, "credit_card_attributes"=>{:full_number=>"2", :expiration_year=>"2015"}, "trial_ended_at"=>nil, "id"=>331, "current_period_ends_at"=>Thu Dec 17 16:00:17 UTC 2009, "product_handle"=>"chargify-api-ares-test", "customer"=>#<Chargify::Customer:0x10234f730 @prefix_options={}, @attributes={"reference"=>"moklett", "updated_at"=>Tue Nov 17 15:51:02 UTC 2009, "id"=>331, "first_name"=>"Michael", "organization"=>"Chargify", "last_name"=>"Klett", "email"=>"moklett@example.com", "created_at"=>Tue Nov 17 15:51:02 UTC 2009}>, "trial_started_at"=>nil, "balance_in_cents"=>0, "current_period_started_at"=>Tue Nov 17 16:00:17 UTC 2009, "state"=>"canceled", "created_at"=>Tue Nov 17 16:00:17 UTC 2009, "customer_reference"=>"moklett"}>
@@ -0,0 +1,17 @@
1
+ $: << File.expand_path(File.dirname(__FILE__) + '/../lib')
2
+
3
+ require 'chargify_api_ares'
4
+
5
+ # You could load your credentials from a file...
6
+ chargify_config = YAML::load_file(File.join(File.dirname(__FILE__), '..', 'config', 'chargify.yml'))
7
+
8
+ Chargify.configure do |c|
9
+ c.subdomain = chargify_config['subdomain']
10
+ c.api_key = chargify_config['api_key']
11
+ end
12
+
13
+
14
+ # Retrieve a list of all your customers
15
+ subscription = Chargify::Subscription.find(:all).first
16
+
17
+ transactions = subscription.transactions
@@ -0,0 +1,10 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe Chargify::Base do
4
+
5
+ it 'parses element names' do
6
+ Chargify::Base.stub!(:name).and_return("Test::Namespace::ElementName")
7
+ Chargify::Base.element_name.should eql('element_name')
8
+ end
9
+
10
+ end
@@ -0,0 +1,48 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe Chargify::Component do
4
+ describe "Recording usage" do
5
+ before do
6
+ @subscription = Factory(:subscription)
7
+ @component = Factory(:component)
8
+ @now = DateTime.now.to_s
9
+ end
10
+
11
+ it "should create a usage record" do
12
+ u = Chargify::Usage.new
13
+ u.subscription_id = @subscription.id
14
+ u.component_id = @component.id
15
+ u.quantity = 5
16
+ u.memo = @now
17
+ u.save
18
+
19
+ component = Chargify::Usage.find(:last, :params => {:subscription_id => @subscription.id, :component_id => @component.id})
20
+ component.memo.should == @now
21
+ component.quantity.should == 5
22
+ end
23
+ end
24
+
25
+ describe "Listing usages" do
26
+ before do
27
+ @subscription = Factory(:subscription)
28
+ @component = Factory(:component)
29
+ @now = DateTime.now.to_s
30
+ create_usage
31
+ end
32
+
33
+ it "should return all usages for a component and subscription" do
34
+ component = Chargify::Usage.find(:last, :params => {:subscription_id => @subscription.id, :component_id => @component.id})
35
+ component.quantity.should == 5
36
+ end
37
+ end
38
+
39
+ def create_usage
40
+ u = Chargify::Usage.new
41
+ u.subscription_id = @subscription.id
42
+ u.component_id = @component.id
43
+ u.quantity = 5
44
+ u.memo = @now
45
+ u.save
46
+ end
47
+ end
48
+
@@ -0,0 +1,23 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe Chargify::Customer do
4
+
5
+ context 'find by reference' do
6
+ before do
7
+ @reference = 'ref0123'
8
+ @existing_customer = Factory(:customer, :reference => @reference, :id => Factory.next(:customer_id))
9
+ FakeWeb.register_uri(:get, "#{test_domain}/customers/lookup.xml?reference=#{@existing_customer.reference}", :body => @existing_customer.attributes.to_xml)
10
+ end
11
+
12
+ it 'finds the correct customer by reference' do
13
+ customer = Chargify::Customer.find_by_reference(@reference)
14
+ customer.should eql(@existing_customer)
15
+ end
16
+
17
+ it 'is an instance of Chargify::Customer' do
18
+ customer = Chargify::Customer.find_by_reference(@reference)
19
+ customer.should be_instance_of(Chargify::Customer)
20
+ end
21
+ end
22
+
23
+ end
@@ -0,0 +1,62 @@
1
+ Factory.sequence :email do |n|
2
+ "customer#{n}@example.com"
3
+ end
4
+
5
+ Factory.sequence :customer_id do |n|
6
+ n
7
+ end
8
+
9
+ Factory.define :customer, :class => Chargify::Customer do |c|
10
+ c.first_name { Faker::Name.first_name }
11
+ c.last_name { Faker::Name.last_name }
12
+ c.email { Factory.next(:email) }
13
+ c.organization { Faker::Company.name }
14
+ c.created_at { 2.days.ago }
15
+ c.updated_at { 1.hour.ago }
16
+ end
17
+
18
+
19
+ Factory.sequence :product_id do |n|
20
+ n
21
+ end
22
+
23
+ Factory.sequence :product_name do |n|
24
+ "Product #{n}"
25
+ end
26
+
27
+ Factory.define :product, :class => Chargify::Product do |p|
28
+ p.name { Factory.next(:product_name) }
29
+ end
30
+
31
+ Factory.sequence :subscription_id do |n|
32
+ n
33
+ end
34
+
35
+ Factory.define :subscription, :class => Chargify::Subscription do |s|
36
+ s.balance_in_cents 500
37
+ s.current_period_ends_at 3.days.from_now
38
+ end
39
+
40
+ Factory.define :subscription_with_extra_attrs, :parent => :subscription do |swea|
41
+ swea.customer Chargify::Customer.new
42
+ swea.product Chargify::Product.new
43
+ swea.credit_card "CREDIT CARD"
44
+ end
45
+
46
+ Factory.define :component, :class => Chargify::Component do |f|
47
+ f.name { Faker::Company.bs }
48
+ f.unit_name 'unit'
49
+ end
50
+
51
+ Factory.define :quantity_based_component, :class => Chargify::Component do |f|
52
+ f.name { Faker::Company.bs }
53
+ f.unit_name 'unit'
54
+ f.pricing_scheme 'tiered'
55
+ f.component_type 'quantity_based_component'
56
+ end
57
+
58
+ Factory.define :subscriptions_component, :class => Chargify::Subscription::Component do |f|
59
+ f.name { Faker::Company.bs }
60
+ f.unit_name 'unit'
61
+ f.component_type 'quantity_based_component'
62
+ end
@@ -0,0 +1,82 @@
1
+ # Taken from https://gist.github.com/238158/487a411c392e1fb2a0c00347e32444320f5cdd49
2
+ require 'FakeWeb'
3
+
4
+ module ActiveResource
5
+
6
+ #
7
+ # The FakeResource fakes ActiveResources so that no real resources are transferred. It catches the creation methods
8
+ # and stores the resources internally instead of sending to a remote service and responds these resources back on
9
+ # request.
10
+ #
11
+ # Additionally it adds a save! method and can be used in conjunction with Cucumber/Pickle/FactoryGirl to fully
12
+ # fake a back end service in the BDD cycle
13
+ #
14
+ module FakeResource
15
+
16
+ @@fake_resources = []
17
+
18
+ def self.clean
19
+ FakeWeb.clean_registry
20
+ @@fake_resources = []
21
+ end
22
+
23
+ def self.included(base)
24
+ base.class_eval do
25
+
26
+ def save
27
+ @@fake_resources << self
28
+ update_fake_responses
29
+ end
30
+
31
+ def destroy
32
+ @@fake_resources.delete(self)
33
+ update_fake_responses
34
+ end
35
+
36
+ def self.delete(id, options = {})
37
+ puts "delete"
38
+ @@fake_resources.delete_if {|r| r.id == id }
39
+ #update_fake_responses
40
+ end
41
+
42
+ def self.exists?(id, options = {})
43
+ not @@fake_resources.select {|r| r.id == id}.blank?
44
+ end
45
+
46
+ end
47
+ end
48
+
49
+ def save!
50
+ save
51
+ end
52
+
53
+ def save
54
+ super
55
+ end
56
+
57
+ private
58
+
59
+ def update_fake_responses
60
+ FakeWeb.clean_registry
61
+
62
+ @@fake_resources.each do |r|
63
+ FakeWeb.register_uri(:get, element_uri, :body => r.to_xml)
64
+ end
65
+
66
+ FakeWeb.register_uri(:get, collection_uri, :body => @@fake_resources.to_xml)
67
+ end
68
+
69
+ def element_uri
70
+ "#{base_uri}#{element_path}"
71
+ end
72
+
73
+ def collection_uri
74
+ "#{base_uri}#{collection_path}"
75
+ end
76
+
77
+ def base_uri
78
+ "#{connection.site.scheme}://#{connection.user}:#{connection.password}@#{connection.site.host}:#{connection.site.port}"
79
+ end
80
+
81
+ end
82
+ end
@@ -0,0 +1,23 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe Chargify::Product do
4
+
5
+ context 'find by handle' do
6
+ before do
7
+ @handle = 'handle1'
8
+ @existing_product = Factory(:product, :handle => @handle, :id => Factory.next(:product_id))
9
+ FakeWeb.register_uri(:get, "#{test_domain}/products/lookup.xml?handle=#{@existing_product.handle}", :body => @existing_product.attributes.to_xml)
10
+ end
11
+
12
+ it 'finds the correct product by handle' do
13
+ product = Chargify::Product.find_by_handle(@handle)
14
+ product.should eql(@existing_product)
15
+ end
16
+
17
+ it 'is an instance of Chargify::Product' do
18
+ product = Chargify::Product.find_by_handle(@handle)
19
+ product.should be_instance_of(Chargify::Product)
20
+ end
21
+ end
22
+
23
+ end
@@ -0,0 +1,514 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ if run_remote_tests?
4
+ describe "Remote" do
5
+ before(:all) do
6
+ clear_site_data
7
+ setup_plans
8
+ setup_customer
9
+ end
10
+
11
+ describe "creating a new subscription to a product with a trial" do
12
+ context "when providing valid attributes for the customer and the payment profile" do
13
+ before(:each) do
14
+ @subscription = create_once(:subscription) do
15
+ Chargify::Subscription.create(
16
+ :product_handle => @@basic_plan.handle,
17
+ :customer_attributes => valid_customer_attributes,
18
+ :payment_profile_attributes => good_payment_profile_attributes
19
+ )
20
+ end
21
+ end
22
+
23
+ it "successfully creates the subscription" do
24
+ @subscription.should be_a(Chargify::Subscription)
25
+ end
26
+
27
+ it "sets the current_period_started_at attribute to now" do
28
+ @subscription.current_period_started_at.utc.should be_close(now.utc, approximately)
29
+ end
30
+
31
+ it "sets the current_period_ends_at attribute to 1 month from now" do
32
+ @subscription.current_period_ends_at.utc.should be_close(one_month_from_now.utc, approximately)
33
+ end
34
+
35
+ it "is in the trialing state" do
36
+ @subscription.state.should == 'trialing'
37
+ end
38
+ end
39
+ end
40
+
41
+ describe "creating a new subscription to a product without a trial" do
42
+ context "when providing an existing customer reference and valid payment profile attributes" do
43
+ before(:each) do
44
+ @subscription = create_once(:subscription) do
45
+ Chargify::Subscription.create(
46
+ :product_handle => @@pro_plan.handle,
47
+ :customer_reference => @@johnadoe.reference,
48
+ :payment_profile_attributes => good_payment_profile_attributes
49
+ )
50
+ end
51
+ end
52
+
53
+ it "successfully creates the subscription" do
54
+ @subscription.should be_a(Chargify::Subscription)
55
+ end
56
+
57
+ it "sets the current_period_started_at attribute to now" do
58
+ @subscription.current_period_started_at.utc.should be_close(now.utc, approximately)
59
+ end
60
+
61
+ it "sets the current_period_ends_at attribute to 1 month from now" do
62
+ @subscription.current_period_ends_at.utc.should be_close(one_month_from_now.utc, approximately)
63
+ end
64
+
65
+ it "is in the active state" do
66
+ @subscription.state.should == 'active'
67
+ end
68
+
69
+ it "belongs to the existing customer" do
70
+ @subscription.customer.should == @@johnadoe
71
+ end
72
+ end
73
+
74
+ context "when providing an existing customer reference and an existing payment profile" do
75
+ before(:each) do
76
+ @subscription = create_once(:subscription) do
77
+ Chargify::Subscription.create(
78
+ :product_handle => @@pro_plan.handle,
79
+ :customer_reference => @@johnadoe.reference,
80
+ :payment_profile_id => @@johnadoes_credit_card.id.to_s
81
+ )
82
+ end
83
+ end
84
+
85
+ it "successfully creates the subscription" do
86
+ @subscription.should be_a(Chargify::Subscription)
87
+ end
88
+
89
+ it "is in the active state" do
90
+ @subscription.state.should == 'active'
91
+ end
92
+
93
+ it "belongs to the existing customer" do
94
+ @subscription.customer.should == @@johnadoe
95
+ end
96
+
97
+ it "uses the provided credit card" do
98
+ expected_card = Chargify::PaymentProfile.find(@@johnadoes_credit_card.id)
99
+ @subscription.payment_profile.id.should == @@johnadoes_credit_card.id
100
+ @subscription.payment_profile.attributes.should == expected_card.attributes
101
+ end
102
+ end
103
+
104
+ context "when providing valid attributes for the customer and attributes for a credit card that cannot be stored" do
105
+ before(:each) do
106
+ @customer_attributes = valid_customer_attributes.dup
107
+ @subscription = create_once(:subscription) do
108
+ Chargify::Subscription.create(
109
+ :product_handle => @@basic_plan.handle,
110
+ :customer_attributes => @customer_attributes,
111
+ :payment_profile_attributes => unstorable_payment_profile_attributes
112
+ )
113
+ end
114
+ end
115
+
116
+ it "does not create the subscription" do
117
+ @subscription.should_not be_valid
118
+ end
119
+
120
+ it "does not create the customer" do
121
+ lambda {
122
+ Chargify::Customer.find_by_reference(@customer_attributes[:reference])
123
+ }.should raise_error(ActiveResource::ResourceNotFound)
124
+ end
125
+ end
126
+
127
+ end
128
+
129
+ describe "importing a subscription to a product with a trial and a next billing date 10 days from now" do
130
+ context "when giving valid attributes for the customer and the payment profile" do
131
+ before(:each) do
132
+ @subscription = create_once(:subscription) do
133
+ Chargify::Subscription.create(
134
+ :product_handle => @@basic_plan.handle,
135
+ :customer_attributes => valid_customer_attributes,
136
+ :payment_profile_attributes => pretokenized_card_attributes,
137
+ :next_billing_at => ten_days_from_now.utc
138
+ )
139
+ end
140
+ end
141
+
142
+ it "successfully creates the subscription" do
143
+ @subscription.should be_a(Chargify::Subscription)
144
+ end
145
+
146
+ it "sets the current_period_started_at attribute to now" do
147
+ @subscription.current_period_started_at.utc.should be_close(now.utc, approximately)
148
+ end
149
+
150
+ it "sets the current_period_ends_at attribute to 1 month from now" do
151
+ @subscription.current_period_ends_at.utc.should be_close(ten_days_from_now.utc, approximately)
152
+ end
153
+
154
+ it "is in the active state" do
155
+ @subscription.state.should == 'active'
156
+ end
157
+ end
158
+ end
159
+
160
+ describe "creating failed subscriptions" do
161
+ context "due to providing payment profile attribtues for a card that will be declined" do
162
+ before(:each) do
163
+ @customer_attributes = valid_customer_attributes.dup
164
+ @subscription = create_once(:subscription) do
165
+ Chargify::Subscription.create(
166
+ :product_handle => @@pro_plan.handle,
167
+ :customer_attributes => @customer_attributes,
168
+ :payment_profile_attributes => declined_payment_profile_attributes
169
+ )
170
+ end
171
+ end
172
+
173
+ it "does not create the subscription" do
174
+ @subscription.should_not be_valid
175
+ end
176
+
177
+ it "does not create the customer" do
178
+ lambda {
179
+ Chargify::Customer.find_by_reference(@customer_attributes[:reference])
180
+ }.should raise_error(ActiveResource::ResourceNotFound)
181
+ end
182
+ end
183
+ end
184
+
185
+ describe "cancelling a subscription" do
186
+ before(:each) do
187
+ @subscription = create_once(:subscription) do
188
+ Chargify::Subscription.create(
189
+ :product_handle => @@pro_plan.handle,
190
+ :customer_reference => @@johnadoe.reference,
191
+ :payment_profile_attributes => good_payment_profile_attributes
192
+ )
193
+ end
194
+ @subscription.cancel
195
+ end
196
+
197
+ it "is in the canceled state" do
198
+ Chargify::Subscription.find(@subscription.id).state.should == 'canceled'
199
+ end
200
+ end
201
+
202
+ describe "reactivating a subscriptions" do
203
+ before(:each) do
204
+ @subscription = create_once(:subscription) do
205
+ Chargify::Subscription.create(
206
+ :product_handle => @@pro_plan.handle,
207
+ :customer_reference => @@johnadoe.reference,
208
+ :payment_profile_attributes => good_payment_profile_attributes
209
+ )
210
+ end
211
+ @subscription.cancel
212
+ @subscription.reload.state.should == 'canceled'
213
+ @subscription.reactivate
214
+ end
215
+
216
+ it "puts it in the active state" do
217
+ @subscription.reload.state.should == 'active'
218
+ end
219
+ end
220
+
221
+ describe "adding a one time charge" do
222
+ before(:each) do
223
+ @subscription = create_once(:subscription) do
224
+ Chargify::Subscription.create(
225
+ :product_handle => @@pro_plan.handle,
226
+ :customer_reference => @@johnadoe.reference,
227
+ :payment_profile_attributes => good_payment_profile_attributes
228
+ )
229
+ end
230
+ end
231
+ it "creates a charge and payment" do
232
+ lambda{
233
+ @subscription.charge(:amount => 7, :memo => 'One Time Charge')
234
+ }.should change{@subscription.reload.transactions.size}.by(2)
235
+ @subscription.transactions.first.amount_in_cents.should == 700
236
+ end
237
+ end
238
+
239
+ describe "adding a credit" do
240
+ before(:each) do
241
+ @subscription = create_once(:subscription) do
242
+ Chargify::Subscription.create(
243
+ :product_handle => @@pro_plan.handle,
244
+ :customer_reference => @@johnadoe.reference,
245
+ :payment_profile_attributes => good_payment_profile_attributes
246
+ )
247
+ end
248
+ end
249
+
250
+ it "creates a credit" do
251
+ lambda{
252
+ @subscription.credit(:amount => 7, :memo => 'credit')
253
+ }.should change{@subscription.reload.transactions.size}.by(1)
254
+ @subscription.transactions.first.amount_in_cents.should == -700
255
+ end
256
+ end
257
+
258
+ describe "adding a refund" do
259
+ before(:each) do
260
+ @subscription = create_once(:subscription) do
261
+ Chargify::Subscription.create(
262
+ :product_handle => @@pro_plan.handle,
263
+ :customer_reference => @@johnadoe.reference,
264
+ :payment_profile_attributes => good_payment_profile_attributes
265
+ )
266
+ end
267
+
268
+ @subscription.charge(:amount => 7, :memo => 'One Time Charge')
269
+ @subscription.reload
270
+ end
271
+
272
+ it "creates a refund" do
273
+ lambda{
274
+ @subscription.refund :payment_id => @subscription.transactions[0].id, :amount => 7,
275
+ :memo => 'Refunding One Time Charge'
276
+ }.should change{@subscription.reload.transactions.size}.by(1)
277
+ @subscription.transactions.first.amount_in_cents.should == 700
278
+ @subscription.transactions.first.transaction_type.should == 'refund'
279
+ end
280
+
281
+ context "via subscription payment (Chargify::Subscription::Transaction)" do
282
+ before :each do
283
+ @payment = @subscription.transactions.first
284
+ end
285
+
286
+ it "creates a refund" do
287
+ lambda{
288
+ @payment.refund :amount => 7, :memo => 'Refunding One Time Charge'
289
+ }.should change{@subscription.reload.transactions.size}.by(1)
290
+ @subscription.transactions.first.amount_in_cents.should == 700
291
+ @subscription.transactions.first.transaction_type.should == 'refund'
292
+ end
293
+
294
+ it "creates a full refund" do
295
+ lambda{
296
+ @payment.full_refund :memo => 'Refunding One Time Charge'
297
+ }.should change{@subscription.reload.transactions.size}.by(1)
298
+ @subscription.transactions.first.amount_in_cents.should == 700
299
+ @subscription.transactions.first.transaction_type.should == 'refund'
300
+ end
301
+ end
302
+
303
+ context "via site payment (Chargify::Transaction)" do
304
+ before :each do
305
+ @site_payment = Chargify::Transaction.find(:first)
306
+ end
307
+
308
+ it "creates a refund" do
309
+ lambda{
310
+ @site_payment.refund :amount => 7, :memo => 'Refunding One Time Charge'
311
+ }.should change{@subscription.reload.transactions.size}.by(1)
312
+ @subscription.transactions.first.amount_in_cents.should == 700
313
+ @subscription.transactions.first.transaction_type.should == 'refund'
314
+ end
315
+
316
+ it "creates a full refund" do
317
+ lambda{
318
+ @site_payment.full_refund :memo => 'Refunding One Time Charge'
319
+ }.should change{@subscription.reload.transactions.size}.by(1)
320
+ @subscription.transactions.first.amount_in_cents.should == 700
321
+ @subscription.transactions.first.transaction_type.should == 'refund'
322
+ end
323
+ end
324
+ end
325
+
326
+ def already_cleared_site_data?
327
+ @@already_cleared_site_data ||= nil
328
+ @@already_cleared_site_data == true
329
+ end
330
+
331
+ def cleared_site_data!
332
+ @@already_cleared_site_data = true
333
+ end
334
+
335
+ def clear_site_data
336
+ return if already_cleared_site_data?
337
+ begin
338
+ Chargify::Site.clear_data!
339
+ cleared_site_data!
340
+ rescue ActiveResource::ForbiddenAccess
341
+ raise StandardError.new("Remote specs may only be run against a site in test mode")
342
+ end
343
+ end
344
+
345
+ # Create Basic and Pro products in the Acme Projects family
346
+ def setup_plans
347
+ begin
348
+ @@acme_projects ||= Chargify::ProductFamily.find_by_handle('acme-projects')
349
+ rescue ActiveResource::ResourceNotFound
350
+ @@acme_projects = Chargify::ProductFamily.new(
351
+ :name => "Acme Projects"
352
+ )
353
+ result = @@acme_projects.save
354
+ result.should be_true
355
+ end
356
+
357
+ begin
358
+ @@basic_plan ||= Chargify::Product.find_by_handle('basic')
359
+ rescue ActiveResource::ResourceNotFound
360
+ @@basic_plan = Chargify::Product.new(
361
+ :product_family_id => @@acme_projects.id,
362
+ :name => "Basic Plan",
363
+ :handle => "basic",
364
+ :price_in_cents => 1000,
365
+ :interval => 1,
366
+ :interval_unit => 'month',
367
+ :trial_interval => 1,
368
+ :trial_interval_unit => 'month',
369
+ :trial_price_in_cents => 0
370
+ )
371
+ result = @@basic_plan.save
372
+ result.should be_true
373
+ end
374
+
375
+ begin
376
+ @@pro_plan ||= Chargify::Product.find_by_handle('pro')
377
+ rescue ActiveResource::ResourceNotFound
378
+ @@pro_plan = Chargify::Product.new(
379
+ :product_family_id => @@acme_projects.id,
380
+ :name => "Pro Plan",
381
+ :handle => "pro",
382
+ :price_in_cents => 5000,
383
+ :interval => 1,
384
+ :interval_unit => 'month'
385
+ )
386
+ result = @@pro_plan.save
387
+ result.should be_true
388
+ end
389
+ end
390
+
391
+ def setup_customer
392
+ # Create a customer
393
+ begin
394
+ @@johnadoe ||= Chargify::Customer.find_by_reference('a')
395
+ rescue ActiveResource::ResourceNotFound
396
+ @@johnadoe = Chargify::Customer.new(valid_customer_attributes)
397
+ result = @@johnadoe.save
398
+ result.should be_true
399
+
400
+ @@johnadoes_credit_card = Chargify::PaymentProfile.new(
401
+ good_payment_profile_attributes.merge(:customer_id => @@johnadoe.id)
402
+ )
403
+ result = @@johnadoes_credit_card.save
404
+ result.should be_true
405
+ end
406
+ end
407
+
408
+ def now
409
+ Time.now
410
+ end
411
+
412
+ def one_month_from_now
413
+ Time.now + 1.month
414
+ end
415
+
416
+ def ten_days_from_now
417
+ 10.days.from_now
418
+ end
419
+
420
+ # Gives a reasonable range for time comparisons
421
+ def approximately
422
+ @approximately ||= 5.minutes
423
+ end
424
+
425
+ def valid_customer_attributes
426
+ initial = next_customer_initial
427
+ {
428
+ :first_name => "John #{initial.upcase}",
429
+ :last_name => "Doe",
430
+ :email => "john.#{initial}.doe@example.com",
431
+ :reference => initial
432
+ }
433
+ end
434
+
435
+ def good_payment_profile_attributes
436
+ {
437
+ :full_number => '1',
438
+ :expiration_month => '12',
439
+ :expiration_year => Time.now.year + 1
440
+ }
441
+ end
442
+
443
+ def declined_payment_profile_attributes
444
+ {
445
+ :full_number => '2',
446
+ :expiration_month => '12',
447
+ :expiration_year => Time.now.year + 1
448
+ }
449
+ end
450
+
451
+ def unstorable_payment_profile_attributes
452
+ {
453
+ :full_number => '3',
454
+ :expiration_month => '12',
455
+ :expiration_year => Time.now.year + 1
456
+ }
457
+ end
458
+
459
+ def expired_payment_profile_attributes
460
+ {
461
+ :full_number => '1',
462
+ :expiration_month => '12',
463
+ :expiration_year => Time.now.year - 1
464
+ }
465
+ end
466
+
467
+ def pretokenized_card_attributes
468
+ {
469
+ :vault_token => '1',
470
+ :current_vault => 'bogus',
471
+ :expiration_month => '12',
472
+ :expiration_year => Time.now.year + 1,
473
+ :last_four => '1234',
474
+ :card_type => 'visa'
475
+ }
476
+ end
477
+
478
+ # Don't create more than 26 customers until we add more initials :)
479
+ def next_customer_initial
480
+ @@customer_initial_index ||= 0
481
+ initial = customer_initials[@@customer_initial_index]
482
+ @@customer_initial_index += 1
483
+ initial
484
+ end
485
+
486
+ # An array of intials
487
+ def customer_initials
488
+ @customer_initials ||= ('a'..'z').to_a
489
+ end
490
+
491
+ # Allows us to create remote resources once per spec hierarchy
492
+ def create_once(type, &block)
493
+ hierarchy = example_group_hierarchy.collect(&:object_id).to_s
494
+
495
+ unless resource(type, hierarchy)
496
+ register_resource(type, hierarchy, block.call)
497
+ end
498
+ resource(type, hierarchy)
499
+ end
500
+
501
+ def resource(type, hierarchy)
502
+ @@resources ||= {}
503
+ @@resources[type] ||= {}
504
+ @@resources[type][hierarchy]
505
+ end
506
+
507
+ def register_resource(type, hierarchy, resource)
508
+ @@resources ||= {}
509
+ @@resources[type] ||= {}
510
+ @@resources[type][hierarchy] = resource
511
+ end
512
+
513
+ end
514
+ end