tshield 0.13.0.0 → 0.13.5.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: caa9310473bc1479ad6bc7db7ae67938b269bbd7
4
- data.tar.gz: 34de8d7084f0eecb054f2b07b9950ef0dffbf32b
2
+ SHA256:
3
+ metadata.gz: ab5c5057fe81ae295f572912c6955ce0ea0bd9be6b42fb515a7832fe3451459a
4
+ data.tar.gz: 9c785dc23adb245fdfcc416698c551f7a45eaa32b5892a2cabea708f16fa2859
5
5
  SHA512:
6
- metadata.gz: 41afa4ac6a4471ea700beaa32ddf4c664f7eeb4f7a61639853b883a5ee0b6dd8f4262f9e14198a186e89cece5bb158669587a00f80dc7bef6bb460a5f6f7c5a3
7
- data.tar.gz: ef52b07f2bfc68d8ff0561c0676350493da7b7f16b26f1e61687f13a78929e4ec9659859a396dcb6bb51d5eab8c041cc15cbb2ca92fcecc8a5ed768101a2a7bd
6
+ metadata.gz: 58fd33ddf9e466af5882e6522612b2b0fa05c95f728578fe50b014dca0777357bf5ccfa17605a86309c5742cb828dd2e52eb9bb2839096f594e1e75fef80e81b
7
+ data.tar.gz: f085f1dcc7a3d861da1b28a0d07f3338f03dd5b27cdd234c283cecf0bce8a0dc66f26193755ea8f5b442cbf4953fb2bd4ce295f90257b76121ac7fdbcbdd38b0
data/README.md CHANGED
@@ -3,9 +3,10 @@ TShield
3
3
 
