apiture 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +19 -0
- data/Gemfile +8 -0
- data/LICENSE +20 -0
- data/README.md +38 -0
- data/Rakefile +6 -0
- data/apiture.gemspec +30 -0
- data/lib/apiture.rb +24 -0
- data/lib/apiture/api_base.rb +27 -0
- data/lib/apiture/api_builder.rb +196 -0
- data/lib/apiture/api_error.rb +3 -0
- data/lib/apiture/api_group.rb +28 -0
- data/lib/apiture/data_model.rb +24 -0
- data/lib/apiture/endpoint.rb +25 -0
- data/lib/apiture/middleware/auth/api_key.rb +39 -0
- data/lib/apiture/middleware/auth/basic.rb +25 -0
- data/lib/apiture/middleware/auth/oauth2.rb +31 -0
- data/lib/apiture/middleware/convert_json_body.rb +15 -0
- data/lib/apiture/middleware/debug.rb +20 -0
- data/lib/apiture/middleware/set_body_parameter.rb +20 -0
- data/lib/apiture/middleware/set_header.rb +15 -0
- data/lib/apiture/middleware/set_parameter_base.rb +37 -0
- data/lib/apiture/middleware/set_path_parameter.rb +18 -0
- data/lib/apiture/middleware/set_query_parameter.rb +13 -0
- data/lib/apiture/middleware_builder.rb +15 -0
- data/lib/apiture/middleware_stack.rb +21 -0
- data/lib/apiture/request_context.rb +103 -0
- data/lib/apiture/swagger/data_type_field.rb +25 -0
- data/lib/apiture/swagger/definition.rb +20 -0
- data/lib/apiture/swagger/external_docs.rb +10 -0
- data/lib/apiture/swagger/info.rb +14 -0
- data/lib/apiture/swagger/node.rb +149 -0
- data/lib/apiture/swagger/operation.rb +32 -0
- data/lib/apiture/swagger/parameter.rb +35 -0
- data/lib/apiture/swagger/parser.rb +148 -0
- data/lib/apiture/swagger/path.rb +37 -0
- data/lib/apiture/swagger/property.rb +15 -0
- data/lib/apiture/swagger/security.rb +21 -0
- data/lib/apiture/swagger/security_definition.rb +23 -0
- data/lib/apiture/swagger/specification.rb +31 -0
- data/lib/apiture/uri.rb +36 -0
- data/lib/apiture/utils/inflections.rb +46 -0
- data/lib/apiture/version.rb +3 -0
- data/spec/apiture/api_builder_spec.rb +20 -0
- data/spec/apiture/swagger/parser_spec.rb +107 -0
- data/spec/apiture/swagger/specification_spec.rb +19 -0
- data/spec/apiture_spec.rb +228 -0
- data/spec/files/github.json +186 -0
- data/spec/files/harvest.json +75 -0
- data/spec/files/honeybadger.json +80 -0
- data/spec/files/mandrill.json +502 -0
- data/spec/files/pivotal_tracker.json +94 -0
- data/spec/files/slack.json +88 -0
- data/spec/files/uber.json +43 -0
- data/spec/fixtures/vcr_cassettes/github_checkAuthorization.yml +70 -0
- data/spec/fixtures/vcr_cassettes/github_getUser.yml +82 -0
- data/spec/fixtures/vcr_cassettes/harvest_invoiceList.yml +85 -0
- data/spec/fixtures/vcr_cassettes/honeybadger.yml +98 -0
- data/spec/fixtures/vcr_cassettes/mandrill_messageSend.yml +44 -0
- data/spec/fixtures/vcr_cassettes/mandrill_userPing.yml +44 -0
- data/spec/fixtures/vcr_cassettes/pivotal_tracker_create_story.yml +61 -0
- data/spec/fixtures/vcr_cassettes/slack.yml +43 -0
- data/spec/fixtures/vcr_cassettes/uber_getProducts.yml +60 -0
- data/spec/spec_helper.rb +11 -0
- metadata +241 -0
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'apiture/swagger/node'
|
2
|
+
|
3
|
+
module Apiture
|
4
|
+
module Swagger
|
5
|
+
class Security < Node
|
6
|
+
attr_reader :id
|
7
|
+
|
8
|
+
attribute :scopes
|
9
|
+
|
10
|
+
def initialize(id)
|
11
|
+
super()
|
12
|
+
@id = id
|
13
|
+
end
|
14
|
+
|
15
|
+
def serializable_hash
|
16
|
+
scopes || []
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'apiture/swagger/node'
|
2
|
+
|
3
|
+
module Apiture
|
4
|
+
module Swagger
|
5
|
+
class SecurityDefinition < Node
|
6
|
+
attr_reader :id
|
7
|
+
|
8
|
+
attribute :type
|
9
|
+
attribute :description
|
10
|
+
attribute :name
|
11
|
+
attribute :in, symbolize: true
|
12
|
+
attribute :flow
|
13
|
+
attribute :authorization_url
|
14
|
+
attribute :token_url
|
15
|
+
attribute :scopes
|
16
|
+
|
17
|
+
def initialize(id)
|
18
|
+
super()
|
19
|
+
@id = id
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'apiture/swagger/info'
|
2
|
+
require 'apiture/swagger/external_docs'
|
3
|
+
require 'apiture/swagger/security'
|
4
|
+
require 'apiture/swagger/security_definition'
|
5
|
+
require 'apiture/swagger/path'
|
6
|
+
require 'apiture/swagger/definition'
|
7
|
+
# require 'apiture/swagger/response'
|
8
|
+
|
9
|
+
module Apiture
|
10
|
+
module Swagger
|
11
|
+
class Specification < Node
|
12
|
+
attribute :swagger
|
13
|
+
attribute :info, validate: true
|
14
|
+
attribute :host
|
15
|
+
attribute :base_path
|
16
|
+
attribute :external_docs, validate: true
|
17
|
+
|
18
|
+
list :schemes
|
19
|
+
list :consumes
|
20
|
+
list :produces
|
21
|
+
list :tags, validate: true
|
22
|
+
|
23
|
+
hash :paths, validate: true
|
24
|
+
hash :definitions, validate: true
|
25
|
+
hash :parameters, validate: true
|
26
|
+
hash :responses, validate: true
|
27
|
+
hash :security_definitions, validate: true
|
28
|
+
hash :security, validate: true
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
data/lib/apiture/uri.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
module Apiture
|
2
|
+
class URI
|
3
|
+
|
4
|
+
components = [:scheme, :host, :base_host, :subdomain, :base_path, :resource_path]
|
5
|
+
|
6
|
+
attr_reader *components
|
7
|
+
|
8
|
+
components.each do |comp|
|
9
|
+
define_method "#{comp}=".to_sym do |v|
|
10
|
+
instance_variable_set("@#{comp}", v)
|
11
|
+
build_url
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def to_s
|
16
|
+
build_url
|
17
|
+
end
|
18
|
+
|
19
|
+
protected
|
20
|
+
|
21
|
+
def build_url
|
22
|
+
host = if base_host && subdomain
|
23
|
+
[subdomain, base_host].join('.')
|
24
|
+
else
|
25
|
+
self.host
|
26
|
+
end
|
27
|
+
[
|
28
|
+
scheme,
|
29
|
+
'://',
|
30
|
+
host,
|
31
|
+
base_path,
|
32
|
+
resource_path
|
33
|
+
].join('')
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module Apiture
|
2
|
+
module Utils
|
3
|
+
module Inflections
|
4
|
+
|
5
|
+
def self.acronyms
|
6
|
+
@@acronyms ||= {}
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.acronym_regex
|
10
|
+
@@acronym_regex ||= /(?=a)b/
|
11
|
+
end
|
12
|
+
|
13
|
+
def camelize(term, uppercase_first_letter = true)
|
14
|
+
string = term.to_s
|
15
|
+
if uppercase_first_letter
|
16
|
+
string = string.sub(/^[a-z\d]*/) { ::Apiture::Utils::Inflections.acronyms[$&] || $&.capitalize }
|
17
|
+
else
|
18
|
+
string = string.sub(/^(?:#{::Apiture::Utils::Inflections.acronym_regex}(?=\b|[A-Z_])|\w)/) { $&.downcase }
|
19
|
+
end
|
20
|
+
string.gsub!(/(?:_|(\/))([a-z\d]*)/) { "#{$1}#{::Apiture::Utils::Inflections.acronyms[$2] || $2.capitalize}" }
|
21
|
+
string.gsub!('/', '::')
|
22
|
+
string
|
23
|
+
end
|
24
|
+
|
25
|
+
def underscore(camel_cased_word)
|
26
|
+
word = camel_cased_word.to_s.gsub('::', '/')
|
27
|
+
word.gsub!(/(?:([A-Za-z\d])|^)(#{::Apiture::Utils::Inflections.acronym_regex})(?=\b|[^a-z])/) { "#{$1}#{$1 && '_'}#{$2.downcase}" }
|
28
|
+
word.gsub!(/([A-Z\d]+)([A-Z][a-z])/,'\1_\2')
|
29
|
+
word.gsub!(/([a-z\d])([A-Z])/,'\1_\2')
|
30
|
+
word.tr!("-", "_")
|
31
|
+
word.downcase!
|
32
|
+
word
|
33
|
+
end
|
34
|
+
|
35
|
+
def constantize(camel_cased_word)
|
36
|
+
unless /\A(?:::)?([A-Z]\w*(?:::[A-Z]\w*)*)\z/ =~ camel_cased_word
|
37
|
+
raise NameError, "#{camel_cased_word.inspect} is not a valid constant name!"
|
38
|
+
end
|
39
|
+
|
40
|
+
Object.module_eval("::#{$1}", __FILE__, __LINE__)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
Apiture::Utils::Inflections.extend(Apiture::Utils::Inflections)
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'apiture'
|
3
|
+
|
4
|
+
describe Apiture::APIBuilder do
|
5
|
+
|
6
|
+
def build_spec(name)
|
7
|
+
Apiture.parse_specification(File.join(File.dirname(__FILE__), '..', 'files', "#{name}.json"))
|
8
|
+
end
|
9
|
+
|
10
|
+
it "should build a API class from specification" do
|
11
|
+
api = Apiture::APIBuilder.new(build_spec("pivotal_tracker")).build
|
12
|
+
expect(api).to_not be_nil
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should build a API class from specification" do
|
16
|
+
api = Apiture::APIBuilder.new(build_spec("mandrill")).build
|
17
|
+
expect(api).to_not be_nil
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
@@ -0,0 +1,107 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'apiture/swagger/parser'
|
3
|
+
|
4
|
+
describe Apiture::Swagger::Parser do
|
5
|
+
subject { Apiture::Swagger::Parser }
|
6
|
+
|
7
|
+
def load_spec(name)
|
8
|
+
File.read(File.join(File.dirname(__FILE__), '..', '..', 'files', "#{name}.json"))
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should parse a swagger specification" do
|
12
|
+
specification = Apiture::Swagger::Parser.new.parse(load_spec('pivotal_tracker'))
|
13
|
+
expect(specification).to_not be_nil
|
14
|
+
|
15
|
+
expect(specification.host).to eq "www.pivotaltracker.com"
|
16
|
+
expect(specification.schemes).to include "https"
|
17
|
+
expect(specification.base_path).to eq "/services/v5"
|
18
|
+
|
19
|
+
expect(specification.info).to_not be_nil
|
20
|
+
expect(specification.info.title).to eq "PivotalTracker"
|
21
|
+
expect(specification.info.version).to eq "5"
|
22
|
+
|
23
|
+
api_token = specification.security_definitions['apiToken']
|
24
|
+
expect(api_token).to_not be_nil
|
25
|
+
expect(api_token.type).to eq "apiKey"
|
26
|
+
expect(api_token.in).to eq :header
|
27
|
+
expect(api_token.name).to eq "X-TrackerToken"
|
28
|
+
|
29
|
+
security = specification.security['apiToken']
|
30
|
+
expect(security).to_not be_nil
|
31
|
+
|
32
|
+
expect(specification.produces).to include "application/json"
|
33
|
+
|
34
|
+
expect(specification.paths.count).to eq 1
|
35
|
+
|
36
|
+
path = specification.paths["/projects/{projectId}/stories"]
|
37
|
+
expect(path).to_not be_nil
|
38
|
+
|
39
|
+
expect(path.post).to_not be_nil
|
40
|
+
expect(path.post.operation_id).to eq "createStory"
|
41
|
+
expect(path.post.external_docs.url).to eq "https://www.pivotaltracker.com/help/api/rest/v5#projects_project_id_stories_post"
|
42
|
+
|
43
|
+
expect(path.post.parameters.count).to eq 2
|
44
|
+
|
45
|
+
param1 = path.post.parameters[0]
|
46
|
+
expect(param1).to_not be_nil
|
47
|
+
expect(param1.in).to eq :path
|
48
|
+
expect(param1.name).to eq "projectId"
|
49
|
+
expect(param1).to be_required
|
50
|
+
|
51
|
+
param2 = path.post.parameters[1]
|
52
|
+
expect(param2).to_not be_nil
|
53
|
+
expect(param2.in).to eq :body
|
54
|
+
expect(param2.name).to eq "story"
|
55
|
+
expect(param2).to be_required
|
56
|
+
expect(param2.schema).to eq "NewStory"
|
57
|
+
|
58
|
+
expect(specification.definitions.count).to eq 1
|
59
|
+
|
60
|
+
definition = specification.definitions["NewStory"]
|
61
|
+
expect(definition).to_not be_nil
|
62
|
+
expect(definition.required).to eq ["name"]
|
63
|
+
|
64
|
+
expect(definition.properties.count).to eq 15
|
65
|
+
|
66
|
+
prop1 = definition.properties["cl_numbers"]
|
67
|
+
expect(prop1).to_not be_nil
|
68
|
+
expect(prop1.type).to eq :string
|
69
|
+
|
70
|
+
prop2 = definition.properties["current_state"]
|
71
|
+
expect(prop2).to_not be_nil
|
72
|
+
expect(prop2.type).to eq :string
|
73
|
+
expect(prop2.enum).to eq [
|
74
|
+
"accepted",
|
75
|
+
"delivered",
|
76
|
+
"finished",
|
77
|
+
"started",
|
78
|
+
"rejected",
|
79
|
+
"unstarted",
|
80
|
+
"unscheduled"
|
81
|
+
]
|
82
|
+
end
|
83
|
+
|
84
|
+
it "should parse a swagger specification with an array of schema objects" do
|
85
|
+
specification = Apiture::Swagger::Parser.new.parse(load_spec('slack'))
|
86
|
+
payload = specification.definitions["Payload"]
|
87
|
+
|
88
|
+
attachments_prop = payload.properties['attachments']
|
89
|
+
expect(attachments_prop.type).to eq :array
|
90
|
+
expect(attachments_prop.items.count).to eq 1
|
91
|
+
expect(attachments_prop.items["$ref"]).to eq '#/definitions/Attachment'
|
92
|
+
end
|
93
|
+
|
94
|
+
it "should parse a swagger specification with operation specific security" do
|
95
|
+
specification = Apiture::Swagger::Parser.new.parse(load_spec('github'))
|
96
|
+
op = specification.paths["/applications/{clientId}/tokens/{accessToken}"].get
|
97
|
+
expect(op.security["basic"]).to_not be_nil
|
98
|
+
end
|
99
|
+
|
100
|
+
it "should parse nested schema objects" do
|
101
|
+
specification = Apiture::Swagger::Parser.new.parse(load_spec('mandrill'))
|
102
|
+
op = specification.paths["/messages/send.json"].post
|
103
|
+
request_param = op.parameters.first
|
104
|
+
expect(specification.consumes).to include "application/json"
|
105
|
+
expect(request_param.schema.class).to eq Apiture::Swagger::Definition
|
106
|
+
end
|
107
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'apiture/swagger/specification'
|
3
|
+
|
4
|
+
describe Apiture::Swagger::Specification do
|
5
|
+
|
6
|
+
it "should serialize security node as key and scopes" do
|
7
|
+
spec = described_class.new
|
8
|
+
|
9
|
+
security = Apiture::Swagger::Security.new('oauth')
|
10
|
+
security.scopes = ['email']
|
11
|
+
spec.security = { 'oauth' => security }
|
12
|
+
|
13
|
+
hash = spec.serializable_hash
|
14
|
+
security_hash = hash['security']
|
15
|
+
expect(security_hash).to_not be_nil
|
16
|
+
scopes = security_hash['oauth']
|
17
|
+
expect(scopes).to eq ['email']
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,228 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'apiture'
|
3
|
+
require 'logger'
|
4
|
+
|
5
|
+
describe Apiture do
|
6
|
+
|
7
|
+
def configure_client(client)
|
8
|
+
#client.logger = Logger.new(STDOUT)
|
9
|
+
#client.logger.level = Logger::DEBUG
|
10
|
+
client
|
11
|
+
end
|
12
|
+
|
13
|
+
def load_api(name)
|
14
|
+
fn = File.join(File.dirname(__FILE__), 'files', "#{name}.json")
|
15
|
+
Apiture.load_api(fn)
|
16
|
+
end
|
17
|
+
|
18
|
+
describe do
|
19
|
+
let(:parser) { double("parser") }
|
20
|
+
|
21
|
+
before do
|
22
|
+
allow(File).to receive(:read)
|
23
|
+
expect(Apiture::Swagger::Parser).to receive(:new).and_return(parser)
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should auto-detect whether it is parsing YAML file" do
|
27
|
+
expect(parser).to receive(:parse_yaml)
|
28
|
+
Apiture.parse_specification("foo.yml")
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should auto-detect whether it is parsing JSON file" do
|
32
|
+
expect(parser).to receive(:parse_json)
|
33
|
+
Apiture.parse_specification("foo.json")
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
describe "Pivotal Tracker API" do
|
38
|
+
before do
|
39
|
+
PivotalTracker = load_api('pivotal_tracker')
|
40
|
+
@client = configure_client(PivotalTracker.new(api_token: 'afaketoken'))
|
41
|
+
end
|
42
|
+
|
43
|
+
after do
|
44
|
+
Object.send(:remove_const, :PivotalTracker)
|
45
|
+
end
|
46
|
+
|
47
|
+
it "should be able to build a client" do
|
48
|
+
VCR.use_cassette('pivotal_tracker_create_story') do
|
49
|
+
result = @client.create_story(
|
50
|
+
project_id: '1053124',
|
51
|
+
story: {
|
52
|
+
name: 'Testing Pivotal API',
|
53
|
+
story_type: :chore
|
54
|
+
})
|
55
|
+
expect(result.body['kind']).to eq 'story'
|
56
|
+
expect(result.body).to have_key('id')
|
57
|
+
expect(result.status).to eq 200
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
describe "Honeybadger API" do
|
63
|
+
before do
|
64
|
+
Honeybadger = load_api('honeybadger')
|
65
|
+
@client = configure_client(Honeybadger.new(auth_token: 'afaketoken'))
|
66
|
+
end
|
67
|
+
|
68
|
+
after do
|
69
|
+
Object.send(:remove_const, :Honeybadger)
|
70
|
+
end
|
71
|
+
|
72
|
+
it "should be able to build a Honeybadger API client" do
|
73
|
+
VCR.use_cassette('honeybadger') do
|
74
|
+
results = @client.get_faults(project_id: 3167)
|
75
|
+
expect(results.body['results'].first).to have_key('project_id')
|
76
|
+
expect(results.status).to eq 200
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
describe "Slack API" do
|
82
|
+
before do
|
83
|
+
Slack = load_api('slack')
|
84
|
+
@client = configure_client(Slack.new)
|
85
|
+
end
|
86
|
+
|
87
|
+
after do
|
88
|
+
Object.send(:remove_const, :Slack)
|
89
|
+
end
|
90
|
+
|
91
|
+
it "should be able to build a Slack API client" do
|
92
|
+
VCR.use_cassette('slack') do
|
93
|
+
results = @client.post_message(path: 'abcd/efgh/ijkl',
|
94
|
+
payload: {
|
95
|
+
text: 'Testing',
|
96
|
+
username: 'TestBot',
|
97
|
+
attachments: [{
|
98
|
+
fallback: "test fallback text",
|
99
|
+
text: "test text",
|
100
|
+
pretext: "test pretext",
|
101
|
+
fields: [{
|
102
|
+
title: "test field 1",
|
103
|
+
value: "test value 1"
|
104
|
+
},{
|
105
|
+
title: "test field 2",
|
106
|
+
value: "test value 2"
|
107
|
+
}]
|
108
|
+
}]
|
109
|
+
})
|
110
|
+
expect(results.status).to eq 200
|
111
|
+
expect(results.body).to eq "ok"
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
describe "Github API" do
|
117
|
+
before do
|
118
|
+
Github = load_api("github")
|
119
|
+
@client = configure_client(Github.new(
|
120
|
+
oauth2: { token: "afaketoken" },
|
121
|
+
basic: {
|
122
|
+
username: "afakeclientid",
|
123
|
+
password: "afakeclientsecret"
|
124
|
+
}
|
125
|
+
))
|
126
|
+
end
|
127
|
+
|
128
|
+
after do
|
129
|
+
Object.send(:remove_const, :Github)
|
130
|
+
end
|
131
|
+
|
132
|
+
it "should be able to call a zero parameter operation" do
|
133
|
+
VCR.use_cassette('github_getUser') do
|
134
|
+
results = @client.get_user
|
135
|
+
expect(results.status).to eq 200
|
136
|
+
expect(results.body['login']).to eq "cyu"
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
it "should be able to use the appropriate security scheme" do
|
141
|
+
VCR.use_cassette('github_checkAuthorization') do
|
142
|
+
results = @client.check_authorization(
|
143
|
+
client_id: "afakeclientid",
|
144
|
+
access_token: "afaketoken"
|
145
|
+
)
|
146
|
+
expect(results.status).to eq 200
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
describe "Uber API" do
|
152
|
+
before do
|
153
|
+
Uber = load_api("uber")
|
154
|
+
@client = configure_client(Uber.new(
|
155
|
+
server_token: "TEST_SERVER_TOKEN"
|
156
|
+
))
|
157
|
+
end
|
158
|
+
|
159
|
+
after do
|
160
|
+
Object.send(:remove_const, :Uber)
|
161
|
+
end
|
162
|
+
|
163
|
+
it "should be able to support x-format extension for apiKey" do
|
164
|
+
VCR.use_cassette('uber_getProducts') do
|
165
|
+
results = @client.get_products(latitude: 33.776776, longitude: -84.389683)
|
166
|
+
expect(results.status).to eq 200
|
167
|
+
expect(results.body["products"].length).to eq 5
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
describe "Mandrill API" do
|
173
|
+
before do
|
174
|
+
Mandrill = load_api("mandrill")
|
175
|
+
@client = configure_client(Mandrill.new(
|
176
|
+
key: "fakekey"
|
177
|
+
))
|
178
|
+
end
|
179
|
+
|
180
|
+
after do
|
181
|
+
Object.send(:remove_const, :Mandrill)
|
182
|
+
end
|
183
|
+
|
184
|
+
it "should be able to support apiKey in JSON body" do
|
185
|
+
VCR.use_cassette('mandrill_userPing') do
|
186
|
+
result = @client.user_ping
|
187
|
+
expect(result.body).to eq "PONG!"
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
it "should be able to build request with apiKey and parameters in JSON body" do
|
192
|
+
VCR.use_cassette('mandrill_messageSend') do
|
193
|
+
result = @client.message_send(request: {
|
194
|
+
message: {
|
195
|
+
text: "testing",
|
196
|
+
subject: "testing",
|
197
|
+
from_email: "test@test.com",
|
198
|
+
to: [ { email: "test@example.com" } ]
|
199
|
+
}
|
200
|
+
}).body
|
201
|
+
expect(result.first["email"]).to eq "test@example.com"
|
202
|
+
expect(result.first["status"]).to eq "sent"
|
203
|
+
end
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
describe "Harvest API" do
|
208
|
+
before do
|
209
|
+
Harvest = load_api("harvest")
|
210
|
+
@client = configure_client(Harvest.new(
|
211
|
+
subdomain: "fakedomain",
|
212
|
+
oauth2: {
|
213
|
+
token: "faketoken"
|
214
|
+
}))
|
215
|
+
end
|
216
|
+
|
217
|
+
after do
|
218
|
+
Object.send(:remove_const, :Harvest)
|
219
|
+
end
|
220
|
+
|
221
|
+
it "should support x-base-host extension" do
|
222
|
+
VCR.use_cassette('harvest_invoiceList') do
|
223
|
+
result = @client.invoice_list.body
|
224
|
+
expect(result.length).to eq 2
|
225
|
+
end
|
226
|
+
end
|
227
|
+
end
|
228
|
+
end
|