castle-rb 3.6.2 → 4.3.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.
Files changed (48) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +57 -5
  3. data/lib/castle.rb +5 -3
  4. data/lib/castle/api.rb +12 -6
  5. data/lib/castle/api/request.rb +15 -10
  6. data/lib/castle/api/session.rb +39 -0
  7. data/lib/castle/client.rb +23 -18
  8. data/lib/castle/configuration.rb +49 -6
  9. data/lib/castle/context/default.rb +36 -18
  10. data/lib/castle/context/sanitizer.rb +1 -0
  11. data/lib/castle/events.rb +49 -0
  12. data/lib/castle/extractors/client_id.rb +7 -3
  13. data/lib/castle/extractors/headers.rb +24 -30
  14. data/lib/castle/extractors/ip.rb +69 -5
  15. data/lib/castle/headers_filter.rb +35 -0
  16. data/lib/castle/headers_formatter.rb +22 -0
  17. data/lib/castle/validators/not_supported.rb +1 -0
  18. data/lib/castle/validators/present.rb +1 -0
  19. data/lib/castle/version.rb +1 -1
  20. data/spec/integration/rails/rails_spec.rb +61 -0
  21. data/spec/integration/rails/support/all.rb +6 -0
  22. data/spec/integration/rails/support/application.rb +15 -0
  23. data/spec/integration/rails/support/home_controller.rb +21 -0
  24. data/spec/lib/castle/api/request_spec.rb +43 -30
  25. data/spec/lib/castle/api/session_spec.rb +47 -0
  26. data/spec/lib/castle/api_spec.rb +4 -4
  27. data/spec/lib/castle/client_spec.rb +5 -3
  28. data/spec/lib/castle/commands/authenticate_spec.rb +1 -0
  29. data/spec/lib/castle/commands/identify_spec.rb +1 -0
  30. data/spec/lib/castle/commands/impersonate_spec.rb +1 -0
  31. data/spec/lib/castle/commands/track_spec.rb +1 -0
  32. data/spec/lib/castle/configuration_spec.rb +21 -4
  33. data/spec/lib/castle/context/default_spec.rb +13 -13
  34. data/spec/lib/castle/events_spec.rb +5 -0
  35. data/spec/lib/castle/extractors/client_id_spec.rb +2 -1
  36. data/spec/lib/castle/extractors/headers_spec.rb +67 -51
  37. data/spec/lib/castle/extractors/ip_spec.rb +89 -12
  38. data/spec/lib/castle/headers_filter_spec.rb +38 -0
  39. data/spec/lib/castle/{header_formatter_spec.rb → headers_formatter_spec.rb} +3 -3
  40. data/spec/lib/castle/utils/cloner_spec.rb +1 -0
  41. data/spec/lib/castle/utils/timestamp_spec.rb +3 -4
  42. data/spec/lib/castle/utils_spec.rb +1 -1
  43. data/spec/lib/castle/validators/not_supported_spec.rb +1 -3
  44. data/spec/spec_helper.rb +1 -2
  45. metadata +38 -10
  46. data/lib/castle/api/request/build.rb +0 -27
  47. data/lib/castle/header_formatter.rb +0 -9
  48. data/spec/lib/castle/api/request/build_spec.rb +0 -44
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ ENV['RAILS_ENV'] = 'test'
4
+ require_relative 'application'
5
+ require_relative 'home_controller'
6
+ require 'rspec/rails'
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'action_controller/railtie'
4
+
5
+ class TestApp < Rails::Application
6
+ secrets.secret_token = 'secret_token'
7
+ secrets.secret_key_base = 'secret_key_base'
8
+
9
+ config.logger = Logger.new($stdout)
10
+ Rails.logger = config.logger
11
+
12
+ routes.draw do
13
+ get '/' => 'home#index'
14
+ end
15
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ class HomeController < ActionController::Base
4
+ def index
5
+ request_context = ::Castle::Client.to_context(request)
6
+ track_options = ::Castle::Client.to_options(
7
+ event: '$login.succeeded',
8
+ user_id: '123',
9
+ properties: {
10
+ key: 'value'
11
+ },
12
+ user_traits: {
13
+ key: 'value'
14
+ }
15
+ )
16
+ client = ::Castle::Client.new(request_context)
17
+ client.track(track_options)
18
+
19
+ render inline: 'hello'
20
+ end
21
+ end
@@ -4,56 +4,69 @@ describe Castle::API::Request do
4
4
  describe '#call' do
5
5
  subject(:call) { described_class.call(command, api_secret, headers) }
6
6
 
7
+ let(:session) { instance_double('Castle::API::Session') }
7
8
  let(:http) { instance_double('Net::HTTP') }
8
- let(:request_build) { instance_double('Castle::API::Request::Build') }
9
9
  let(:command) { Castle::Commands::Track.new({}).build(event: '$login.succeeded') }
10
10
  let(:headers) { {} }
11
11
  let(:api_secret) { 'secret' }
12
+ let(:request_build) { {} }
12
13
  let(:expected_headers) { { 'Content-Type' => 'application/json' } }
13
14
 
14
15
  before do
15
- allow(described_class).to receive(:http).and_return(http)
16
- allow(http).to receive(:request).with(request_build)
17
- allow(Castle::API::Request::Build).to receive(:call)
18
- .with(command, expected_headers, api_secret)
19
- .and_return(request_build)
16
+ allow(Castle::API::Session).to receive(:instance).and_return(session)
17
+ allow(session).to receive(:http).and_return(http)
18
+ allow(http).to receive(:request)
19
+ allow(described_class).to receive(:build).and_return(request_build)
20
20
  call
21
21
  end
22
22
 
23
23
  it do
24
- expect(Castle::API::Request::Build).to have_received(:call)
25
- .with(command, expected_headers, api_secret)
24
+ expect(described_class).to have_received(:build).with(command, expected_headers, api_secret)
26
25
  end
26
+
27
27
  it { expect(http).to have_received(:request).with(request_build) }
28
28
  end
29
29
 
30
- describe '#http' do
31
- subject(:http) { described_class.http }
30
+ describe '#build' do
31
+ subject(:build) { described_class.build(command, headers, api_secret) }
32
32
 
33
- context 'when ssl false' do
34
- before do
35
- Castle.config.host = 'localhost'
36
- Castle.config.port = 3002
37
- end
33
+ let(:headers) { { 'SAMPLE-HEADER' => '1' } }
34
+ let(:api_secret) { 'secret' }
38
35
 
39
- after do
40
- Castle.config.host = Castle::Configuration::HOST
41
- Castle.config.port = Castle::Configuration::PORT
42
- end
36
+ context 'when get' do
37
+ let(:command) { Castle::Commands::Review.build(review_id) }
38
+ let(:review_id) { SecureRandom.uuid }
43
39
 
44
- it { expect(http).to be_instance_of(Net::HTTP) }
45
- it { expect(http.address).to eq(Castle.config.host) }
46
- it { expect(http.port).to eq(Castle.config.port) }
47
- it { expect(http.use_ssl?).to be false }
48
- it { expect(http.verify_mode).to be_nil }
40
+ it { expect(build.body).to be_nil }
41
+ it { expect(build.method).to eql('GET') }
42
+ it { expect(build.path).to eql("/v1/#{command.path}") }
43
+ it { expect(build.to_hash).to have_key('authorization') }
44
+ it { expect(build.to_hash).to have_key('sample-header') }
45
+ it { expect(build.to_hash['sample-header']).to eql(['1']) }
49
46
  end
50
47
 
51
- context 'when ssl true' do
52
- it { expect(http).to be_instance_of(Net::HTTP) }
53
- it { expect(http.address).to eq(Castle.config.host) }
54
- it { expect(http.port).to eq(Castle.config.port) }
55
- it { expect(http.use_ssl?).to be true }
56
- it { expect(http.verify_mode).to eq(OpenSSL::SSL::VERIFY_PEER) }
48
+ context 'when post' do
49
+ let(:time) { Time.now.utc.iso8601(3) }
50
+ let(:command) do
51
+ Castle::Commands::Track.new({}).build(event: '$login.succeeded', name: "\xC4")
52
+ end
53
+ let(:expected_body) do
54
+ {
55
+ event: '$login.succeeded',
56
+ name: '�',
57
+ context: {},
58
+ sent_at: time
59
+ }
60
+ end
61
+
62
+ before { allow(Castle::Utils::Timestamp).to receive(:call).and_return(time) }
63
+
64
+ it { expect(build.body).to be_eql(expected_body.to_json) }
65
+ it { expect(build.method).to eql('POST') }
66
+ it { expect(build.path).to eql("/v1/#{command.path}") }
67
+ it { expect(build.to_hash).to have_key('authorization') }
68
+ it { expect(build.to_hash).to have_key('sample-header') }
69
+ it { expect(build.to_hash['sample-header']).to eql(['1']) }
57
70
  end
