vault-invoice-builder-client 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,6 @@
1
+ .bundle/
2
+ .rvmrc
3
+ .yardoc/
4
+ doc/
5
+ vendor/
6
+ test/.test*
@@ -0,0 +1 @@
1
+ -m markdown
data/Gemfile ADDED
@@ -0,0 +1,12 @@
1
+ source :rubygems
2
+
3
+ gemspec
4
+
5
+ group :development do
6
+ gem 'rake'
7
+ end
8
+
9
+ group :test do
10
+ gem 'rr'
11
+ gem 'vault-test-tools', '~> 0.2.2', :git => 'https://github.com/heroku/vault-test-tools.git'
12
+ end
@@ -0,0 +1,56 @@
1
+ GIT
2
+ remote: https://github.com/heroku/vault-test-tools.git
3
+ revision: 5eabd67610f279b81cadb803cee8ef704093a05d
4
+ specs:
5
+ vault-test-tools (0.2.2)
6
+ minitest
7
+ nokogiri
8
+ rack-perftools_profiler
9
+ rack-test
10
+ rdoc
11
+ redcarpet
12
+ turn
13
+ yard
14
+
15
+ PATH
16
+ remote: .
17
+ specs:
18
+ vault-invoice-builder-client (0.0.2)
19
+ excon
20
+ yajl-ruby
21
+
22
+ GEM
23
+ remote: http://rubygems.org/
24
+ specs:
25
+ ansi (1.4.3)
26
+ excon (0.16.10)
27
+ json (1.7.7)
28
+ minitest (4.6.0)
29
+ nokogiri (1.5.6)
30
+ open4 (1.3.0)
31
+ perftools.rb (2.0.0)
32
+ rack (1.5.2)
33
+ rack-perftools_profiler (0.6.0)
34
+ open4 (~> 1.0)
35
+ perftools.rb (~> 2.0.0)
36
+ rack (~> 1.0)
37
+ rack-test (0.6.2)
38
+ rack (>= 1.0)
39
+ rake (10.0.3)
40
+ rdoc (3.12.1)
41
+ json (~> 1.4)
42
+ redcarpet (2.2.2)
43
+ rr (1.0.4)
44
+ turn (0.9.6)
45
+ ansi
46
+ yajl-ruby (1.1.0)
47
+ yard (0.8.4.1)
48
+
49
+ PLATFORMS
50
+ ruby
51
+
52
+ DEPENDENCIES
53
+ rake
54
+ rr
55
+ vault-invoice-builder-client!
56
+ vault-test-tools (~> 0.2.2)!
@@ -0,0 +1,67 @@
1
+ # Vault::InvoiceBuilder::Client
2
+
3
+ A Ruby client for the `Vault::InvoiceBuilder` HTTP API.
4
+
5
+ ## Setting up a development environment
6
+
7
+ Install dependencies and run the test suite:
8
+
9
+ bundle install --binstubs vendor/bin
10
+ rbenv rehash
11
+ rake
12
+
13
+ Run tests:
14
+
15
+ rake test
16
+
17
+ See tasks:
18
+
19
+ rake -T
20
+
21
+ Generate API documentation:
22
+
23
+ rake yard
24
+
25
+ ## Using the client
26
+
27
+ The `Vault::InvoiceBuilder` API may only be accessed anonymously:
28
+
29
+ ```ruby
30
+ require 'vault-invoice-builder-client'
31
+
32
+ client = Vault::InvoiceBuilder::Client.new(
33
+ 'https://vault-invoice-builder.herokuapp.com')
34
+ ```
35
+
36
+ For endpoints that require authentication, HTTP Basic credentials must
37
+ be supplied in the URL:
38
+
39
+ ```ruby
40
+ client = Vault::InvoiceBuilder::Client.new(
41
+ 'https://username:password@vault-invoice-builder.herokuapp.com')
42
+ ```
43
+
44
+ ### Rendering an invoice.
45
+
46
+ An invoice contains customer contact and tax details, a list of apps
47
+ and the charges they've incurred by consuming dyno hours and using
48
+ addons, a list of charges for products the customer used directly,
49
+ such as a support contract, and credits that have been applied to
50
+ cover some or all of the charges on the invoice. An invoice is
51
+ rendered from a receipt, a JSON representation of app and user charges
52
+ and credits.
53
+
54
+ ```ruby
55
+ receipt = {user: 'user123@heroku.com', start_time: …, …}
56
+ html_content = client.render_html(receipt)
57
+ ```
58
+
59
+ ### Storing an invoice
60
+ The `store` method can be used to render an invoice and then store it
61
+ to S3. The same receipt JSON object is passed and an empty 200 OK
62
+ response is returned if the request was successful.
63
+
64
+ ```ruby
65
+ receipt = {user: 'user123@heroku.com', start_time: …, …}
66
+ response = client.store(receipt)
67
+ ```
@@ -0,0 +1,11 @@
1
+ require "bundler/gem_tasks"
2
+ require 'yard'
3
+
4
+ desc "Test the things"
5
+ require 'vault-test-tools/rake_task'
6
+
7
+ desc "Doc the things"
8
+ YARD::Rake::YardocTask.new
9
+
10
+ desc "Run the test suite"
11
+ task :default => [:test]
@@ -0,0 +1,17 @@
1
+ require 'bundler'
2
+ Bundler.require :default, ENV['RACK_ENV'].to_sym
3
+
4
+ require 'excon'
5
+ require 'yajl/json_gem'
6
+
7
+ module Vault
8
+ module InvoiceBuilder
9
+ # Client provides a Ruby API to access the `Vault::InvoiceBuilder` HTTP
10
+ # API.
11
+ class Client
12
+ end
13
+ end
14
+ end
15
+
16
+ require 'vault-invoice-builder-client/client'
17
+ require 'vault-invoice-builder-client/version'
@@ -0,0 +1,67 @@
1
+ module Vault::InvoiceBuilder
2
+ # Client for the `Vault::InvoiceBuilder` HTTP API.
3
+ class Client
4
+ # The `Vault::InvoiceBuilder` HTTP API URL.
5
+ attr_reader :url
6
+
7
+ # Instantiate a client.
8
+ #
9
+ # @param url [String] The URL to connect to. Include the username and
10
+ # password to use when connecting. Defaults to the URL defined in the
11
+ # `VAULT_INVOICE_BUILDER_URL` environment variable if one isn't
12
+ # explicitly provided.
13
+ def initialize(url = nil)
14
+ @url = url || ENV['VAULT_INVOICE_BUILDER_URL']
15
+ end
16
+
17
+ # Render a statement into an HTML invoice.
18
+ #
19
+ # @param statement [Hash] An object matching the statement format described in
20
+ # the `Vault::InvoiceBuilder` README.
21
+ # @raise [Excon::Errors::HTTPStatusError] Raised if the server returns an
22
+ # unsuccessful HTTP status code.
23
+ # @return [String] The rendered HTML invoice.
24
+ def render_html(statement)
25
+ connection = Excon.new(@url)
26
+ response = connection.post(
27
+ path: "/invoice.html",
28
+ headers: {'Content-Type' => 'application/json'},
29
+ body: JSON.generate(statement),
30
+ expects: [200])
31
+ response.body
32
+ end
33
+
34
+ # POST a statement to to the proxy-able /statement/:id endpoint
35
+ #
36
+ # @param statement [Hash] An object matching the statement format described in
37
+ # the `Vault::InvoiceBuilder` README.
38
+ # @raise [Excon::Errors::HTTPStatusError] Raised if the server returns an
39
+ # unsuccessful HTTP status code.
40
+ # @return [Excon::Response] The response object.
41
+ def post(statement)
42
+ connection = Excon.new(@url)
43
+ id = statement[:id] || statement['id']
44
+ response = connection.post(
45
+ path: "/statement/#{id}",
46
+ headers: {'Content-Type' => 'application/json'},
47
+ body: JSON.generate(statement),
48
+ expects: [200])
49
+ end
50
+
51
+ # @deprecated
52
+ #
53
+ # @param statement [Hash] An object matching the statement format described in
54
+ # the `Vault::InvoiceBuilder` README.
55
+ # @raise [Excon::Errors::HTTPStatusError] Raised if the server returns an
56
+ # unsuccessful HTTP status code.
57
+ # @return [Excon::Response] The response object.
58
+ def store(statement)
59
+ connection = Excon.new(@url)
60
+ response = connection.post(
61
+ path: '/store',
62
+ headers: {'Content-Type' => 'application/json'},
63
+ body: JSON.generate(statement),
64
+ expects: [200])
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,8 @@
1
+ module Vault
2
+ module InvoiceBuilder
3
+ class Client
4
+ # The `Vault::InvoiceBuilder::Client` gem version.
5
+ VERSION = '0.0.2'
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,132 @@
1
+ require 'helper'
2
+
3
+ class ClientTest < Vault::TestCase
4
+ include Vault::Test::EnvironmentHelpers
5
+
6
+ def setup
7
+ super
8
+ Excon.stubs.clear
9
+ Excon.defaults[:mock] = true
10
+ @client = Vault::InvoiceBuilder::Client.new(
11
+ 'https://vault-invoice-builder.herokuapp.com')
12
+ @statement = {user: 'user123@heroku.com',
13
+ start_time: Time.utc(2012, 1),
14
+ stop_time: Time.utc(2012, 2)}
15
+ end
16
+
17
+ def teardown
18
+ # FIXME This is a bit ugly, but Excon doesn't provide a builtin way to
19
+ # ensure that a request was invoked, so we have to do it ourselves.
20
+ # Without this, and the Excon.stubs.pop calls in the tests below, tests
21
+ # will pass if request logic is completely removed from application
22
+ # code. -jkakar
23
+ assert(Excon.stubs.empty?, 'Expected HTTP requests were not made.')
24
+ super
25
+ end
26
+
27
+ # Client.new looks for VAULT_INVOICE_BUILDER_URL if none is passed to the
28
+ # constructor.
29
+ def test_uses_url_from_environment_by_default
30
+ url = 'http://example.com'
31
+ set_env 'VAULT_INVOICE_BUILDER_URL', url
32
+ @client = Vault::InvoiceBuilder::Client.new
33
+ assert_equal(url, @client.url)
34
+ end
35
+
36
+ # Client.render_html makes a PUT request to the Vault::InvoiceBuilder HTTP
37
+ # API, passing the supplied credentials using HTTP basic auth, to report
38
+ # that usage of a product began at a particular time.
39
+ def test_render_html
40
+ content = '<html><body><p>Hello, world!</p></body></html>'
41
+ Excon.stub(method: :post) do |request|
42
+ assert_equal('vault-invoice-builder.herokuapp.com:443',
43
+ request[:host_port])
44
+ assert_equal("/invoice.html", request[:path])
45
+ Excon.stubs.pop
46
+ {status: 200, body: content}
47
+ end
48
+ assert_equal(content, @client.render_html(@statement))
49
+ end
50
+
51
+ # Client.render_html raises the appropriate Excon::Errors::HTTPStatusError
52
+ # if an unsuccessful HTTP status code is returned by the server.
53
+ def test_render_html_with_unsuccessful_response
54
+ Excon.stub(method: :post) do |request|
55
+ Excon.stubs.pop
56
+ {status: 400, body: 'Bad inputs provided.'}
57
+ end
58
+ assert_raises Excon::Errors::BadRequest do
59
+ @client.render_html(@statement)
60
+ end
61
+ end
62
+
63
+ # Client.store makes a POST request to the Vault::InvoiceBuilder HTTP API,
64
+ # passing the supplied credentials using HTTP Basic Auth, to which triggers
65
+ # Vault::InvoiceBuilder to generate the invoice and store it to S3.
66
+ def test_store
67
+ Excon.stub(method: :post) do |request|
68
+ assert_equal('vault-invoice-builder.herokuapp.com:443',
69
+ request[:host_port])
70
+ assert_equal('/store', request[:path])
71
+ assert_equal('application/json', request[:headers]['Content-Type'])
72
+ Excon.stubs.pop
73
+ {status: 200}
74
+ end
75
+ response = @client.store(@statement)
76
+ assert_equal(200, response.status)
77
+ end
78
+
79
+ # Client.store raises the appropriate Excon::Errors::HTTPStatusError if an
80
+ # unsuccessful HTTP status code is returned by the server.
81
+ def test_store_with_unsuccessful_response
82
+ Excon.stub(method: :post) do |request|
83
+ Excon.stubs.pop
84
+ {status: 400, body: 'Bad inputs provided.'}
85
+ end
86
+ assert_raises Excon::Errors::BadRequest do
87
+ @client.store(@statement)
88
+ end
89
+ end
90
+
91
+ # Client.post makes a POST request to the canonical statement drain API
92
+ def test_post_with_symbol_id_key
93
+ @statement[:id] = 1
94
+ Excon.stub(method: :post) do |request|
95
+ assert_equal('vault-invoice-builder.herokuapp.com:443',
96
+ request[:host_port])
97
+ assert_equal('/statement/1', request[:path])
98
+ assert_equal('application/json', request[:headers]['Content-Type'])
99
+ Excon.stubs.pop
100
+ {status: 200}
101
+ end
102
+ response = @client.post(@statement)
103
+ assert_equal(200, response.status)
104
+ end
105
+
106
+ # Client.post makes a POST request to the canonical statement drain API
107
+ def test_post_with_string_id_key
108
+ @statement['id'] = 1
109
+ Excon.stub(method: :post) do |request|
110
+ assert_equal('vault-invoice-builder.herokuapp.com:443',
111
+ request[:host_port])
112
+ assert_equal('/statement/1', request[:path])
113
+ assert_equal('application/json', request[:headers]['Content-Type'])
114
+ Excon.stubs.pop
115
+ {status: 200}
116
+ end
117
+ response = @client.post(@statement)
118
+ assert_equal(200, response.status)
119
+ end
120
+
121
+ # Client.store raises the appropriate Excon::Errors::HTTPStatusError if an
122
+ # unsuccessful HTTP status code is returned by the server.
123
+ def test_post_with_unsuccessful_response
124
+ Excon.stub(method: :post) do |request|
125
+ Excon.stubs.pop
126
+ {status: 400, body: 'Bad inputs provided.'}
127
+ end
128
+ assert_raises Excon::Errors::BadRequest do
129
+ @client.post(@statement)
130
+ end
131
+ end
132
+ end
@@ -0,0 +1,4 @@
1
+ ENV['RACK_ENV'] = 'test'
2
+
3
+ require 'vault-invoice-builder-client'
4
+ require 'vault-test-tools'
@@ -0,0 +1,9 @@
1
+ require 'helper'
2
+
3
+ class VersionTest < Vault::TestCase
4
+ # Vault::InvoiceBuilder::Client::VERSION is a string matching the
5
+ # `major.minor.patch` format.
6
+ def test_version
7
+ assert_match(/\d+\.\d+\.\d+/, Vault::InvoiceBuilder::Client::VERSION)
8
+ end
9
+ end
@@ -0,0 +1,21 @@
1
+ lib = File.expand_path('../lib', __FILE__)
2
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+ require 'vault-invoice-builder-client/version'
4
+
5
+ Gem::Specification.new do |gem|
6
+ gem.name = "vault-invoice-builder-client"
7
+ gem.version = Vault::InvoiceBuilder::Client::VERSION
8
+ gem.authors = ["Chris Continanza", "Jamu Kakar", "Matthew Manning"]
9
+ gem.email = ["csquared@heroku.com", "jkakar@heroku.com",
10
+ "matthew@heroku.com"]
11
+ gem.description = "Client for Vault::InvoiceBuilder"
12
+ gem.summary = "A simple wrapper for the Vault::InvoiceBuilder HTTP API"
13
+ gem.homepage = "https://github.com/heroku/vault-invoice-builder-client"
14
+
15
+ gem.files = `git ls-files`.split($/)
16
+ gem.test_files = gem.files.grep('^(test|spec|features)/')
17
+ gem.require_paths = ["lib"]
18
+
19
+ gem.add_dependency 'excon'
20
+ gem.add_dependency 'yajl-ruby'
21
+ end
metadata ADDED
@@ -0,0 +1,101 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: vault-invoice-builder-client
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Chris Continanza
9
+ - Jamu Kakar
10
+ - Matthew Manning
11
+ autorequire:
12
+ bindir: bin
13
+ cert_chain: []
14
+ date: 2013-05-09 00:00:00.000000000 Z
15
+ dependencies:
16
+ - !ruby/object:Gem::Dependency
17
+ name: excon
18
+ requirement: !ruby/object:Gem::Requirement
19
+ none: false
20
+ requirements:
21
+ - - ! '>='
22
+ - !ruby/object:Gem::Version
23
+ version: '0'
24
+ type: :runtime
25
+ prerelease: false
26
+ version_requirements: !ruby/object:Gem::Requirement
27
+ none: false
28
+ requirements:
29
+ - - ! '>='
30
+ - !ruby/object:Gem::Version
31
+ version: '0'
32
+ - !ruby/object:Gem::Dependency
33
+ name: yajl-ruby
34
+ requirement: !ruby/object:Gem::Requirement
35
+ none: false
36
+ requirements:
37
+ - - ! '>='
38
+ - !ruby/object:Gem::Version
39
+ version: '0'
40
+ type: :runtime
41
+ prerelease: false
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ none: false
44
+ requirements:
45
+ - - ! '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ description: Client for Vault::InvoiceBuilder
49
+ email:
50
+ - csquared@heroku.com
51
+ - jkakar@heroku.com
52
+ - matthew@heroku.com
53
+ executables: []
54
+ extensions: []
55
+ extra_rdoc_files: []
56
+ files:
57
+ - .gitignore
58
+ - .yardopts
59
+ - Gemfile
60
+ - Gemfile.lock
61
+ - README.md
62
+ - Rakefile
63
+ - lib/vault-invoice-builder-client.rb
64
+ - lib/vault-invoice-builder-client/client.rb
65
+ - lib/vault-invoice-builder-client/version.rb
66
+ - test/client_test.rb
67
+ - test/helper.rb
68
+ - test/version_test.rb
69
+ - vault-invoice-builder-client.gemspec
70
+ homepage: https://github.com/heroku/vault-invoice-builder-client
71
+ licenses: []
72
+ post_install_message:
73
+ rdoc_options: []
74
+ require_paths:
75
+ - lib
76
+ required_ruby_version: !ruby/object:Gem::Requirement
77
+ none: false
78
+ requirements:
79
+ - - ! '>='
80
+ - !ruby/object:Gem::Version
81
+ version: '0'
82
+ segments:
83
+ - 0
84
+ hash: -3070326704752709441
85
+ required_rubygems_version: !ruby/object:Gem::Requirement
86
+ none: false
87
+ requirements:
88
+ - - ! '>='
89
+ - !ruby/object:Gem::Version
90
+ version: '0'
91
+ segments:
92
+ - 0
93
+ hash: -3070326704752709441
94
+ requirements: []
95
+ rubyforge_project:
96
+ rubygems_version: 1.8.23
97
+ signing_key:
98
+ specification_version: 3
99
+ summary: A simple wrapper for the Vault::InvoiceBuilder HTTP API
100
+ test_files: []
101
+ has_rdoc: