vault-invoice-builder-client 0.0.2
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/.gitignore +6 -0
- data/.yardopts +1 -0
- data/Gemfile +12 -0
- data/Gemfile.lock +56 -0
- data/README.md +67 -0
- data/Rakefile +11 -0
- data/lib/vault-invoice-builder-client.rb +17 -0
- data/lib/vault-invoice-builder-client/client.rb +67 -0
- data/lib/vault-invoice-builder-client/version.rb +8 -0
- data/test/client_test.rb +132 -0
- data/test/helper.rb +4 -0
- data/test/version_test.rb +9 -0
- data/vault-invoice-builder-client.gemspec +21 -0
- metadata +101 -0
data/.gitignore
ADDED
data/.yardopts
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
-m markdown
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -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)!
|
data/README.md
ADDED
@@ -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
|
+
```
|
data/Rakefile
ADDED
@@ -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
|
data/test/client_test.rb
ADDED
@@ -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
|
data/test/helper.rb
ADDED
@@ -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:
|