58
71
  end
59
72
  end
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe Castle::API::Session do
4
+ describe '#get' do
5
+ it { expect(described_class.get).to eql(described_class.get) }
6
+ it { expect(described_class.get).to eql(described_class.instance.http) }
7
+ end
8
+
9
+ describe '#initialize' do
10
+ subject(:session) { described_class.get }
11
+
12
+ after do
13
+ described_class.instance.reset
14
+ end
15
+
16
+ context 'when ssl false' do
17
+ before do
18
+ Castle.config.host = 'localhost'
19
+ Castle.config.port = 3002
20
+ described_class.instance.reset
21
+ end
22
+
23
+ after do
24
+ Castle.config.host = Castle::Configuration::HOST
25
+ Castle.config.port = Castle::Configuration::PORT
26
+ end
27
+
28
+ it { expect(session).to be_instance_of(Net::HTTP) }
29
+ it { expect(session.address).to eq('localhost') }
30
+ it { expect(session.port).to eq(3002) }
31
+ it { expect(session.use_ssl?).to be false }
32
+ it { expect(session.verify_mode).to be_nil }
33
+ end
34
+
35
+ context 'when ssl true' do
36
+ before do
37
+ described_class.instance.reset
38
+ end
39
+
40
+ it { expect(session).to be_instance_of(Net::HTTP) }
41
+ it { expect(session.address).to eq(Castle.config.host) }
42
+ it { expect(session.port).to eq(Castle.config.port) }
43
+ it { expect(session.use_ssl?).to be true }
44
+ it { expect(session.verify_mode).to eq(OpenSSL::SSL::VERIFY_PEER) }
45
+ end
46
+ end
47
+ end
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  describe Castle::API do
4
- subject(:request) { described_class.request(command) }
4
+ subject(:call) { described_class.call(command) }
5
5
 
6
6
  let(:command) { Castle::Commands::Track.new({}).build(event: '$login.succeeded') }
7
7
 
@@ -10,7 +10,7 @@ describe Castle::API do
10
10
 
11
11
  it do
12
12
  expect do
13
- request
13
+ call
14
14
  end.to raise_error(Castle::RequestError)
15
15
  end
16
16
  end
@@ -20,7 +20,7 @@ describe Castle::API do
20
20
 
21
21
  it do
22
22
  expect do
23
- request
23
+ call
24
24
  end.to raise_error(Castle::BadRequestError)
25
25
  end
26
26
  end
@@ -30,7 +30,7 @@ describe Castle::API do
30
30
 
31
31
  it do
32
32
  expect do
33
- request
33
+ call
34
34
  end.to raise_error(Castle::ConfigurationError)
35
35
  end
36
36
  end
@@ -244,11 +244,13 @@ describe Castle::Client do
244
244
  it { expect(request_response[:action]).to be_eql('allow') }
245
245
  it { expect(request_response[:user_id]).to be_eql('1234') }
246
246
  it { expect(request_response[:failover]).to be true }
247
- it { expect(request_response[:failover_reason]).to be_eql('Castle set to do not track.') }
247
+ it { expect(request_response[:failover_reason]).to be_eql('Castle is set to do not track.') }
248
248
  end
249
249
 
250
250
  context 'when request with fail' do
251
- before { allow(Castle::API).to receive(:request).and_raise(Castle::RequestError.new(Timeout::Error)) }
251
+ before do
252
+ allow(Castle::API).to receive(:request).and_raise(Castle::RequestError.new(Timeout::Error))
253
+ end
252
254
 
253
255
  context 'with request error and throw strategy' do
254
256
  before { allow(Castle.config).to receive(:failover_strategy).and_return(:throw) }
@@ -274,7 +276,7 @@ describe Castle::Client do
274
276
  it { expect { request_response }.to raise_error(Castle::InternalServerError) }
275
277
  end
276
278
 
