fake_chargify 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.
- data/Gemfile +10 -0
- data/README.md +20 -0
- data/Rakefile +150 -0
- data/fake_chargify.gemspec +68 -0
- data/lib/fake_chargify.rb +45 -0
- data/lib/fake_chargify/configuration.rb +5 -0
- data/lib/fake_chargify/credit_card.rb +26 -0
- data/lib/fake_chargify/customer.rb +40 -0
- data/lib/fake_chargify/customer_registry.rb +65 -0
- data/lib/fake_chargify/product.rb +21 -0
- data/lib/fake_chargify/product_family.rb +18 -0
- data/lib/fake_chargify/statement.rb +51 -0
- data/lib/fake_chargify/statement_registry.rb +32 -0
- data/lib/fake_chargify/string_patches.rb +5 -0
- data/lib/fake_chargify/subscription.rb +64 -0
- data/lib/fake_chargify/subscription_registry.rb +77 -0
- data/lib/fake_chargify/url_parser.rb +11 -0
- data/readme.md +20 -0
- data/spec/fake_chargify/configuration_spec.rb +14 -0
- data/spec/fake_chargify/credit_card_spec.rb +21 -0
- data/spec/fake_chargify/customer_spec.rb +99 -0
- data/spec/fake_chargify/product_family_spec.rb +21 -0
- data/spec/fake_chargify/product_spec.rb +34 -0
- data/spec/fake_chargify/statement_spec.rb +79 -0
- data/spec/fake_chargify/subscription_spec.rb +195 -0
- data/spec/fake_chargify_spec.rb +27 -0
- data/spec/spec_helper.rb +18 -0
- data/spec/string_patches_spec.rb +21 -0
- metadata +116 -0
data/Gemfile
ADDED
data/README.md
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
fake_chargify
|
|
2
|
+
==============
|
|
3
|
+
fake_chargify is a helper for faking web requests and responses to and from the Chargify API. You can test Chargify within your application on a plane now. I am sure that happens all the time.
|
|
4
|
+
|
|
5
|
+
# Installation
|
|
6
|
+
|
|
7
|
+
gem 'fake_chargify'
|
|
8
|
+
require 'fake_chargify'
|
|
9
|
+
|
|
10
|
+
# The basics
|
|
11
|
+
|
|
12
|
+
Example, in spec_helper.rb
|
|
13
|
+
|
|
14
|
+
FakeChargify.activate!
|
|
15
|
+
RSpec.configure do |c|
|
|
16
|
+
c.before do
|
|
17
|
+
FakeChargify.clear!
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
data/Rakefile
ADDED
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
require 'rubygems'
|
|
2
|
+
require 'rake'
|
|
3
|
+
require 'date'
|
|
4
|
+
|
|
5
|
+
#############################################################################
|
|
6
|
+
#
|
|
7
|
+
# Helper functions
|
|
8
|
+
#
|
|
9
|
+
#############################################################################
|
|
10
|
+
|
|
11
|
+
def name
|
|
12
|
+
@name ||= Dir['*.gemspec'].first.split('.').first
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def version
|
|
16
|
+
line = File.read("lib/#{name}.rb")[/^\s*VERSION\s*=\s*.*/]
|
|
17
|
+
line.match(/.*VERSION\s*=\s*['"](.*)['"]/)[1]
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def date
|
|
21
|
+
Date.today.to_s
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def rubyforge_project
|
|
25
|
+
name
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def gemspec_file
|
|
29
|
+
"#{name}.gemspec"
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def gem_file
|
|
33
|
+
"#{name}-#{version}.gem"
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def replace_header(head, header_name)
|
|
37
|
+
head.sub!(/(\.#{header_name}\s*= ').*'/) { "#{$1}#{send(header_name)}'"}
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
#############################################################################
|
|
41
|
+
#
|
|
42
|
+
# Standard tasks
|
|
43
|
+
#
|
|
44
|
+
#############################################################################
|
|
45
|
+
|
|
46
|
+
task :default => :test
|
|
47
|
+
|
|
48
|
+
require 'rake/testtask'
|
|
49
|
+
Rake::TestTask.new(:test) do |test|
|
|
50
|
+
test.libs << 'lib' << 'test'
|
|
51
|
+
test.pattern = 'test/**/test_*.rb'
|
|
52
|
+
test.verbose = true
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
desc "Generate RCov test coverage and open in your browser"
|
|
56
|
+
task :coverage do
|
|
57
|
+
require 'rcov'
|
|
58
|
+
sh "rm -fr coverage"
|
|
59
|
+
sh "rcov test/test_*.rb"
|
|
60
|
+
sh "open coverage/index.html"
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
require 'rake/rdoctask'
|
|
64
|
+
Rake::RDocTask.new do |rdoc|
|
|
65
|
+
rdoc.rdoc_dir = 'rdoc'
|
|
66
|
+
rdoc.title = "#{name} #{version}"
|
|
67
|
+
rdoc.rdoc_files.include('README*')
|
|
68
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
desc "Open an irb session preloaded with this library"
|
|
72
|
+
task :console do
|
|
73
|
+
sh "irb -rubygems -r ./lib/#{name}.rb"
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
#############################################################################
|
|
77
|
+
#
|
|
78
|
+
# Custom tasks (add your own tasks here)
|
|
79
|
+
#
|
|
80
|
+
#############################################################################
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
#############################################################################
|
|
85
|
+
#
|
|
86
|
+
# Packaging tasks
|
|
87
|
+
#
|
|
88
|
+
#############################################################################
|
|
89
|
+
|
|
90
|
+
desc "Create tag v#{version} and build and push #{gem_file} to Rubygems"
|
|
91
|
+
task :release => :build do
|
|
92
|
+
unless `git branch` =~ /^\* master$/
|
|
93
|
+
puts "You must be on the master branch to release!"
|
|
94
|
+
exit!
|
|
95
|
+
end
|
|
96
|
+
sh "git commit --allow-empty -a -m 'Release #{version}'"
|
|
97
|
+
sh "git tag v#{version}"
|
|
98
|
+
sh "git push origin master"
|
|
99
|
+
sh "git push origin v#{version}"
|
|
100
|
+
sh "gem push pkg/#{name}-#{version}.gem"
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
desc "Build #{gem_file} into the pkg directory"
|
|
104
|
+
task :build => :gemspec do
|
|
105
|
+
sh "mkdir -p pkg"
|
|
106
|
+
sh "gem build #{gemspec_file}"
|
|
107
|
+
sh "mv #{gem_file} pkg"
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
desc "Generate #{gemspec_file}"
|
|
111
|
+
task :gemspec => :validate do
|
|
112
|
+
# read spec file and split out manifest section
|
|
113
|
+
spec = File.read(gemspec_file)
|
|
114
|
+
head, manifest, tail = spec.split(" # = MANIFEST =\n")
|
|
115
|
+
|
|
116
|
+
# replace name version and date
|
|
117
|
+
replace_header(head, :name)
|
|
118
|
+
replace_header(head, :version)
|
|
119
|
+
replace_header(head, :date)
|
|
120
|
+
#comment this out if your rubyforge_project has a different name
|
|
121
|
+
replace_header(head, :rubyforge_project)
|
|
122
|
+
|
|
123
|
+
# determine file list from git ls-files
|
|
124
|
+
files = `git ls-files`.
|
|
125
|
+
split("\n").
|
|
126
|
+
sort.
|
|
127
|
+
reject { |file| file =~ /^\./ }.
|
|
128
|
+
reject { |file| file =~ /^(rdoc|pkg)/ }.
|
|
129
|
+
map { |file| " #{file}" }.
|
|
130
|
+
join("\n")
|
|
131
|
+
|
|
132
|
+
# piece file back together and write
|
|
133
|
+
manifest = " s.files = %w[\n#{files}\n ]\n"
|
|
134
|
+
spec = [head, manifest, tail].join(" # = MANIFEST =\n")
|
|
135
|
+
File.open(gemspec_file, 'w') { |io| io.write(spec) }
|
|
136
|
+
puts "Updated #{gemspec_file}"
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
desc "Validate #{gemspec_file}"
|
|
140
|
+
task :validate do
|
|
141
|
+
libfiles = Dir['lib/*'] - ["lib/#{name}.rb", "lib/#{name}"]
|
|
142
|
+
unless libfiles.empty?
|
|
143
|
+
puts "Directory `lib` should only contain a `#{name}.rb` file and `#{name}` dir."
|
|
144
|
+
exit!
|
|
145
|
+
end
|
|
146
|
+
unless Dir['VERSION*'].empty?
|
|
147
|
+
puts "A `VERSION` file at root level violates Gem best practices."
|
|
148
|
+
exit!
|
|
149
|
+
end
|
|
150
|
+
end
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
|
|
2
|
+
Gem::Specification.new do |s|
|
|
3
|
+
s.specification_version = 2 if s.respond_to? :specification_version=
|
|
4
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
|
5
|
+
s.rubygems_version = '1.3.5'
|
|
6
|
+
|
|
7
|
+
s.name = 'fake_chargify'
|
|
8
|
+
s.version = '0.1.0'
|
|
9
|
+
s.date = '2011-11-29'
|
|
10
|
+
s.rubyforge_project = 'fake_chargify'
|
|
11
|
+
|
|
12
|
+
s.summary = "A helper for faking web requests and responses to and from the Chargify API."
|
|
13
|
+
s.description = "A helper for faking web requests and responses to and from the Chargify API."
|
|
14
|
+
|
|
15
|
+
## List the primary authors. If there are a bunch of authors, it's probably
|
|
16
|
+
## better to set the email to an email list or something. If you don't have
|
|
17
|
+
## a custom homepage, consider using your GitHub URL or the like.
|
|
18
|
+
s.authors = ["Jamie Wright"]
|
|
19
|
+
s.email = 'jamie@brilliantfantastic.com'
|
|
20
|
+
s.homepage = 'http://github.com/brilliantfantastic/fake_chargify'
|
|
21
|
+
|
|
22
|
+
s.require_paths = %w[lib]
|
|
23
|
+
|
|
24
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
|
25
|
+
s.extra_rdoc_files = %w[README.md]
|
|
26
|
+
|
|
27
|
+
## List your runtime dependencies here. Runtime dependencies are those
|
|
28
|
+
## that are needed for an end user to actually USE your code.
|
|
29
|
+
s.add_dependency('webmock', "~> 1.7.8")
|
|
30
|
+
s.add_dependency('nokogiri', "~> 1.5.0")
|
|
31
|
+
|
|
32
|
+
#s.add_development_dependency('DEVDEPNAME', [">= 1.1.0", "< 2.0.0"])
|
|
33
|
+
|
|
34
|
+
## Leave this section as-is. It will be automatically generated from the
|
|
35
|
+
## contents of your Git repository via the gemspec task. DO NOT REMOVE
|
|
36
|
+
## THE MANIFEST COMMENTS, they are used as delimiters by the task.
|
|
37
|
+
# = MANIFEST =
|
|
38
|
+
s.files = %w[
|
|
39
|
+
Gemfile
|
|
40
|
+
Rakefile
|
|
41
|
+
fake_chargify.gemspec
|
|
42
|
+
lib/fake_chargify.rb
|
|
43
|
+
lib/fake_chargify/configuration.rb
|
|
44
|
+
lib/fake_chargify/credit_card.rb
|
|
45
|
+
lib/fake_chargify/customer.rb
|
|
46
|
+
lib/fake_chargify/customer_registry.rb
|
|
47
|
+
lib/fake_chargify/product.rb
|
|
48
|
+
lib/fake_chargify/product_family.rb
|
|
49
|
+
lib/fake_chargify/statement.rb
|
|
50
|
+
lib/fake_chargify/statement_registry.rb
|
|
51
|
+
lib/fake_chargify/string_patches.rb
|
|
52
|
+
lib/fake_chargify/subscription.rb
|
|
53
|
+
lib/fake_chargify/subscription_registry.rb
|
|
54
|
+
lib/fake_chargify/url_parser.rb
|
|
55
|
+
readme.md
|
|
56
|
+
spec/fake_chargify/configuration_spec.rb
|
|
57
|
+
spec/fake_chargify/credit_card_spec.rb
|
|
58
|
+
spec/fake_chargify/customer_spec.rb
|
|
59
|
+
spec/fake_chargify/product_family_spec.rb
|
|
60
|
+
spec/fake_chargify/product_spec.rb
|
|
61
|
+
spec/fake_chargify/statement_spec.rb
|
|
62
|
+
spec/fake_chargify/subscription_spec.rb
|
|
63
|
+
spec/fake_chargify_spec.rb
|
|
64
|
+
spec/spec_helper.rb
|
|
65
|
+
spec/string_patches_spec.rb
|
|
66
|
+
]
|
|
67
|
+
# = MANIFEST =
|
|
68
|
+
end
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
require 'webmock'
|
|
2
|
+
require 'fake_chargify/string_patches'
|
|
3
|
+
require 'fake_chargify/customer_registry'
|
|
4
|
+
require 'fake_chargify/subscription_registry'
|
|
5
|
+
require 'fake_chargify/statement_registry'
|
|
6
|
+
require 'fake_chargify/configuration'
|
|
7
|
+
|
|
8
|
+
module FakeChargify
|
|
9
|
+
VERSION = '0.1.0'
|
|
10
|
+
|
|
11
|
+
class << self
|
|
12
|
+
attr_accessor :customers, :subscriptions, :statements
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def self.clear!
|
|
16
|
+
self.customers = CustomerRegistry.new
|
|
17
|
+
self.subscriptions = SubscriptionRegistry.new
|
|
18
|
+
self.statements = StatementRegistry.new
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def self.activate!
|
|
22
|
+
self.activate = true
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def self.activate=(activate)
|
|
26
|
+
if activate
|
|
27
|
+
WebMock.disable_net_connect!(:allow_localhost => true)
|
|
28
|
+
self.clear!
|
|
29
|
+
|
|
30
|
+
self.customers.stub_requests!
|
|
31
|
+
self.subscriptions.stub_requests!
|
|
32
|
+
self.statements.stub_requests!
|
|
33
|
+
else
|
|
34
|
+
WebMock.allow_net_connect!
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def self.configuration
|
|
39
|
+
@configuration ||= FakeChargify::Configuration.new
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def self.configure
|
|
43
|
+
yield configuration if block_given?
|
|
44
|
+
end
|
|
45
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
require 'nokogiri'
|
|
2
|
+
|
|
3
|
+
module FakeChargify
|
|
4
|
+
class CreditCard
|
|
5
|
+
attr_accessor :expiration_month, :expiration_year
|
|
6
|
+
|
|
7
|
+
def full_number=(value)
|
|
8
|
+
@full_number = value
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def masked_card_number
|
|
12
|
+
"XXXX-XXXX-XXXX-#{@full_number.to_s.last(4)}"
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def to_xml
|
|
16
|
+
builder = Nokogiri::XML::Builder.new do |xml|
|
|
17
|
+
xml.credit_card {
|
|
18
|
+
xml.masked_card_number masked_card_number
|
|
19
|
+
xml.expiration_month expiration_month
|
|
20
|
+
xml.expiration_year expiration_year
|
|
21
|
+
}
|
|
22
|
+
end
|
|
23
|
+
builder.to_xml
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
require 'nokogiri'
|
|
2
|
+
|
|
3
|
+
module FakeChargify
|
|
4
|
+
class Customer
|
|
5
|
+
attr_accessor :id, :first_name, :last_name, :email, :organization, :reference, :created_at, :updated_at
|
|
6
|
+
|
|
7
|
+
def to_xml
|
|
8
|
+
builder = Nokogiri::XML::Builder.new do |xml|
|
|
9
|
+
xml.customer {
|
|
10
|
+
xml.id_ id
|
|
11
|
+
xml.first_name first_name
|
|
12
|
+
xml.last_name last_name
|
|
13
|
+
xml.email email
|
|
14
|
+
xml.organization organization
|
|
15
|
+
xml.reference reference
|
|
16
|
+
xml.created_at created_at
|
|
17
|
+
xml.updated_at updated_at
|
|
18
|
+
}
|
|
19
|
+
end
|
|
20
|
+
builder.to_xml
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def self.from_xml(xml)
|
|
24
|
+
customer = Customer.new
|
|
25
|
+
doc = Nokogiri::XML.parse(xml)
|
|
26
|
+
doc.xpath('//customer').map do |e|
|
|
27
|
+
customer.id = e.xpath('id').text.to_i
|
|
28
|
+
customer.first_name = e.xpath('first_name').text
|
|
29
|
+
customer.last_name = e.xpath('last_name').text
|
|
30
|
+
customer.email = e.xpath('email').text
|
|
31
|
+
customer.organization = e.xpath('organization').text
|
|
32
|
+
customer.reference = e.xpath('reference').text
|
|
33
|
+
customer.created_at = Time.parse(e.xpath('created_at').text)
|
|
34
|
+
customer.updated_at = Time.parse(e.xpath('updated_at').text)
|
|
35
|
+
end
|
|
36
|
+
customer
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
end
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
require 'fake_chargify/customer'
|
|
2
|
+
require 'fake_chargify/url_parser'
|
|
3
|
+
|
|
4
|
+
module FakeChargify
|
|
5
|
+
class CustomerRegistry
|
|
6
|
+
include UrlParser
|
|
7
|
+
|
|
8
|
+
def repository
|
|
9
|
+
@customers ||= []
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def stub_requests!
|
|
13
|
+
stub_create!
|
|
14
|
+
stub_update!
|
|
15
|
+
stub_show!
|
|
16
|
+
stub_lookup!
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
private
|
|
20
|
+
|
|
21
|
+
def stub_create!
|
|
22
|
+
WebMock::API.stub_request(:post, "https://#{FakeChargify.configuration.api_key}:X@#{FakeChargify.configuration.subdomain}.chargify.com/customers.xml").
|
|
23
|
+
to_return(:status => 201, :body => lambda { |request|
|
|
24
|
+
customer = Customer.from_xml(request.body)
|
|
25
|
+
repository << customer
|
|
26
|
+
customer.to_xml
|
|
27
|
+
})
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def stub_update!
|
|
31
|
+
WebMock::API.stub_request(:put, /https:\/\/#{FakeChargify.configuration.api_key}:X@#{FakeChargify.configuration.subdomain}.chargify.com\/customers\/#{/\d/}.xml/).
|
|
32
|
+
to_return(:status => 200, :body => lambda { |request|
|
|
33
|
+
id = get_id_from_uri request.uri
|
|
34
|
+
customer = Customer.from_xml(request.body)
|
|
35
|
+
repository.map! do |c|
|
|
36
|
+
if c.id == id
|
|
37
|
+
customer
|
|
38
|
+
else
|
|
39
|
+
c
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
customer.to_xml
|
|
43
|
+
})
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def stub_show!
|
|
47
|
+
WebMock::API.stub_request(:get, /https:\/\/#{FakeChargify.configuration.api_key}:X@#{FakeChargify.configuration.subdomain}.chargify.com\/customers\/#{/\d/}.xml/).
|
|
48
|
+
to_return(:status => 200, :body => lambda { |request|
|
|
49
|
+
id = get_id_from_uri request.uri
|
|
50
|
+
customers = repository.select { |customer| customer.id == id }
|
|
51
|
+
customers.first.to_xml
|
|
52
|
+
})
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def stub_lookup!
|
|
56
|
+
WebMock::API.stub_request(:get, /https:\/\/#{FakeChargify.configuration.api_key}:X@#{FakeChargify.configuration.subdomain}.chargify.com\/customers\/lookup.xml\?reference=#{/\w/}/).
|
|
57
|
+
to_return(:status => 200, :body => lambda { |request|
|
|
58
|
+
reference = request.uri.query_values['reference']
|
|
59
|
+
customers = repository.select { |customer| customer.reference == reference }
|
|
60
|
+
customers.first.to_xml
|
|
61
|
+
})
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
end
|
|
65
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
require 'fake_chargify/product_family'
|
|
2
|
+
|
|
3
|
+
module FakeChargify
|
|
4
|
+
class Product
|
|
5
|
+
attr_accessor :accounting_code, :handle, :interval, :name, :price_in_cents, :family
|
|
6
|
+
|
|
7
|
+
def to_xml
|
|
8
|
+
builder = Nokogiri::XML::Builder.new do |xml|
|
|
9
|
+
xml.product {
|
|
10
|
+
xml.accounting_code accounting_code
|
|
11
|
+
xml.handle handle
|
|
12
|
+
xml.interval interval
|
|
13
|
+
xml.name name
|
|
14
|
+
xml.price_in_cents price_in_cents
|
|
15
|
+
xml << Nokogiri.XML(family.to_xml).root.to_xml unless family.nil?
|
|
16
|
+
}
|
|
17
|
+
end
|
|
18
|
+
builder.to_xml
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|