4
4
  [![Build Status](https://travis-ci.org/diegorubin/tshield.svg)](https://travis-ci.org/diegorubin/tshield)
5
5
  [![Coverage Status](https://coveralls.io/repos/github/diegorubin/tshield/badge.svg?branch=master)](https://coveralls.io/github/diegorubin/tshield?branch=master)
6
- [![SourceLevel](https://app.sourcelevel.io/github/diegorubin/tshield.svg)](https://app.sourcelevel.io/github/diegorubin/tshield)
6
+ [![SourceLevel](https://app.sourcelevel.io/github/diegorubin/-/tshield.svg)](https://app.sourcelevel.io/github/diegorubin/-/tshield)
7
7
  [![Join the chat at https://gitter.im/diegorubin/tshield](https://badges.gitter.im/diegorubin/tshield.svg)](https://gitter.im/diegorubin/tshield?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
8
8
  [![Gem Version](https://badge.fury.io/rb/tshield.svg)](https://badge.fury.io/rb/tshield)
9
+ ![TShield Publish](https://github.com/diegorubin/tshield/workflows/TShield%20Publish/badge.svg)
9
10
 
10
11
  ## API mocks for development and testing
11
12
  TShield is an open source proxy for mocks API responses.
@@ -191,6 +192,7 @@ domains:
191
192
  headers:
192
193
  HTTP_AUTHORIZATION: Authorization
193
194
  HTTP_COOKIE: Cookie
195
+ send_header_content_type: true
194
196
  not_save_headers:
195
197
  - transfer-encoding
196
198
  cache_request: <<value>>
@@ -234,6 +236,7 @@ domains:
234
236
  * Define Base URI of service
235
237
  * **name**: Name to identify the domain in the generated files
236
238
  * **headers**: github-issue #17
239
+ * **send_header_content_type**: Boolean domain config to send header 'Content-Type' when requesting this domain
237
240
  * **not_save_headers**: List of headers that should be ignored in generated file
238
241
  * **skip_query_params**: List of query params that should be ignored in generated file
239
242
  * **cache_request**: <<some_description>>
@@ -65,6 +65,10 @@ module TShield
65
65
  nil
66
66
  end
67
67
 
68
+ def windows_compatibility?
69
+ windows_compatibility || false
70
+ end
71
+
68
72
  def get_headers(domain)
69
73
  (domains[domain] || {})['headers'] || {}
70
74
  end
@@ -100,12 +104,13 @@ module TShield
100
104
  domains[domain]['not_save_headers'] || []
101
105
  end
102
106
 
103
- def read_session_path
104
- session_path || '/sessions'
107
+ def send_header_content_type(domain)
108
+ return domains[domain]['send_header_content_type'] != false if domains[domain]
109
+ true
105
110
  end
106
111
 
107
- def get_questionmark_char
108
- windows_compatibility ? '%3f' : '?'
112
+ def read_session_path
113
+ session_path || '/sessions'
109
114
  end
110
115
 
111
116
  def grpc
@@ -57,6 +57,8 @@ module TShield
57
57
  ip: request.ip
58
58
  }
59
59
 
60
+ treat_headers_by_domain(options, path)
61
+
60
62
  if %w[POST PUT PATCH].include? method
61
63
  result = request.body.read.encode('UTF-8',
62
64
  invalid: :replace,
@@ -74,7 +76,7 @@ module TShield
74
76
  configuration.get_excluded_headers(domain(path)).include?(key)
75
77
  end
76
78
  end
77
-
79
+
78
80
  logger.info(
79
81
  "original=#{api_response.original} method=#{method} path=#{path} "\
80
82
  "content-type=#{request_content_type} "\
@@ -94,6 +96,11 @@ module TShield
94
96
  end
95
97
  end
96
98
 
99
+ def treat_headers_by_domain(options, path)
100
+ @send_header_content_type = configuration.send_header_content_type(domain(path))
101
+ options[:headers].delete('Content-Type') unless @send_header_content_type
102
+ end
103
+
97
104
  def configuration
98
105
  @configuration ||= TShield::Configuration.singleton
99
106
  end
@@ -1,10 +1,14 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'tshield/configuration'
3
4
  require 'tshield/sessions'
4
5
 
5
6
  module TShield
6
7
  module Grpc
7
8
  module VCR
9
+ def initialize
10
+ @configuration = TShield::Configuration.singleton
11
+ end
8
12
  def handler_in_vcr_mode(method_name, request, parameters, options)
9
13
  parameters.peer =~ /ipv6:\[(.+?)\]|ipv4:(.+?):/
10
14
  peer = Regexp.last_match(1) || Regexp.last_match(2)
@@ -16,6 +20,7 @@ module TShield
16
20
  module_name = options['module']
17
21
 
18
22
  path = create_destiny(module_name, method_name, request)
23
+ save_request(path, request)
19
24
  response = saved_response(path)
20
25
  if response
21
26
  TShield.logger.info("returning saved response for request #{request.to_json} saved into #{hexdigest(request)}")
@@ -26,10 +31,14 @@ module TShield
26
31
  client_class = Object.const_get("#{module_name}::Stub")
27
32
  client_instance = client_class.new(options['hostname'], :this_channel_is_insecure)
28
33
  response = client_instance.send(method_name, request)
29
- save_request_and_response(path, request, response)
34
+ save_response(path, response)
30
35
  response
31
36
  end
32
37
 
38
+ def encode_colon(value)
39
+ value.gsub(':','%3a')
40
+ end
41
+
33
42
  def saved_response(path)
34
43
  response_file = File.join(path, 'response')
35
44
  return false unless File.exist? response_file
@@ -39,11 +48,6 @@ module TShield
39
48
  Kernel.const_get(response_class).new(content)
40
49
  end
41
50
 
42
- def save_request_and_response(path, request, response)
43
- save_request(path, request)
44
- save_response(path, response)
45
- end
46
-
47
51
  def save_request(path, request)
48
52
  file = File.open(File.join(path, 'original_request'), 'w')
49
53
  file.puts request.to_json
@@ -62,6 +66,7 @@ module TShield
62
66
 
63
67
  def complete_path(module_name, method_name, request)
64
68
  @session_name = (@session || {})[:name]
69
+ module_name = @configuration.windows_compatibility? ? encode_colon(module_name) : module_name
65
70
  path = ['requests', 'grpc', @session_name, module_name, method_name.to_s, hexdigest(request)].compact
66
71
  path
67
72
  end
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'tshield/logger'
3
4
  require 'tshield/matching/filters'
4
5
  require 'tshield/request'
5
6
 
@@ -59,15 +60,38 @@ module TShield
59
60
  end
60
61
 
61
62
  def load_stub(file)
62
- content = JSON.parse File.open(file).read
63
+ content = read_stub_file(file)
63
64
  content.each do |stub|
64
- stub_session_name = init_stub_session(stub)
65
+ next unless valid_stub?(file, stub)
65
66
 
66
- if stub['stubs']
67
- load_items(stub['stubs'] || [], stub_session_name)
68
- else
69
- load_item(stub, stub_session_name)
70
- end
67
+ load_valid_stub(stub)
68
+ end
69
+ end
70
+
71
+ def read_stub_file(file)
72
+ JSON.parse File.open(file).read
73
+ rescue StandardError
74
+ TShield.logger.error "error in loading matching file #{file}"
75
+ []
76
+ end
77
+
78
+ def valid_stub?(file, stub)
79
+ is_valid = stub.is_a?(Hash) && mandatory_attributes?(stub)
80
+ TShield.logger.info "loading matching file #{file}" if is_valid
81
+ is_valid
82
+ end
83
+
84
+ def mandatory_attributes?(stub)
85
+ (stub['method'] && stub['path'] && stub['response']) || (stub['session'] && stub['stubs'])
86
+ end
87
+
88
+ def load_valid_stub(stub)
89
+ stub_session_name = init_stub_session(stub)
90
+
91
+ if stub['stubs']
92
+ load_items(stub['stubs'] || [], stub_session_name)
93
+ else
94
+ load_item(stub, stub_session_name)
71
95
  end
72
96
  end
73
97
 
@@ -78,12 +78,31 @@ module TShield
78
78
  @method ||= @options[:method].downcase
79
79
  end
80
80
 
81
+ def apply_set_cookie_header_values(raw_response, headers = {})
82
+
83
+ headers_clone = headers.clone
84
+
85
+ field = raw_response.get_fields('Set-Cookie')
86
+
87
+ if !field.nil? && !field.empty?
88
+ cookies_values = []
89
+ field.each { |value| cookies_values.push(value) }
90
+ headers_clone['Set-Cookie'] = cookies_values
91
+ end
92
+
93
+ headers_clone
94
+ end
95
+
81
96
  def save(raw_response)
82
97
  headers = {}
98
+
83
99
  raw_response.headers.each do |k, v|
100
+ next if k == 'set-cookie'
84
101
  headers[k] = v unless configuration.not_save_headers(domain).include? k
85
102
  end
86
103
 
104
+ headers = apply_set_cookie_header_values(raw_response, headers)
105
+
87
106
  content = {
88
107
  body: raw_response.body,
89
108
  status: raw_response.code,
@@ -136,14 +155,23 @@ module TShield
136
155
  content[:body] = body
137
156
  end
138
157
 
158
+ def encode_for_windows_dir(directory)
159
+ replace = [['<','%3c'],['>','%3e'],[':','%3a'],['"','%22'],['?','%3f'],[' ','%20'],['*','%2a'],['/','%2f']]
160
+ replace.each do |value|
161
+ directory = directory.gsub(value.first,value.last)
162
+ end
163
+ directory
164
+ end
165
+
139
166
  def safe_dir(url)
140
167
  if url.size > 225
141
168
  path = url.gsub(/(\?.*)/, '')
142
169
  params = Digest::SHA1.hexdigest Regexp.last_match(1)
143
- "#{path.gsub(%r{/}, '-').gsub(/^-/, '')}#{configuration.get_questionmark_char}#{params}"
170
+ directory = "#{path.gsub(%r{/}, '-').gsub(/^-/, '')}?#{params}"
144
171
  else
145
- url.gsub(%r{/}, '-').gsub(/^-/, '').gsub('?', configuration.get_questionmark_char)
172
+ directory = url.gsub(%r{/}, '-').gsub(/^-/, '')
146
173
  end
174
+ configuration.windows_compatibility? ? encode_for_windows_dir(directory) : directory
147
175
  end
148
176
  end
149
177
  end
@@ -29,9 +29,9 @@ module TShield
29
29
 
30
30
  options '*' do
31
31
  response.headers['Allow'] = 'GET, PUT, POST, DELETE, OPTIONS'
32
- response.headers['Access-Control-Allow-Headers'] = 'Authorization, Content-Type,
33
- Accept, X-User-Email, X-Auth-Token'
32
+ response.headers['Access-Control-Allow-Headers'] = '*'
34
33
  response.headers['Access-Control-Allow-Origin'] = '*'
34
+ response.headers['Access-Control-Allow-Methods'] = '*'
35
35
  200
36
36
  end
37
37
 
@@ -5,7 +5,7 @@ module TShield
5
5
  class Version
6
6
  MAJOR = 0
7
7
  MINOR = 13
8
- PATCH = 0
8
+ PATCH = 5
9
9
  PRE = 0
10
10
 
11
11
  class << self
data/spec/spec_helper.rb CHANGED
@@ -1,7 +1,9 @@
1
1
  # frozen_string_literal: false
2
2
 
3
- require 'coveralls'
4
- Coveralls.wear!
3
+ if ENV['COVERALLS_REPO_TOKEN']
4
+ require 'coveralls'
5
+ Coveralls.wear!
6
+ end
5
7
 
6
8
  require 'bundler/setup'
7
9
  Bundler.setup
@@ -71,7 +71,7 @@ describe TShield::Configuration do
71
71
  TShield::Configuration.clear
72
72
  @configuration = TShield::Configuration.singleton
73
73
 
74
- expect(@configuration.get_questionmark_char).to eq('%3f')
74
+ expect(@configuration.windows_compatibility?).to eq(true)
75
75
  end
76
76
 
77
77
  it 'should be compatible with Unix when configuration is false' do
@@ -79,7 +79,7 @@ describe TShield::Configuration do
79
79
  TShield::Configuration.clear
80
80
  @configuration = TShield::Configuration.singleton
81
81
 
82
- expect(@configuration.get_questionmark_char).to eq('?')
82
+ expect(@configuration.windows_compatibility?).to eq(false)
83
83
  end
84
84
 
85
85
  it 'should be compatible with Unix when configuration is missing' do
@@ -87,7 +87,7 @@ describe TShield::Configuration do
87
87
  TShield::Configuration.clear
88
88
  @configuration = TShield::Configuration.singleton
89
89
 
90
- expect(@configuration.get_questionmark_char).to eq('?')
90
+ expect(@configuration.windows_compatibility?).to eq(false)
91
91
  end
92
92
 
93
93
  end
@@ -108,14 +108,42 @@ describe TShield::Configuration do
108
108
 
109
109
  context 'on config exists without grpc entry' do
110
110
  before :each do
111
- options_instance = double
112
- allow(options_instance).to receive(:configuration_file)
113
- .and_return('spec/tshield/fixtures/config/tshield-without-grpc.yml')
114
- allow(TShield::Options).to receive(:instance).and_return(options_instance)
115
- @configuration = TShield::Configuration.singleton
111
+ @configuration = generate_configuration_from_file('spec/tshield/fixtures/config/tshield-without-grpc.yml')
112
+ TShield::Configuration.clear
116
113
  end
117
114
  it 'should set default value for port' do
118
115
  expect(@configuration.grpc).to eql('port' => 5678, 'proto_dir' => 'proto', 'services' => {})
119
116
  end
120
117
  end
118
+
119
+ context 'on config property request.domains.domain.send_header_content_type does not exists' do
120
+ before :each do
121
+ @configuration = generate_configuration_from_file('spec/tshield/fixtures/config/tshield-without-grpc.yml')
122
+ TShield::Configuration.clear
123
+ end
124
+ it 'should return send_header_content_type as true when property is not set' do
125
+ expect(@configuration.send_header_content_type('example.org')).to be true
126
+ end
127
+ end
128
+
129
+ context 'on config property request.domains.domain.send_header_content_type does exists' do
130
+ before :each do
131
+ TShield::Configuration.clear
132
+ end
133
+ it 'should return send_header_content_type as true when property is true' do
134
+ @configuration = generate_configuration_from_file('spec/tshield/fixtures/config/tshield-with-send-content-type-header.yml')
135
+ expect(@configuration.send_header_content_type('example.org')).to be true
136
+ end
137
+ it 'should return send_header_content_type as false when property is false' do
138
+ @configuration = generate_configuration_from_file('spec/tshield/fixtures/config/tshield-with-send-content-type-header_as_false.yml')
139
+ expect(@configuration.send_header_content_type('example.org')).to be false
140
+ end
141
+ end
142
+ end
143
+
144
+ def generate_configuration_from_file(file)
145
+ options_instance = double
146
+ allow(options_instance).to receive(:configuration_file).and_return(file)
147
+ allow(TShield::Options).to receive(:instance).and_return(options_instance)
148
+ TShield::Configuration.singleton
121
149
  end
@@ -58,3 +58,95 @@ describe TShield::Controllers::Requests do
58
58
  end
59
59
  end
60
60
  end
61
+
62
+ describe TShield::Controllers::Requests do
63
+ before :each do
64
+ @configuration = double
65
+ allow(TShield::Configuration)
66
+ .to receive(:singleton).and_return(@configuration)
67
+ allow(@configuration).to receive(:get_before_filters).and_return([])
68
+ allow(@configuration).to receive(:not_save_headers).and_return([])
69
+ allow(@configuration).to receive(:get_after_filters).and_return([])
70
+ allow(@configuration).to receive(:get_headers).and_return([])
71
+ allow(@configuration).to receive(:request).and_return('timeout' => 10)
72
+ allow(@configuration).to receive(:get_name).and_return('example.org')
73
+ allow(@configuration).to receive(:get_domain_for).and_return('example.org')
74
+ allow(@configuration).to receive(:get_delay).and_return(0)
75
+
76
+
77
+ allow(TShield::Options).to receive_message_chain(:instance, :break?)
78
+ @mock_logger = double
79
+ @controller = MockController.new(@mock_logger)
80
+ end
81
+ context 'when send_header_content_type is false for a single domain' do
82
+ it 'should remove application/json header when making a request' do
83
+ params = { 'captures' => ['/'] }
84
+ request = double
85
+ matcher = double
86
+ matched_response = double
87
+
88
+ allow(@configuration).to receive(:send_header_content_type).and_return(false)
89
+ allow(request).to receive(:request_method).and_return('GET')
90
+ allow(request).to receive(:content_type).and_return('application/json')
91
+ allow(request).to receive(:ip).and_return('0.0.0.0')
92
+ allow(request).to receive(:env).and_return('QUERY_STRING' => 'a=b')
93
+ allow(TShield::RequestMatching).to receive(:new).and_return(matcher)
94
+ allow(matcher).to receive(:match_request).and_return(nil)
95
+ allow(TShield::RequestVCR).to receive(:new).and_return(matcher)
96
+ allow(matcher).to receive(:vcr_response).and_return(matched_response)
97
+ allow(matched_response).to receive(:original).and_return(false)
98
+ allow(matched_response).to receive(:status).and_return(200)
99
+ allow(matched_response).to receive(:headers).and_return({})
100
+ allow(matched_response).to receive(:body).and_return('')
101
+ allow(@mock_logger).to receive(:info)
102
+
103
+ expect(TShield::RequestVCR).to receive(:new).with("/",{
104
+ call: 0,
105
+ headers: {},
106
+ ip: "0.0.0.0",
107
+ method: "GET",
108
+ raw_query: "a=b",
109
+ secondary_sessions: nil,
110
+ session: nil
111
+ })
112
+ @controller.treat(params, request, nil)
113
+ end
114
+ end
115
+
116
+ context 'when send_header_content_type is true for a single domain' do
117
+ it 'should NOT remove application/json header when making a request' do
118
+ params = { 'captures' => ['/'] }
119
+ request = double
120
+ matcher = double
121
+ matched_response = double
122
+
123
+ allow(@configuration).to receive(:send_header_content_type).and_return(true)
124
+ allow(request).to receive(:request_method).and_return('GET')
125
+ allow(request).to receive(:content_type).and_return('application/json')
126
+ allow(request).to receive(:ip).and_return('0.0.0.0')
127
+ allow(request).to receive(:env).and_return('QUERY_STRING' => 'a=b')
128
+ allow(TShield::RequestMatching).to receive(:new).and_return(matcher)
129
+ allow(matcher).to receive(:match_request).and_return(nil)
130
+ allow(TShield::RequestVCR).to receive(:new).and_return(matcher)
131
+ allow(matcher).to receive(:vcr_response).and_return(matched_response)
132
+ allow(matched_response).to receive(:original).and_return(false)
133
+ allow(matched_response).to receive(:status).and_return(200)
134
+ allow(matched_response).to receive(:headers).and_return({})
135
+ allow(matched_response).to receive(:body).and_return('')
136
+ allow(@mock_logger).to receive(:info)
137
+
138
+ expect(TShield::RequestVCR).to receive(:new).with("/",{
139
+ call: 0,
140
+ headers: {'Content-Type' => 'application/json'},
141
+ ip: "0.0.0.0",
142
+ method: "GET",
143
+ raw_query: "a=b",
144
+ secondary_sessions: nil,
145
+ session: nil
146
+ })
147
+
148
+
149
+ @controller.treat(params, request, nil)
150
+ end
151
+ end
152
+ end
@@ -0,0 +1,18 @@
1
+ ---
2
+ request:
3
+ timeout: 0
4
+ domains:
5
+ 'example.org':
6
+ name: 'example.org'
7
+ send_header_content_type: true
8
+ filters:
9
+ - 'ExampleFilter'
10
+ paths:
11
+ - '/api/one'
12
+ - '/api/two'
13
+ skip_query_params:
14
+ - 'a'
15
+ 'example.com':
16
+ name: 'example.com'
17
+ paths:
18
+ - '/api/three'
@@ -0,0 +1,18 @@
1
+ ---
2
+ request:
3
+ timeout: 0
4
+ domains:
5
+ 'example.org':
6
+ name: 'example.org'
7
+ send_header_content_type: false
8
+ filters:
9
+ - 'ExampleFilter'
10
+ paths:
11
+ - '/api/one'
12
+ - '/api/two'
13
+ skip_query_params:
14
+ - 'a'
15
+ 'example.com':
16
+ name: 'example.com'
17
+ paths:
18
+ - '/api/three'
@@ -36,6 +36,38 @@ describe TShield::RequestMatching do
36
36
  end
37
37
  end
38
38
 
39
+ context 'invalid matching file' do
40
+ before :each do
41
+ allow(Dir).to receive(:glob)
42
+ .and_return(['spec/tshield/fixtures/matching/invalid_matching_file.json'])
43
+ end
44
+
45
+ context 'on loading stubs' do
46
+ before :each do
47
+ @request_matching = TShield::RequestMatching.new('/')
48
+ end
49
+ it 'should stubs be empty' do
50
+ expect(@request_matching.class.stubs[DEFAULT_SESSION]).to be_nil
51
+ end
52
+ end
53
+ end
54
+
55
+ context 'empty matching file' do
56
+ before :each do
57
+ allow(Dir).to receive(:glob)
58
+ .and_return(['spec/tshield/fixtures/matching/empty.json'])
59
+ end
60
+
61
+ context 'on loading stubs' do
62
+ before :each do
63
+ @request_matching = TShield::RequestMatching.new('/')
64
+ end
65
+ it 'should stubs be empty' do
66
+ expect(@request_matching.class.stubs[DEFAULT_SESSION]).to be_nil
67
+ end
68
+ end
69
+ end
70
+
39
71
  context 'matching path' do
40
72
  before :each do
41
73
  allow(Dir).to receive(:glob)
@@ -10,6 +10,7 @@ describe TShield::RequestVCR do
10
10
  allow(TShield::Configuration)
11
11
  .to receive(:singleton).and_return(@configuration)
12
12
  allow(@configuration).to receive(:get_before_filters).and_return([])
13
+ allow(@configuration).to receive(:not_save_headers).and_return([])
13
14
  allow(@configuration).to receive(:get_after_filters).and_return([])
14
15
  allow(@configuration).to receive(:request).and_return('timeout' => 10)
15
16
  allow(@configuration).to receive(:get_domain_for).and_return('example.org')
@@ -35,6 +36,24 @@ describe TShield::RequestVCR do
35
36
  TShield::RequestVCR.new '/', method: 'GET'
36
37
  end
37
38
 
39
+ it 'should write response headers as multiple occcurences when has more than one with same key' do
40
+ allow_any_instance_of(TShield::RequestVCR).to receive(:exists)
41
+ .and_return(false)
42
+ allow_any_instance_of(TShield::RequestVCR).to receive(:destiny)
43
+ allow(HTTParty).to receive(:send).and_return(RawResponseCookiesMultipleValues.new)
44
+
45
+ write_spy = double
46
+ allow(File).to receive(:open).and_return(write_spy)
47
+
48
+ expect(write_spy).to receive(:write).ordered.with('this is the body')
49
+ expect(write_spy).to receive(:write)
50
+ .ordered
51
+ .with("{\n \"status\": 200,\n \"headers\": {\n \"Set-Cookie\": [\n \"FirstCookie=An Value\",\n \"SecondCookie=An Value\"\n ]\n }\n}")
52
+ allow(write_spy).to receive(:close)
53
+
54
+ TShield::RequestVCR.new '/', method: 'GET'
55
+ end
56
+
38
57
  describe 'and query params exists in list to skip' do
39
58
  before :each do
40
59
  allow(@configuration).to receive(:get_name).and_return('example.org')
@@ -62,7 +81,7 @@ describe TShield::RequestVCR do
62
81
  }
63
82
  )
64
83
 
65
- allow(@configuration).to receive(:get_questionmark_char).and_return('?')
84
+ allow(@configuration).to receive(:windows_compatibility?).and_return(false)
66
85
 
67
86
  allow(HTTParty).to receive(:send).and_return(RawResponse.new)
68
87
  file_double = double
@@ -87,14 +106,13 @@ describe TShield::RequestVCR do
87
106
  end
88
107
 
89
108
  it 'should create response directory in windows standard' do
90
-
91
109
  allow(@configuration).to receive(:domains).and_return(
92
110
  'example.org' => {
93
111
  'skip_query_params' => []
94
112
  }
95
113
  )
96
114
 
97
- allow(@configuration).to receive(:get_questionmark_char).and_return('%3f')
115
+ allow(@configuration).to receive(:windows_compatibility?).and_return(true)
98
116
 
99
117
  allow(HTTParty).to receive(:send).and_return(RawResponse.new)
100
118
  file_double = double
@@ -131,7 +149,6 @@ describe TShield::RequestVCR do
131
149
  call: 0
132
150
  end
133
151
 
134
-
135
152
  end
136
153
  end
137
154
 
@@ -144,8 +161,33 @@ describe TShield::RequestVCR do
144
161
  'this is the body'
145
162
  end
146
163
 
164
+ def get_fields(field = "")
165
+ []
166
+ end
167
+
168
+ def code
169
+ 200
170
+ end
171
+ end
172
+
173
+ class RawResponseCookiesMultipleValues
174
+ def headers
175
+ {'Set-Cookie' => ['FirstCookie=An Value', 'SecondCookie=An Value']}
176
+ end
177
+
178
+ def body
179
+ 'this is the body'
180
+ end
181
+
182
+ def get_fields(field = "")
183
+ self.headers[filed] unless self.headers.key?(field)
184
+ end
185
+
147
186
  def code
148
187
  200
149
188
  end
150
189
  end
190
+
151
191
  end
192
+
193
+
data/tshield.gemspec CHANGED
@@ -28,7 +28,7 @@ Gem::Specification.new do |s|
28
28
  s.add_dependency('grpc-tools', '~> 1.28', '>= 1.28.0')
29
29
  s.add_dependency('httparty', '~> 0.14', '>= 0.14.0')
30
30
  s.add_dependency('json', '~> 2.0', '>= 2.0')
31
- s.add_dependency('puma', '~> 4.3', '>= 4.3.3')
31
+ s.add_dependency('puma', '>= 4.3.3', '< 6.0')
32
32
  s.add_dependency('sinatra', '~> 2.1', '>= 2.1.0')
33
33
  s.add_dependency('sinatra-cross_origin', '~> 0.4.0', '>= 0.4')
34
34
  s.add_development_dependency('coveralls', '~> 0.8', '>= 0.8.23')
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tshield
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.13.0.0
4
+ version: 0.13.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Diego Rubin
@@ -9,148 +9,148 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2020-11-25 00:00:00.000000000 Z
12
+ date: 2021-06-03 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: grpc
16
16
  requirement: !ruby/object:Gem::Requirement
17
17
  requirements:
18
- - - "~>"
19
- - !ruby/object:Gem::Version
20
- version: '1.28'
21
18
  - - ">="
22
19
  - !ruby/object:Gem::Version
23
20
  version: 1.28.0
21
+ - - "~>"
22
+ - !ruby/object:Gem::Version
23
+ version: '1.28'
24
24
  type: :runtime
25
25
  prerelease: false
26
26
  version_requirements: !ruby/object:Gem::Requirement
27
27
  requirements:
28
- - - "~>"
29
- - !ruby/object:Gem::Version
30
- version: '1.28'
31
28
  - - ">="
32
29
  - !ruby/object:Gem::Version
33
30
  version: 1.28.0
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.28'
34
34
  - !ruby/object:Gem::Dependency
35
35
  name: grpc-tools
36
36
  requirement: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - "~>"
39
- - !ruby/object:Gem::Version
40
- version: '1.28'
41
38
  - - ">="
42
39
  - !ruby/object:Gem::Version
43
40
  version: 1.28.0
41
+ - - "~>"
42
+ - !ruby/object:Gem::Version
43
+ version: '1.28'
44
44
  type: :runtime
45
45
  prerelease: false
46
46
  version_requirements: !ruby/object:Gem::Requirement
47
47
  requirements:
48
- - - "~>"
49
- - !ruby/object:Gem::Version
50
- version: '1.28'
51
48
  - - ">="
52
49
  - !ruby/object:Gem::Version
53
50
  version: 1.28.0
51
+ - - "~>"
52
+ - !ruby/object:Gem::Version
53
+ version: '1.28'
54
54
  - !ruby/object:Gem::Dependency
55
55
  name: httparty
56
56
  requirement: !ruby/object:Gem::Requirement
57
57
  requirements:
58
- - - "~>"
59
- - !ruby/object:Gem::Version
60
- version: '0.14'
61
58
  - - ">="
62
59
  - !ruby/object:Gem::Version
63
60
  version: 0.14.0
61
+ - - "~>"
62
+ - !ruby/object:Gem::Version
63
+ version: '0.14'
64
64
  type: :runtime
65
65
  prerelease: false
66
66
  version_requirements: !ruby/object:Gem::Requirement
67
67
  requirements:
68
- - - "~>"
69
- - !ruby/object:Gem::Version
70
- version: '0.14'
71
68
  - - ">="
72
69
  - !ruby/object:Gem::Version
73
70
  version: 0.14.0
71
+ - - "~>"
72
+ - !ruby/object:Gem::Version
73
+ version: '0.14'
74
74
  - !ruby/object:Gem::Dependency
75
75
  name: json
76
76
  requirement: !ruby/object:Gem::Requirement
77
77
  requirements:
78
- - - "~>"
78
+ - - ">="
79
79
  - !ruby/object:Gem::Version
80
80
  version: '2.0'
81
- - - ">="
81
+ - - "~>"
82
82
  - !ruby/object:Gem::Version
83
83
  version: '2.0'
84
84
  type: :runtime
85
85
  prerelease: false
86
86
  version_requirements: !ruby/object:Gem::Requirement
87
87
  requirements:
88
- - - "~>"
88
+ - - ">="
89
89
  - !ruby/object:Gem::Version
90
90
  version: '2.0'
91
- - - ">="
91
+ - - "~>"
92
92
  - !ruby/object:Gem::Version
93
93
  version: '2.0'
94
94
  - !ruby/object:Gem::Dependency
95
95
  name: puma
96
96
  requirement: !ruby/object:Gem::Requirement
97
97
  requirements:
98
- - - "~>"
99
- - !ruby/object:Gem::Version
100
- version: '4.3'
101
98
  - - ">="
102
99
  - !ruby/object:Gem::Version
103
100
  version: 4.3.3
101
+ - - "<"
102
+ - !ruby/object:Gem::Version
103
+ version: '6.0'
104
104
  type: :runtime
105
105
  prerelease: false
106
106
  version_requirements: !ruby/object:Gem::Requirement
107
107
  requirements:
108
- - - "~>"
109
- - !ruby/object:Gem::Version
110
- version: '4.3'
111
108
  - - ">="
112
109
  - !ruby/object:Gem::Version
113
110
  version: 4.3.3
111
+ - - "<"
112
+ - !ruby/object:Gem::Version
113
+ version: '6.0'
114
114
  - !ruby/object:Gem::Dependency
115
115
  name: sinatra
116
116
  requirement: !ruby/object:Gem::Requirement
117
117
  requirements:
118
- - - "~>"
119
- - !ruby/object:Gem::Version
120
- version: '2.1'
121
118
  - - ">="
122
119
  - !ruby/object:Gem::Version
123
120
  version: 2.1.0
121
+ - - "~>"
122
+ - !ruby/object:Gem::Version
123
+ version: '2.1'
124
124
  type: :runtime
125
125
  prerelease: false
126
126
  version_requirements: !ruby/object:Gem::Requirement
127
127
  requirements:
128
- - - "~>"
129
- - !ruby/object:Gem::Version
130
- version: '2.1'
131
128
  - - ">="
132
129
  - !ruby/object:Gem::Version
133
130
  version: 2.1.0
131
+ - - "~>"
132
+ - !ruby/object:Gem::Version
133
+ version: '2.1'
134
134
  - !ruby/object:Gem::Dependency
135
135
  name: sinatra-cross_origin
136
136
  requirement: !ruby/object:Gem::Requirement
137
137
  requirements:
138
- - - "~>"
139
- - !ruby/object:Gem::Version
140
- version: 0.4.0
141
138
  - - ">="
142
139
  - !ruby/object:Gem::Version
143
140
  version: '0.4'
141
+ - - "~>"
142
+ - !ruby/object:Gem::Version
143
+ version: 0.4.0
144
144
  type: :runtime
145
145
  prerelease: false
146
146
  version_requirements: !ruby/object:Gem::Requirement
147
147
  requirements:
148
- - - "~>"
149
- - !ruby/object:Gem::Version
150
- version: 0.4.0
151
148
  - - ">="
152
149
  - !ruby/object:Gem::Version
153
150
  version: '0.4'
151
+ - - "~>"
152
+ - !ruby/object:Gem::Version
153
+ version: 0.4.0
154
154
  - !ruby/object:Gem::Dependency
155
155
  name: coveralls
156
156
  requirement: !ruby/object:Gem::Requirement
@@ -255,80 +255,80 @@ dependencies:
255
255
  name: rdoc
256
256
  requirement: !ruby/object:Gem::Requirement
257
257
  requirements:
258
- - - "~>"
258
+ - - ">="
259
259
  - !ruby/object:Gem::Version
260
260
  version: '6.0'
261
- - - ">="
261
+ - - "~>"
262
262
  - !ruby/object:Gem::Version
263
263
  version: '6.0'
264
264
  type: :development
265
265
  prerelease: false
266
266
  version_requirements: !ruby/object:Gem::Requirement
267
267
  requirements:
268
- - - "~>"
268
+ - - ">="
269
269
  - !ruby/object:Gem::Version
270
270
  version: '6.0'
271
- - - ">="
271
+ - - "~>"
272
272
  - !ruby/object:Gem::Version
273
273
  version: '6.0'
274
274
  - !ruby/object:Gem::Dependency
275
275
  name: reek
276
276
  requirement: !ruby/object:Gem::Requirement
277
277
  requirements:
278
- - - "~>"
278
+ - - ">="
279
279
  - !ruby/object:Gem::Version
280
280
  version: 5.4.0
281
- - - ">="
281
+ - - "~>"
282
282
  - !ruby/object:Gem::Version
283
283
  version: 5.4.0
284
284
  type: :development
285
285
  prerelease: false
286
286
  version_requirements: !ruby/object:Gem::Requirement
287
287
  requirements:
288
- - - "~>"
288
+ - - ">="
289
289
  - !ruby/object:Gem::Version
290
290
  version: 5.4.0
291
- - - ">="
291
+ - - "~>"
292
292
  - !ruby/object:Gem::Version
293
293
  version: 5.4.0
294
294
  - !ruby/object:Gem::Dependency
295
295
  name: rspec
296
296
  requirement: !ruby/object:Gem::Requirement
297
297
  requirements:
298
- - - "~>"
299
- - !ruby/object:Gem::Version
300
- version: '3.5'
301
298
  - - ">="
302
299
  - !ruby/object:Gem::Version
303
300
  version: 3.5.0
301
+ - - "~>"
302
+ - !ruby/object:Gem::Version
303
+ version: '3.5'
304
304
  type: :development
305
305
  prerelease: false
306
306
  version_requirements: !ruby/object:Gem::Requirement
307
307
  requirements:
308
- - - "~>"
309
- - !ruby/object:Gem::Version
310
- version: '3.5'
311
308
  - - ">="
312
309
  - !ruby/object:Gem::Version
313
310
  version: 3.5.0
311
+ - - "~>"
312
+ - !ruby/object:Gem::Version
313
+ version: '3.5'
314
314
  - !ruby/object:Gem::Dependency
315
315
  name: rubocop
316
316
  requirement: !ruby/object:Gem::Requirement
317
317
  requirements:
318
- - - "~>"
318
+ - - ">="
319
319
  - !ruby/object:Gem::Version
320
320
  version: 0.73.0
321
- - - ">="
321
+ - - "~>"
322
322
  - !ruby/object:Gem::Version
323
323
  version: 0.73.0
324
324
  type: :development
325
325
  prerelease: false
326
326
  version_requirements: !ruby/object:Gem::Requirement
327
327
  requirements:
328
- - - "~>"
328
+ - - ">="
329
329
  - !ruby/object:Gem::Version
330
330
  version: 0.73.0
331
- - - ">="
331
+ - - "~>"
332
332
  - !ruby/object:Gem::Version
333
333
  version: 0.73.0
334
334
  - !ruby/object:Gem::Dependency
@@ -375,22 +375,22 @@ dependencies:
375
375
  name: webmock
376
376
  requirement: !ruby/object:Gem::Requirement
377
377
  requirements:
378
- - - "~>"
379
- - !ruby/object:Gem::Version
380
- version: '2.1'
381
378
  - - ">="
382
379
  - !ruby/object:Gem::Version
383
380
  version: 2.1.0
381
+ - - "~>"
382
+ - !ruby/object:Gem::Version
383
+ version: '2.1'
384
384
  type: :development
385
385
  prerelease: false
386
386
  version_requirements: !ruby/object:Gem::Requirement
387
387
  requirements:
388
- - - "~>"
389
- - !ruby/object:Gem::Version
390
- version: '2.1'
391
388
  - - ">="
392
389
  - !ruby/object:Gem::Version
393
390
  version: 2.1.0
391
+ - - "~>"
392
+ - !ruby/object:Gem::Version
393
+ version: '2.1'
394
394
  description: Proxy for mocks API responses
395
395
  email: rubin.diego@gmail.com
396
396
  executables:
@@ -430,6 +430,8 @@ files:
430
430
  - spec/tshield/after_filter_spec.rb
431
431
  - spec/tshield/configuration_spec.rb
432
432
  - spec/tshield/controllers/requests_spec.rb
433
+ - spec/tshield/fixtures/config/tshield-with-send-content-type-header.yml
434
+ - spec/tshield/fixtures/config/tshield-with-send-content-type-header_as_false.yml
433
435
  - spec/tshield/fixtures/config/tshield-without-grpc.yml
434
436
  - spec/tshield/fixtures/config/tshield.yml
435
437
  - spec/tshield/fixtures/filters/example_filter.rb
@@ -460,23 +462,24 @@ required_rubygems_version: !ruby/object:Gem::Requirement
460
462
  - !ruby/object:Gem::Version
461
463
  version: '0'
462
464
  requirements: []
463
- rubyforge_project:
464
- rubygems_version: 2.6.14.4
465
+ rubygems_version: 3.0.3.1
465
466
  signing_key:
466
467
  specification_version: 4
467
468
  summary: Proxy for mocks API responses
468
469
  test_files:
469
- - spec/spec_helper.rb
470
+ - spec/tshield/controllers/requests_spec.rb
471
+ - spec/tshield/after_filter_spec.rb
472
+ - spec/tshield/configuration_spec.rb
473
+ - spec/tshield/fixtures/proto/test_services_pb.rb
474
+ - spec/tshield/fixtures/config/tshield-without-grpc.yml
475
+ - spec/tshield/fixtures/config/tshield-with-send-content-type-header_as_false.yml
476
+ - spec/tshield/fixtures/config/tshield.yml
477
+ - spec/tshield/fixtures/config/tshield-with-send-content-type-header.yml
478
+ - spec/tshield/fixtures/matching/example.json
479
+ - spec/tshield/fixtures/filters/example_filter.rb
470
480
  - spec/tshield/request_vcr_spec.rb
471
481
  - spec/tshield/sessions_spec.rb
472
- - spec/tshield/controllers/requests_spec.rb
473
- - spec/tshield/request_matching_spec.rb
474
482
  - spec/tshield/grpc_spec.rb
475
483
  - spec/tshield/options_spec.rb
476
- - spec/tshield/fixtures/proto/test_services_pb.rb
477
- - spec/tshield/fixtures/filters/example_filter.rb
478
- - spec/tshield/fixtures/matching/example.json
479
- - spec/tshield/fixtures/config/tshield.yml
480
- - spec/tshield/fixtures/config/tshield-without-grpc.yml
481
- - spec/tshield/configuration_spec.rb
482
- - spec/tshield/after_filter_spec.rb
484
+ - spec/tshield/request_matching_spec.rb
485
+ - spec/spec_helper.rb