stacker_bee 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +20 -0
- data/.rspec +2 -0
- data/.rubocop.yml +7 -0
- data/.travis.yml +9 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +112 -0
- data/Rakefile +6 -0
- data/bin/stacker_bee +97 -0
- data/config.default.yml +3 -0
- data/config/4.2.json +67126 -0
- data/lib/stacker_bee.rb +16 -0
- data/lib/stacker_bee/api.rb +44 -0
- data/lib/stacker_bee/body_parser.rb +23 -0
- data/lib/stacker_bee/client.rb +105 -0
- data/lib/stacker_bee/configuration.rb +6 -0
- data/lib/stacker_bee/connection.rb +31 -0
- data/lib/stacker_bee/middleware/logger.rb +48 -0
- data/lib/stacker_bee/middleware/signed_query.rb +29 -0
- data/lib/stacker_bee/rash.rb +95 -0
- data/lib/stacker_bee/request.rb +41 -0
- data/lib/stacker_bee/request_error.rb +39 -0
- data/lib/stacker_bee/response.rb +29 -0
- data/lib/stacker_bee/utilities.rb +18 -0
- data/lib/stacker_bee/version.rb +3 -0
- data/spec/cassettes/A_response_to_a_request_sent_to_the_CloudStack_API/.yml +33 -0
- data/spec/cassettes/A_response_to_a_request_sent_to_the_CloudStack_API/a_nil_request_parameter/properly_executes_the_request.yml +33 -0
- data/spec/cassettes/A_response_to_a_request_sent_to_the_CloudStack_API/a_request_parameter_with_an_Array/.yml +35 -0
- data/spec/cassettes/A_response_to_a_request_sent_to_the_CloudStack_API/a_request_parameter_with_and_empty_string/properly_executes_the_request.yml +33 -0
- data/spec/cassettes/A_response_to_a_request_sent_to_the_CloudStack_API/containing_an_error/.yml +37 -0
- data/spec/cassettes/A_response_to_a_request_sent_to_the_CloudStack_API/containing_an_error/should_log_response_as_error.yml +37 -0
- data/spec/cassettes/A_response_to_a_request_sent_to_the_CloudStack_API/first/.yml +33 -0
- data/spec/cassettes/A_response_to_a_request_sent_to_the_CloudStack_API/first_item/.yml +33 -0
- data/spec/cassettes/A_response_to_a_request_sent_to_the_CloudStack_API/first_item/_account_type_/.yml +33 -0
- data/spec/cassettes/A_response_to_a_request_sent_to_the_CloudStack_API/first_item/_accounttype_/.yml +33 -0
- data/spec/cassettes/A_response_to_a_request_sent_to_the_CloudStack_API/should_log_request.yml +33 -0
- data/spec/cassettes/A_response_to_a_request_sent_to_the_CloudStack_API/should_not_log_response_as_error.yml +33 -0
- data/spec/cassettes/A_response_to_a_request_sent_to_the_CloudStack_API/space_character_in_a_request_parameter/properly_signs_the_request.yml +32 -0
- data/spec/fixtures/4.2.json +67126 -0
- data/spec/fixtures/simple.json +871 -0
- data/spec/integration/request_spec.rb +116 -0
- data/spec/spec_helper.rb +58 -0
- data/spec/units/stacker_bee/api_spec.rb +24 -0
- data/spec/units/stacker_bee/client_spec.rb +181 -0
- data/spec/units/stacker_bee/configuration_spec.rb +7 -0
- data/spec/units/stacker_bee/connection_spec.rb +45 -0
- data/spec/units/stacker_bee/middleware/logger_spec.rb +55 -0
- data/spec/units/stacker_bee/rash_spec.rb +87 -0
- data/spec/units/stacker_bee/request_error_spec.rb +44 -0
- data/spec/units/stacker_bee/request_spec.rb +49 -0
- data/spec/units/stacker_bee/response_spec.rb +79 -0
- data/spec/units/stacker_bee/utilities_spec.rb +25 -0
- data/spec/units/stacker_bee_spec.rb +6 -0
- data/stacker_bee.gemspec +30 -0
- metadata +225 -0
@@ -0,0 +1,116 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'logger'
|
3
|
+
|
4
|
+
describe "A response to a request sent to the CloudStack API", :vcr do
|
5
|
+
let(:io) { StringIO.new }
|
6
|
+
let(:logger) { Logger.new(io) }
|
7
|
+
let(:log_string) { io.string }
|
8
|
+
let(:url) { CONFIG["url"] }
|
9
|
+
let(:config_hash) do
|
10
|
+
{
|
11
|
+
url: url,
|
12
|
+
api_key: CONFIG["api_key"],
|
13
|
+
secret_key: CONFIG["secret_key"],
|
14
|
+
logger: logger,
|
15
|
+
apis_path: File.join(File.dirname(__FILE__), '../fixtures/4.2.json')
|
16
|
+
}
|
17
|
+
end
|
18
|
+
let(:client) do
|
19
|
+
StackerBee::Client.new(config_hash)
|
20
|
+
end
|
21
|
+
subject { client.list_accounts }
|
22
|
+
|
23
|
+
it { should_not be_empty }
|
24
|
+
|
25
|
+
context "first item" do
|
26
|
+
subject { client.list_accounts.first }
|
27
|
+
it { should include "id" }
|
28
|
+
its(["accounttype"]) { should be_a Numeric }
|
29
|
+
its(["account_type"]) { should be_a Numeric }
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should log request" do
|
33
|
+
subject
|
34
|
+
log_string.should include "listAccounts"
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should not log response as error" do
|
38
|
+
subject
|
39
|
+
log_string.should_not include "ERROR"
|
40
|
+
end
|
41
|
+
|
42
|
+
context "containing an error" do
|
43
|
+
subject do
|
44
|
+
client.deploy_virtual_machine
|
45
|
+
end
|
46
|
+
it { expect { subject }.to raise_error StackerBee::ClientError }
|
47
|
+
|
48
|
+
it "should log response as error" do
|
49
|
+
begin
|
50
|
+
subject
|
51
|
+
rescue StackerBee::ClientError
|
52
|
+
log_string.should include "ERROR"
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
context "failing to connect" do
|
58
|
+
let(:url) { "http://127.0.0.1:1234/client/api" }
|
59
|
+
it "should raise helpful exception" do
|
60
|
+
klass = StackerBee::ConnectionError
|
61
|
+
expect(-> { subject }).to raise_error klass, /#{url}/
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
context "trailing slash in URL", :regression do
|
66
|
+
let(:url) { CONFIG["url"].gsub(/\/$/, '') + '/' }
|
67
|
+
it "makes request with trailing slash" do
|
68
|
+
stub = stub_request(:get, /#{url}/).to_return(body: '{"foo": {}}')
|
69
|
+
subject
|
70
|
+
stub.should have_been_requested
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
context "space character in a request parameter", :regression do
|
75
|
+
let(:params) { { name: "stacker bee" } }
|
76
|
+
subject do
|
77
|
+
client.list_accounts(params)
|
78
|
+
end
|
79
|
+
|
80
|
+
it "properly signs the request" do
|
81
|
+
expect { subject }.not_to raise_error
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
context "a nil request parameter", :regression do
|
86
|
+
let(:params) { { name: nil } }
|
87
|
+
subject do
|
88
|
+
client.list_accounts(params)
|
89
|
+
end
|
90
|
+
|
91
|
+
it "properly executes the request" do
|
92
|
+
expect { subject }.not_to raise_error
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
context "a request parameter with and empty string", :regression do
|
97
|
+
let(:params) { { name: '' } }
|
98
|
+
subject do
|
99
|
+
client.list_accounts(params)
|
100
|
+
end
|
101
|
+
|
102
|
+
it "properly executes the request" do
|
103
|
+
expect { subject }.not_to raise_error
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
context "a request parameter with an Array", :regression do
|
108
|
+
let(:params) { { page: 1, pagesize: 1, details: [:events, :stats] } }
|
109
|
+
subject do
|
110
|
+
client.list_hosts(params).first.keys
|
111
|
+
end
|
112
|
+
it { should include "cpuused" }
|
113
|
+
it { should include "events" }
|
114
|
+
it { should_not include "cpuallocated" }
|
115
|
+
end
|
116
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
# This file was generated by the `rspec --init` command. Conventionally, all
|
2
|
+
# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
|
3
|
+
# Require this file using `require "spec_helper"` to ensure that it is only
|
4
|
+
# loaded once.
|
5
|
+
#
|
6
|
+
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
|
7
|
+
|
8
|
+
require File.expand_path("../../lib/stacker_bee", __FILE__)
|
9
|
+
|
10
|
+
require 'yaml'
|
11
|
+
|
12
|
+
default_config_file = File.expand_path("../../config.default.yml", __FILE__)
|
13
|
+
config_file = File.expand_path("../../config.yml", __FILE__)
|
14
|
+
|
15
|
+
CONFIG = YAML.load(File.read(default_config_file))
|
16
|
+
CONFIG.merge!(YAML.load(File.read(config_file))) if File.exists?(config_file)
|
17
|
+
|
18
|
+
require 'webmock/rspec'
|
19
|
+
|
20
|
+
RSpec.configure do |config|
|
21
|
+
config.treat_symbols_as_metadata_keys_with_true_values = true
|
22
|
+
config.run_all_when_everything_filtered = true
|
23
|
+
config.filter_run :focus
|
24
|
+
|
25
|
+
# Run specs in random order to surface order dependencies. If you find an
|
26
|
+
# order dependency and want to debug it, you can fix the order by providing
|
27
|
+
# the seed, which is printed after each run.
|
28
|
+
# --seed 1234
|
29
|
+
config.order = 'random'
|
30
|
+
|
31
|
+
config.after(:each) do
|
32
|
+
StackerBee::Client.reset!
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
require 'vcr'
|
37
|
+
|
38
|
+
VCR.configure do |c|
|
39
|
+
c.hook_into :webmock
|
40
|
+
c.cassette_library_dir = 'spec/cassettes'
|
41
|
+
c.filter_sensitive_data('<CLOUD_STACK_URL>') do
|
42
|
+
CONFIG["url"]
|
43
|
+
end
|
44
|
+
c.filter_sensitive_data('<CLOUD_STACK_API_KEY>') do
|
45
|
+
CONFIG["api_key"]
|
46
|
+
end
|
47
|
+
c.filter_sensitive_data('<CLOUD_STACK_SECRET_KEY>') do
|
48
|
+
CONFIG["secret_key"]
|
49
|
+
end
|
50
|
+
c.default_cassette_options = {
|
51
|
+
record: :new_episodes,
|
52
|
+
match_requests_on: [
|
53
|
+
:method,
|
54
|
+
VCR.request_matchers.uri_without_param(:signature)
|
55
|
+
]
|
56
|
+
}
|
57
|
+
c.configure_rspec_metadata!
|
58
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe StackerBee::API do
|
4
|
+
subject { api }
|
5
|
+
|
6
|
+
let(:api) { StackerBee::API.new(api_path: api_path) }
|
7
|
+
let(:api_path) do
|
8
|
+
File.join(File.dirname(__FILE__), '../../fixtures/simple.json')
|
9
|
+
end
|
10
|
+
|
11
|
+
its(:api_path) { should eq api_path }
|
12
|
+
|
13
|
+
its(["list_virtual_machines"]) { should be_a Hash }
|
14
|
+
its(["get_vm_password"]) { should be_a Hash }
|
15
|
+
its(["getvmpassword"]) { should be_a Hash }
|
16
|
+
its(["getVMPassword"]) { should be_a Hash }
|
17
|
+
its(["getVmPassword"]) { should be_a Hash }
|
18
|
+
its(["getWRONG"]) { should be_nil }
|
19
|
+
|
20
|
+
it { should be_key "get_vm_password" }
|
21
|
+
it { should be_key "getvmpassword" }
|
22
|
+
it { should be_key "getVMPassword" }
|
23
|
+
it { should be_key "getVmPassword" }
|
24
|
+
end
|
@@ -0,0 +1,181 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
require "ostruct"
|
3
|
+
|
4
|
+
describe StackerBee::Client, ".api" do
|
5
|
+
let(:api) { double }
|
6
|
+
before do
|
7
|
+
StackerBee::API.stub(:new) { api }
|
8
|
+
StackerBee::Client.api_path = nil
|
9
|
+
end
|
10
|
+
subject { StackerBee::Client }
|
11
|
+
its(:api_path) { should_not be_nil }
|
12
|
+
its(:api) { should eq api }
|
13
|
+
end
|
14
|
+
|
15
|
+
describe StackerBee::Client, "calling endpoint" do
|
16
|
+
let(:url) { "cloud-stack.com" }
|
17
|
+
let(:api_key) { "cloud-stack-api-key" }
|
18
|
+
let(:secret_key) { "cloud-stack-secret-key" }
|
19
|
+
let(:config_hash) do
|
20
|
+
{
|
21
|
+
url: url,
|
22
|
+
api_key: api_key,
|
23
|
+
secret_key: secret_key
|
24
|
+
}
|
25
|
+
end
|
26
|
+
let(:client) { StackerBee::Client.new config_hash }
|
27
|
+
let(:endpoint) { :list_virtual_machines }
|
28
|
+
let(:params) { { list: :all } }
|
29
|
+
let(:connection) { double }
|
30
|
+
let(:request) { double :allow_empty_string_params= => nil }
|
31
|
+
let(:raw_response) { double }
|
32
|
+
let(:response) { double }
|
33
|
+
let(:api_path) do
|
34
|
+
File.join(File.dirname(__FILE__), '../../fixtures/simple.json')
|
35
|
+
end
|
36
|
+
|
37
|
+
before do
|
38
|
+
StackerBee::Client.api_path = api_path
|
39
|
+
StackerBee::Connection.stub(:new) { connection }
|
40
|
+
StackerBee::Request.stub(:new).with(
|
41
|
+
"listVirtualMachines", api_key, params
|
42
|
+
) do
|
43
|
+
request
|
44
|
+
end
|
45
|
+
connection.stub(:get).with(request) { raw_response }
|
46
|
+
StackerBee::Response.stub(:new).with(raw_response) { response }
|
47
|
+
end
|
48
|
+
|
49
|
+
subject { client }
|
50
|
+
it { should respond_to endpoint }
|
51
|
+
describe "response to endpoint request" do
|
52
|
+
subject { client.list_virtual_machines(params) }
|
53
|
+
it { should eq response }
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
describe StackerBee::Client, "#request" do
|
58
|
+
subject { client.request(endpoint, params) }
|
59
|
+
let(:endpoint) { "listVirtualMachines" }
|
60
|
+
let(:params) { { list: :all } }
|
61
|
+
|
62
|
+
let(:url) { "cloud-stack.com" }
|
63
|
+
let(:api_key) { "cloud-stack-api-key" }
|
64
|
+
let(:secret_key) { "cloud-stack-secret-key" }
|
65
|
+
let(:config_hash) do
|
66
|
+
{
|
67
|
+
url: url,
|
68
|
+
api_key: api_key,
|
69
|
+
secret_key: secret_key
|
70
|
+
}
|
71
|
+
end
|
72
|
+
let(:client) { StackerBee::Client.new config_hash }
|
73
|
+
let(:connection) { double }
|
74
|
+
let(:request) { double :allow_empty_string_params= => nil }
|
75
|
+
let(:raw_response) { double }
|
76
|
+
let(:response) { double }
|
77
|
+
|
78
|
+
before do
|
79
|
+
StackerBee::Connection.should_receive(:new) { connection }
|
80
|
+
StackerBee::Request.should_receive(:new).with(endpoint, api_key, params) do
|
81
|
+
request
|
82
|
+
end
|
83
|
+
connection.should_receive(:get).with(request) { raw_response }
|
84
|
+
StackerBee::Response.should_receive(:new).with(raw_response) { response }
|
85
|
+
end
|
86
|
+
|
87
|
+
it { should eq response }
|
88
|
+
|
89
|
+
context "called with a differently-cased endpoint" do
|
90
|
+
subject { client.request("list_Virtual_mACHINES", params) }
|
91
|
+
it { should eq response }
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
describe StackerBee::Client, "configuration" do
|
96
|
+
let(:default_url) { "default_cloud-stack.com" }
|
97
|
+
let(:default_api_key) { "default-cloud-stack-api-key" }
|
98
|
+
let(:default_secret_key) { "default-cloud-stack-secret-key" }
|
99
|
+
let(:default_config_hash) do
|
100
|
+
{
|
101
|
+
url: default_url,
|
102
|
+
api_key: default_api_key,
|
103
|
+
secret_key: default_secret_key,
|
104
|
+
allow_empty_string_params: false
|
105
|
+
}
|
106
|
+
end
|
107
|
+
let!(:default_configuration) do
|
108
|
+
StackerBee::Configuration.new(default_config_hash)
|
109
|
+
end
|
110
|
+
let(:instance_url) { "instance-cloud-stack.com" }
|
111
|
+
let(:instance_api_key) { "instance-cloud-stack-api-key" }
|
112
|
+
let(:instance_secret_key) { "instance-cloud-stack-secret-key" }
|
113
|
+
let(:instance_config_hash) do
|
114
|
+
{
|
115
|
+
url: instance_url,
|
116
|
+
api_key: instance_api_key,
|
117
|
+
secret_key: instance_secret_key,
|
118
|
+
allow_empty_string_params: false
|
119
|
+
}
|
120
|
+
end
|
121
|
+
let!(:instance_configuration) do
|
122
|
+
StackerBee::Configuration.new(instance_config_hash)
|
123
|
+
end
|
124
|
+
before do
|
125
|
+
StackerBee::Configuration.stub(:new) do
|
126
|
+
fail "Unexpected Configuration instantiation"
|
127
|
+
end
|
128
|
+
StackerBee::Configuration.stub(:new).with(default_config_hash) do
|
129
|
+
default_configuration
|
130
|
+
end
|
131
|
+
StackerBee::Configuration.stub(:new).with(instance_config_hash) do
|
132
|
+
instance_configuration
|
133
|
+
end
|
134
|
+
StackerBee::Client.configuration = default_config_hash
|
135
|
+
end
|
136
|
+
|
137
|
+
describe ".new" do
|
138
|
+
subject { StackerBee::Client.new }
|
139
|
+
|
140
|
+
context "with default, class configuration" do
|
141
|
+
its(:url) { should eq default_url }
|
142
|
+
its(:api_key) { should eq default_api_key }
|
143
|
+
its(:secret_key) { should eq default_secret_key }
|
144
|
+
end
|
145
|
+
|
146
|
+
context "with instance-specific configuration" do
|
147
|
+
subject { StackerBee::Client.new(instance_config_hash) }
|
148
|
+
its(:configuration) { should eq instance_configuration }
|
149
|
+
its(:url) { should eq instance_url }
|
150
|
+
its(:api_key) { should eq instance_api_key }
|
151
|
+
its(:secret_key) { should eq instance_secret_key }
|
152
|
+
end
|
153
|
+
|
154
|
+
context "with instance-specific configuration that's not a hash" do
|
155
|
+
subject { StackerBee::Client.new(config) }
|
156
|
+
let(:config) { double(to_hash: instance_config_hash) }
|
157
|
+
its(:configuration) { should eq instance_configuration }
|
158
|
+
its(:url) { should eq instance_url }
|
159
|
+
its(:api_key) { should eq instance_api_key }
|
160
|
+
its(:secret_key) { should eq instance_secret_key }
|
161
|
+
end
|
162
|
+
|
163
|
+
describe "#url" do
|
164
|
+
let(:other_url) { "other-cloud-stack.com" }
|
165
|
+
before { subject.url = other_url }
|
166
|
+
its(:url) { should eq other_url }
|
167
|
+
end
|
168
|
+
|
169
|
+
describe "#api_key" do
|
170
|
+
let(:other_api_key) { "other-cloud-stack-api-key" }
|
171
|
+
before { subject.api_key = other_api_key }
|
172
|
+
its(:api_key) { should eq other_api_key }
|
173
|
+
end
|
174
|
+
|
175
|
+
describe "#secret_key" do
|
176
|
+
let(:other_secret_key) { "other-cloud-stack-secret-key" }
|
177
|
+
before { subject.secret_key = other_secret_key }
|
178
|
+
its(:secret_key) { should eq other_secret_key }
|
179
|
+
end
|
180
|
+
end
|
181
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe StackerBee::Connection do
|
4
|
+
let(:url) { "http://test.com:1234/foo/bar/" }
|
5
|
+
let(:secret_key) { "shhh" }
|
6
|
+
let(:configuration) { double url: url, secret_key: secret_key }
|
7
|
+
let(:query_params) { [[:foo, :bar]] }
|
8
|
+
let(:request) { double query_params: query_params }
|
9
|
+
let(:response) { double }
|
10
|
+
let(:faraday) { double get: response }
|
11
|
+
let(:connection) { StackerBee::Connection.new configuration }
|
12
|
+
subject { connection.get request }
|
13
|
+
before do
|
14
|
+
Faraday.stub(:new) { faraday }
|
15
|
+
end
|
16
|
+
|
17
|
+
context "successfully connecting" do
|
18
|
+
before do
|
19
|
+
faraday.should_receive(:get).with('/foo/bar/', query_params) { response }
|
20
|
+
end
|
21
|
+
it { should be response }
|
22
|
+
it "specifies url without path when creating connection" do
|
23
|
+
subject
|
24
|
+
Faraday.should have_received(:new).with(url: "http://test.com:1234")
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
context "failing to connect" do
|
29
|
+
before do
|
30
|
+
faraday.stub(:get) { fail Faraday::Error::ConnectionFailed, "boom" }
|
31
|
+
end
|
32
|
+
it "should raise helpful exception" do
|
33
|
+
klass = StackerBee::ConnectionError
|
34
|
+
expect(-> { subject }).to raise_error klass, /#{url}/
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
context "no protocol specified in URL" do
|
39
|
+
let(:url) { "wrong.com" }
|
40
|
+
it "should raise helpful exception" do
|
41
|
+
klass = StackerBee::ConnectionError
|
42
|
+
expect(-> { subject }).to raise_error klass, /no protocol/
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe StackerBee::Middleware::Logger do
|
4
|
+
let(:app) { double }
|
5
|
+
let(:io) { StringIO.new }
|
6
|
+
let(:logger) { Logger.new(io) }
|
7
|
+
let(:log_string) { io.string }
|
8
|
+
let(:middleware) { described_class.new app, logger }
|
9
|
+
subject { middleware }
|
10
|
+
|
11
|
+
context "with a no logger specified" do
|
12
|
+
let(:middleware) { described_class.new app, nil }
|
13
|
+
its(:logger) { should be_a Logger }
|
14
|
+
end
|
15
|
+
|
16
|
+
describe "logging request" do
|
17
|
+
let(:env) do
|
18
|
+
{
|
19
|
+
method: "PATCH",
|
20
|
+
url: "http://localhost",
|
21
|
+
request_headers: { "User-Agent" => "RSpec" }
|
22
|
+
}
|
23
|
+
end
|
24
|
+
before do
|
25
|
+
middleware.log_request(env)
|
26
|
+
end
|
27
|
+
subject { log_string }
|
28
|
+
it { should include "PATCH" }
|
29
|
+
it { should include "localhost" }
|
30
|
+
it { should include "User-Agent" }
|
31
|
+
end
|
32
|
+
|
33
|
+
describe "logging a response" do
|
34
|
+
let(:status) { 200 }
|
35
|
+
let(:env) do
|
36
|
+
{
|
37
|
+
status: status,
|
38
|
+
body: "OK",
|
39
|
+
response_headers: { "Server" => "RSpec" }
|
40
|
+
}
|
41
|
+
end
|
42
|
+
before do
|
43
|
+
middleware.log_response(env)
|
44
|
+
end
|
45
|
+
subject { log_string }
|
46
|
+
it { should =~ /INFO.*#{status}/ }
|
47
|
+
it { should include "OK" }
|
48
|
+
it { should include "Server" }
|
49
|
+
|
50
|
+
context "failing status" do
|
51
|
+
let(:status) { 401 }
|
52
|
+
it { should =~ /ERROR.*#{status}/ }
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|