277
- context 'not throw on eg deny strategy' do
279
+ describe 'not throw on eg deny strategy' do
278
280
  it { assert_not_requested :post, 'https://:secret@api.castle.io/v1/authenticate' }
279
281
  it { expect(request_response[:action]).to be_eql('allow') }
280
282
  it { expect(request_response[:user_id]).to be_eql('1234') }
@@ -10,6 +10,7 @@ describe Castle::Commands::Authenticate do
10
10
  let(:time_auto) { time_now.utc.iso8601(3) }
11
11
 
12
12
  before { Timecop.freeze(time_now) }
13
+
13
14
  after { Timecop.return }
14
15
 
15
16
  describe '.build' do
@@ -10,6 +10,7 @@ describe Castle::Commands::Identify do
10
10
  let(:time_auto) { time_now.utc.iso8601(3) }
11
11
 
12
12
  before { Timecop.freeze(time_now) }
13
+
13
14
  after { Timecop.return }
14
15
 
15
16
  describe '.build' do
@@ -11,6 +11,7 @@ describe Castle::Commands::Impersonate do
11
11
  let(:time_auto) { time_now.utc.iso8601(3) }
12
12
 
13
13
  before { Timecop.freeze(time_now) }
14
+
14
15
  after { Timecop.return }
15
16
 
16
17
  describe '.build' do
@@ -10,6 +10,7 @@ describe Castle::Commands::Track do
10
10
  let(:time_auto) { time_now.utc.iso8601(3) }
11
11
 
12
12
  before { Timecop.freeze(time_now) }
13
+
13
14
  after { Timecop.return }
14
15
 
15
16
  describe '#build' do
@@ -2,7 +2,7 @@
2
2
 
3
3
  describe Castle::Configuration do
4
4
  subject(:config) do
5
- described_class.new
5
+ described_class.instance
6
6
  end
7
7
 
8
8
  describe 'host' do
@@ -31,14 +31,26 @@ describe Castle::Configuration do
31
31
 
32
32
  describe 'api_secret' do
33
33
  context 'with env' do
34
+ let(:secret_key_env) { 'secret_key_env' }
35
+ let(:secret_key) { 'secret_key' }
36
+
34
37
  before do
35
38
  allow(ENV).to receive(:fetch).with(
36
39
  'CASTLE_API_SECRET', ''
37
- ).and_return('secret_key')
40
+ ).and_return(secret_key_env)
41
+ config.reset
38
42
  end
39
43
 
40
44
  it do
41
- expect(config.api_secret).to be_eql('secret_key')
45
+ expect(config.api_secret).to be_eql(secret_key_env)
46
+ end
47
+
48
+ context 'when key is overwritten' do
49
+ before { config.api_secret = secret_key }
50
+
51
+ it do
52
+ expect(config.api_secret).to be_eql(secret_key)
53
+ end
42
54
  end
43
55
  end
44
56
 
@@ -48,13 +60,14 @@ describe Castle::Configuration do
48
60
  before do
49
61
  config.api_secret = value
50
62
  end
63
+
51
64
  it do
52
65
  expect(config.api_secret).to be_eql(value)
53
66
  end
54
67
  end
55
68
 
56
69
  it do
57
- expect(config.api_secret).to be_eql('')
70
+ expect(config.api_secret).to be_eql('secret')
58
71
  end
59
72
  end
60
73
 
@@ -69,6 +82,7 @@ describe Castle::Configuration do
69
82
  before do
70
83
  config.request_timeout = value
71
84
  end
85
+
72
86
  it do
73
87
  expect(config.request_timeout).to be_eql(value)
74
88
  end
@@ -84,6 +98,7 @@ describe Castle::Configuration do
84
98
  before do
85
99
  config.whitelisted = ['header']
86
100
  end
101
+
87
102
  it do
88
103
  expect(config.whitelisted).to be_eql(['Header'])
89
104
  end
@@ -99,6 +114,7 @@ describe Castle::Configuration do
99
114
  before do
100
115
  config.blacklisted = ['header']
101
116
  end
117
+
102
118
  it do
103
119
  expect(config.blacklisted).to be_eql(['Header'])
104
120
  end
@@ -114,6 +130,7 @@ describe Castle::Configuration do
114
130
  before do
115
131
  config.failover_strategy = :deny
116
132
  end
133
+
117
134
  it do
118
135
  expect(config.failover_strategy).to be_eql(:deny)
119
136
  end
@@ -4,37 +4,37 @@ describe Castle::Context::Default do
4
4
  subject { described_class.new(request, nil) }
5
5
 
6
6
  let(:ip) { '1.2.3.4' }
7
- let(:cookie_id) { 'abcd' }
7
+ let(:client_id) { 'abcd' }
8
8
 
9
9
  let(:env) do
10
10
  Rack::MockRequest.env_for('/',
11
11
  'HTTP_X_FORWARDED_FOR' => ip,
12
12
  'HTTP_ACCEPT_LANGUAGE' => 'en',
13
13
  'HTTP_USER_AGENT' => 'test',
14
- 'HTTP_COOKIE' => "__cid=#{cookie_id};other=efgh")
14
+ 'HTTP_COOKIE' => "__cid=#{client_id};other=efgh")
15
15
  end
16
16
  let(:request) { Rack::Request.new(env) }
17
17
  let(:default_context) { subject.call }
18
18
  let(:version) { '2.2.0' }
19
-
20
- before do
21
- stub_const('Castle::VERSION', version)
22
- end
23
-
24
- it { expect(default_context[:active]).to be_eql(true) }
25
- it { expect(default_context[:origin]).to be_eql('web') }
26
-
27
- it do
28
- expect(default_context[:headers]).to be_eql(
19
+ let(:result_headers) do
20
+ {
29
21
  'X-Forwarded-For' => '1.2.3.4',
30
22
  'Accept-Language' => 'en',
31
23
  'User-Agent' => 'test',
32
24
  'Content-Length' => '0',
33
25
  'Cookie' => true
34
- )
26
+ }
35
27
  end
36
28
 
29
+ before do
30
+ stub_const('Castle::VERSION', version)
31
+ end
32
+
33
+ it { expect(default_context[:active]).to be_eql(true) }
34
+ it { expect(default_context[:origin]).to be_eql('web') }
35
+ it { expect(default_context[:headers]).to be_eql(result_headers) }
37
36
  it { expect(default_context[:ip]).to be_eql(ip) }
37
+ it { expect(default_context[:client_id]).to be_eql(client_id) }
38
38
  it { expect(default_context[:library][:name]).to be_eql('castle-rb') }
39
39
  it { expect(default_context[:library][:version]).to be_eql(version) }
40
40
  it { expect(default_context[:user_agent]).to be_eql('test') }
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe Castle::Events do
4
+ it { expect(described_class::LOGIN_SUCCEEDED).to eq('$login.succeeded') }
5
+ end
@@ -1,8 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  describe Castle::Extractors::ClientId do
4
- subject(:extractor) { described_class.new(request, cookies) }
4
+ subject(:extractor) { described_class.new(formatted_headers, cookies) }
5
5
 
6
+ let(:formatted_headers) { Castle::HeadersFilter.new(request).call }
6
7
  let(:client_id_cookie) { 'abcd' }
7
8
  let(:client_id_header) { 'abcde' }
8
9
  let(:cookies) { request.cookies }
@@ -1,78 +1,94 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  describe Castle::Extractors::Headers do
4
- subject(:headers) { described_class.new(request).call }
5
-
6
- let(:client_id) { 'abcd' }
7
- let(:env) do
8
- result = Rack::MockRequest.env_for(
9
- '/',
10
- 'Action-Dispatch.request.content-Type' => 'application/json',
11
- 'HTTP_AUTHORIZATION' => 'Basic 123456',
12
- 'HTTP_COOKIE' => "__cid=#{client_id};other=efgh",
13
- 'HTTP_ACCEPT' => 'application/json',
14
- 'HTTP_X_FORWARDED_FOR' => '1.2.3.4',
15
- 'HTTP_USER_AGENT' => 'Mozilla 1234',
16
- 'TEST' => '1'
17
- )
18
- result[:HTTP_OK] = 'OK'
19
- result
4
+ subject(:headers) { described_class.new(formatted_headers).call }
5
+
6
+ let(:formatted_headers) do
7
+ {
8
+ 'Content-Length' => '0',
9
+ 'Authorization' => 'Basic 123456',
10
+ 'Cookie' => '__cid=abcd;other=efgh',
11
+ 'Ok' => 'OK',
12
+ 'Accept' => 'application/json',
13
+ 'X-Forwarded-For' => '1.2.3.4',
14
+ 'User-Agent' => 'Mozilla 1234'
15
+ }
16
+ end
17
+
18
+ after do
19
+ Castle.config.whitelisted = %w[]
20
+ Castle.config.blacklisted = %w[]
20
21
  end
21
- let(:request) { Rack::Request.new(env) }
22
22
 
23
23
  context 'when whitelist is not set in the configuration' do
24
- it do
25
- is_expected.to eq('Accept' => 'application/json',
26
- 'Authorization' => true,
27
- 'Cookie' => true,
28
- 'Content-Length' => '0',
29
- 'Ok' => 'OK',
30
- 'User-Agent' => 'Mozilla 1234',
31
- 'X-Forwarded-For' => '1.2.3.4')
24
+ let(:result) do
25
+ {
26
+ 'Accept' => 'application/json',
27
+ 'Authorization' => true,
28
+ 'Cookie' => true,
29
+ 'Content-Length' => '0',
30
+ 'Ok' => 'OK',
31
+ 'User-Agent' => 'Mozilla 1234',
32
+ 'X-Forwarded-For' => '1.2.3.4'
33
+ }
32
34
  end
35
+
36
+ it { expect(headers).to eq(result) }
33
37
  end
34
38
 
35
39
  context 'when whitelist is set in the configuration' do
36
40
  before { Castle.config.whitelisted = %w[Accept OK] }
37
41
 
38
- it do
39
- is_expected.to eq('Accept' => 'application/json',
40
- 'Authorization' => true,
41
- 'Cookie' => true,
42
- 'Content-Length' => true,
43
- 'Ok' => 'OK',
44
- 'User-Agent' => 'Mozilla 1234',
45
- 'X-Forwarded-For' => true)
42
+ let(:result) do
43
+ {
44
+ 'Accept' => 'application/json',
45
+ 'Authorization' => true,
46
+ 'Cookie' => true,
47
+ 'Content-Length' => true,
48
+ 'Ok' => 'OK',
49
+ 'User-Agent' => 'Mozilla 1234',
50
+ 'X-Forwarded-For' => true
51
+ }
46
52
  end
53
+
54
+ it { expect(headers).to eq(result) }
47
55
  end
48
56
 
49
57
  context 'when blacklist is set in the configuration' do
50
58
  context 'with a User-Agent' do
59
+ let(:result) do
60
+ {
61
+ 'Accept' => 'application/json',
62
+ 'Authorization' => true,
63
+ 'Cookie' => true,
64
+ 'Content-Length' => '0',
65
+ 'Ok' => 'OK',
66
+ 'User-Agent' => 'Mozilla 1234',
67
+ 'X-Forwarded-For' => '1.2.3.4'
68
+ }
69
+ end
70
+
51
71
  before { Castle.config.blacklisted = %w[User-Agent] }
52
72
 
53
- it do
54
- is_expected.to eq('Accept' => 'application/json',
55
- 'Authorization' => true,
56
- 'Cookie' => true,
57
- 'Content-Length' => '0',
58
- 'Ok' => 'OK',
59
- 'User-Agent' => 'Mozilla 1234',
60
- 'X-Forwarded-For' => '1.2.3.4')
61
- end
73
+ it { expect(headers).to eq(result) }
62
74
  end
63
75
 
64
76
  context 'with a different header' do
77
+ let(:result) do
78
+ {
79
+ 'Accept' => true,
80
+ 'Authorization' => true,
81
+ 'Cookie' => true,
82
+ 'Content-Length' => '0',
83
+ 'Ok' => 'OK',
84
+ 'User-Agent' => 'Mozilla 1234',
85
+ 'X-Forwarded-For' => '1.2.3.4'
86
+ }
87
+ end
88
+
65
89
  before { Castle.config.blacklisted = %w[Accept] }
66
90
 
67
- it do
68
- is_expected.to eq('Accept' => true,
69
- 'Authorization' => true,
70
- 'Cookie' => true,
71
- 'Content-Length' => '0',
72
- 'Ok' => 'OK',
73
- 'User-Agent' => 'Mozilla 1234',
74
- 'X-Forwarded-For' => '1.2.3.4')
75
- end
91
+ it { expect(headers).to eq(result) }
76
92
  end
77
93
  end
78
94