http_stub 0.24.3 → 0.25.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (70) hide show
  1. checksums.yaml +4 -4
  2. data/lib/http_stub.rb +8 -2
  3. data/lib/http_stub/server/application/application.rb +16 -4
  4. data/lib/http_stub/server/request/request.rb +6 -1
  5. data/lib/http_stub/server/response.rb +5 -3
  6. data/lib/http_stub/server/scenario/controller.rb +2 -2
  7. data/lib/http_stub/server/scenario/parser.rb +1 -3
  8. data/lib/http_stub/server/stub/controller.rb +8 -6
  9. data/lib/http_stub/server/stub/empty.rb +9 -5
  10. data/lib/http_stub/server/stub/match/controller.rb +22 -0
  11. data/lib/http_stub/server/stub/match/{result.rb → match.rb} +9 -1
  12. data/lib/http_stub/server/stub/match/miss.rb +19 -0
  13. data/lib/http_stub/server/stub/match/rules.rb +33 -0
  14. data/lib/http_stub/server/stub/parser.rb +1 -1
  15. data/lib/http_stub/server/stub/payload.rb +20 -0
  16. data/lib/http_stub/server/stub/payload/base_uri_modifier.rb +17 -0
  17. data/lib/http_stub/server/stub/payload/response_body_modifier.rb +19 -0
  18. data/lib/http_stub/server/stub/response/base.rb +5 -1
  19. data/lib/http_stub/server/stub/response/file.rb +5 -0
  20. data/lib/http_stub/server/stub/response/text.rb +4 -0
  21. data/lib/http_stub/server/stub/stub.rb +8 -18
  22. data/lib/http_stub/server/stub/triggers.rb +1 -1
  23. data/lib/http_stub/server/views/_activate_scenario.haml +17 -4
  24. data/lib/http_stub/server/views/_stub.haml +2 -2
  25. data/lib/http_stub/server/views/{_match.haml → _stub_match.haml} +1 -1
  26. data/lib/http_stub/server/views/_stub_miss.haml +3 -0
  27. data/lib/http_stub/server/views/index.haml +4 -2
  28. data/lib/http_stub/server/views/stub_matches.haml +4 -0
  29. data/lib/http_stub/server/views/stub_misses.haml +4 -0
  30. data/lib/http_stub/version.rb +1 -1
  31. data/spec/acceptance/stub_match_last_spec.rb +170 -0
  32. data/spec/acceptance/stub_match_list_spec.rb +115 -0
  33. data/spec/acceptance/stub_miss_list_spec.rb +58 -0
  34. data/spec/lib/http_stub/server/application/application_spec.rb +57 -13
  35. data/spec/lib/http_stub/server/request/request_spec.rb +41 -1
  36. data/spec/lib/http_stub/server/response_spec.rb +18 -12
  37. data/spec/lib/http_stub/server/scenario/controller_spec.rb +4 -4
  38. data/spec/lib/http_stub/server/scenario/parser_spec.rb +30 -27
  39. data/spec/lib/http_stub/server/stub/controller_spec.rb +45 -26
  40. data/spec/lib/http_stub/server/stub/empty_spec.rb +14 -14
  41. data/spec/lib/http_stub/server/stub/match/controller_spec.rb +69 -0
  42. data/spec/lib/http_stub/server/stub/match/match_spec.rb +146 -0
  43. data/spec/lib/http_stub/server/stub/match/miss_spec.rb +15 -0
  44. data/spec/lib/http_stub/server/stub/match/rules_spec.rb +247 -0
  45. data/spec/lib/http_stub/server/stub/parser_spec.rb +12 -14
  46. data/spec/lib/http_stub/server/stub/payload/base_uri_modifier_spec.rb +23 -0
  47. data/spec/lib/http_stub/server/{payload_file_consolidator_spec.rb → stub/payload/response_body_modifier_spec.rb} +22 -14
  48. data/spec/lib/http_stub/server/stub/payload_spec.rb +33 -0
  49. data/spec/lib/http_stub/server/stub/response/base_spec.rb +22 -0
  50. data/spec/lib/http_stub/server/stub/response/file_spec.rb +29 -1
  51. data/spec/lib/http_stub/server/stub/response/text_spec.rb +18 -0
  52. data/spec/lib/http_stub/server/stub/stub_spec.rb +48 -145
  53. data/spec/lib/http_stub/server/stub/triggers_spec.rb +14 -0
  54. data/spec/spec_helper.rb +7 -3
  55. data/spec/support/{configurer_integration.rb → http_stub/configurer_integration.rb} +3 -2
  56. data/spec/support/http_stub/html_view_excluding_request_details.rb +11 -0
  57. data/spec/support/http_stub/html_view_including_request_details.rb +47 -0
  58. data/spec/support/http_stub/server/scenario/scenario_fixture.rb +1 -1
  59. data/spec/support/http_stub/server/stub/match/match_fixture.rb +21 -0
  60. data/spec/support/http_stub/server/stub/match/miss_fixture.rb +17 -0
  61. data/spec/support/{server_integration.rb → http_stub/server_integration.rb} +0 -0
  62. data/spec/support/http_stub/stub_fixture.rb +1 -0
  63. data/spec/support/http_stub/stub_registrator.rb +83 -0
  64. metadata +47 -19
  65. data/lib/http_stub/server/stub/payload_file_consolidator.rb +0 -18
  66. data/lib/http_stub/server/views/_miss.haml +0 -7
  67. data/lib/http_stub/server/views/match_results.haml +0 -7
  68. data/spec/acceptance/stub_match_spec.rb +0 -252
  69. data/spec/lib/http_stub/server/stub/match/result_spec.rb +0 -33
  70. data/spec/support/http_stub/server/stub/match/result_fixture.rb +0 -19
@@ -0,0 +1,23 @@
1
+ describe HttpStub::Server::Stub::Payload::BaseUriModifier do
2
+
3
+ let(:modifier) { described_class }
4
+
5
+ describe "::modify!" do
6
+
7
+ let(:payload) { HttpStub::StubFixture.new.server_payload }
8
+ let(:base_uri) { "http://base.uri:8888" }
9
+ let(:request) { instance_double(HttpStub::Server::Request::Request, base_uri: base_uri) }
10
+
11
+ subject { modifier.modify!(payload, request) }
12
+
13
+ it "alters the payload to include the servers base uri" do
14
+ expected_payload = payload.clone.merge("base_uri" => base_uri)
15
+
16
+ subject
17
+
18
+ expect(payload).to eql(expected_payload)
19
+ end
20
+
21
+ end
22
+
23
+ end
@@ -1,13 +1,15 @@
1
- describe HttpStub::Server::Stub::PayloadFileConsolidator do
1
+ describe HttpStub::Server::Stub::Payload::ResponseBodyModifier do
2
2
 
3
- let(:consolidator) { described_class }
3
+ let(:modifier) { described_class }
4
4
 
5
- describe "::consolidate!" do
5
+ describe "::modify!" do
6
6
 
7
7
  let(:parameters) { {} }
8
8
  let(:request) { instance_double(HttpStub::Server::Request::Request, parameters: parameters) }
9
9
 
10
- subject { consolidator.consolidate!(payload, request) }
10
+ let!(:original_payload) { payload.clone }
11
+
12
+ subject { modifier.modify!(payload, request) }
11
13
 
12
14
  context "when the payload contains a response file and has a corresponding file parameter" do
13
15
 
@@ -15,10 +17,12 @@ describe HttpStub::Server::Stub::PayloadFileConsolidator do
15
17
  let(:payload) { payload_fixture.server_payload }
16
18
  let(:parameters) { { "response_file_#{payload_fixture.id}" => payload_fixture.file_parameter } }
17
19
 
18
- it "returns the payload with a response body that contains the file parameter value" do
20
+ it "modifies the payload to have a response body that contains the file parameter value" do
19
21
  expected_payload = payload.clone.tap { |hash| hash["response"]["body"] = payload_fixture.file_parameter }
20
22
 
21
- expect(subject).to eql(expected_payload)
23
+ subject
24
+
25
+ expect(payload).to eql(expected_payload)
22
26
  end
23
27
 
24
28
  end
@@ -32,8 +36,10 @@ describe HttpStub::Server::Stub::PayloadFileConsolidator do
32
36
 
33
37
  let(:trigger_fixtures) { (1..3).map { HttpStub::StubFixture.new.with_text_response! } }
34
38
 
35
- it "returns the payload unchanged" do
36
- expect(subject).to eql(payload)
39
+ it "leaves the payload unchanged" do
40
+ subject
41
+
42
+ expect(payload).to eql(original_payload)
37
43
  end
38
44
 
39
45
  end
@@ -47,13 +53,15 @@ describe HttpStub::Server::Stub::PayloadFileConsolidator do
47
53
  end
48
54
  end
49
55
 
50
- it "returns the payload with the trigger response bodies replaced by the files" do
51
- expected_payload = payload_fixture.server_payload
56
+ it "modifies the payload to have trigger response bodies replaced by the files" do
57
+ expected_payload = payload.clone
52
58
  expected_payload["triggers"].zip(trigger_fixtures.map(&:file_parameter)).each do |trigger, file_param|
53
59
  trigger["response"]["body"] = file_param
54
60
  end
55
61
 
56
- expect(subject).to eql(expected_payload)
62
+ subject
63
+
64
+ expect(payload).to eql(expected_payload)
57
65
  end
58
66
 
59
67
  end
@@ -64,10 +72,10 @@ describe HttpStub::Server::Stub::PayloadFileConsolidator do
64
72
 
65
73
  let(:payload) { HttpStub::StubFixture.new.server_payload }
66
74
 
67
- it "returns an unchanged payload" do
68
- original_payload = payload.clone
75
+ it "leaves the payload unchanged" do
76
+ subject
69
77
 
70
- expect(subject).to eql(original_payload)
78
+ expect(payload).to eql(original_payload)
71
79
  end
72
80
 
73
81
  end
@@ -0,0 +1,33 @@
1
+ describe HttpStub::Server::Stub::Payload do
2
+
3
+ describe "::modify!" do
4
+
5
+ let(:payload) { HttpStub::StubFixture.new.server_payload }
6
+ let(:request) { instance_double(HttpStub::Server::Request::Request) }
7
+
8
+ subject { described_class.modify!(payload, request) }
9
+
10
+ before(:example) do
11
+ allow(HttpStub::Server::Stub::Payload::BaseUriModifier).to receive(:modify!)
12
+ allow(HttpStub::Server::Stub::Payload::ResponseBodyModifier).to receive(:modify!)
13
+ end
14
+
15
+ it "modifies the payloads base uri" do
16
+ expect(HttpStub::Server::Stub::Payload::BaseUriModifier).to receive(:modify!).with(payload, request)
17
+
18
+ subject
19
+ end
20
+
21
+ it "modifies the payloads request body" do
22
+ expect(HttpStub::Server::Stub::Payload::ResponseBodyModifier).to receive(:modify!).with(payload, request)
23
+
24
+ subject
25
+ end
26
+
27
+ it "returns the potentially modified payload" do
28
+ expect(subject).to be(payload)
29
+ end
30
+
31
+ end
32
+
33
+ end
@@ -186,4 +186,26 @@ describe HttpStub::Server::Stub::Response::Base do
186
186
 
187
187
  end
188
188
 
189
+ describe "#to_hash" do
190
+
191
+ subject { response.to_hash }
192
+
193
+ describe "supporting creating a JSON representation of the response" do
194
+
195
+ it "contains the responses status" do
196
+ expect(subject).to include(status: response.status)
197
+ end
198
+
199
+ it "contains the responses headers" do
200
+ expect(subject).to include(headers: response.headers)
201
+ end
202
+
203
+ it "contains the responses delay in seconds" do
204
+ expect(subject).to include(delay_in_seconds: response.delay_in_seconds)
205
+ end
206
+
207
+ end
208
+
209
+ end
210
+
189
211
  end
@@ -77,7 +77,8 @@ describe HttpStub::Server::Stub::Response::File do
77
77
 
78
78
  let(:status) { 321 }
79
79
  let(:additional_args) { { "status" => status } }
80
- let(:server) { instance_double(Sinatra::Base) }
80
+ let(:server_response) { instance_double(Sinatra::Response, status: 200) }
81
+ let(:server) { instance_double(Sinatra::Base, response: server_response) }
81
82
 
82
83
  subject { response_file.serve_on(server) }
83
84
 
@@ -93,6 +94,15 @@ describe HttpStub::Server::Stub::Response::File do
93
94
  subject
94
95
  end
95
96
 
97
+ it "updates the responses status to reflect the status evaluated by Sinatra" do
98
+ expect(server).to receive(:send_file).ordered
99
+ expect(server_response).to receive(:status).and_return(304).ordered
100
+
101
+ subject
102
+
103
+ expect(response_file.status).to eql(304)
104
+ end
105
+
96
106
  context "when a content type header is specified" do
97
107
 
98
108
  let(:content_type) { "plain/text" }
@@ -170,4 +180,22 @@ describe HttpStub::Server::Stub::Response::File do
170
180
 
171
181
  end
172
182
 
183
+ describe "#to_hash" do
184
+
185
+ subject { response_file.to_hash }
186
+
187
+ describe "supporting creating a JSON representation of the response" do
188
+
189
+ it "contains the files uri" do
190
+ expect(subject).to include(file_uri: response_file.uri)
191
+ end
192
+
193
+ it "contains the standard response attributes" do
194
+ expect(subject).to include(headers: response_file.headers)
195
+ end
196
+
197
+ end
198
+
199
+ end
200
+
173
201
  end
@@ -165,4 +165,22 @@ describe HttpStub::Server::Stub::Response::Text do
165
165
 
166
166
  end
167
167
 
168
+ describe "#to_hash" do
169
+
170
+ subject { response_text.to_hash }
171
+
172
+ describe "supporting creating a JSON representation of the response" do
173
+
174
+ it "contains the responses body" do
175
+ expect(subject).to include(body: response_text.body)
176
+ end
177
+
178
+ it "contains the standard response attributes" do
179
+ expect(subject).to include(headers: response_text.headers)
180
+ end
181
+
182
+ end
183
+
184
+ end
185
+
168
186
  end
@@ -1,22 +1,10 @@
1
1
  describe HttpStub::Server::Stub::Stub do
2
2
 
3
- let(:request_header_payload) do
4
- {
5
- "header1" => "header_value1",
6
- "header2" => "header_value2",
7
- "header3" => "header_value3"
8
- }
9
- end
10
- let(:request_parameter_payload) do
11
- {
12
- "param1" => "param_value1",
13
- "param2" => "param_value2",
14
- "param3" => "param_value3"
15
- }
16
- end
17
- let(:request_method_payload) { "get" }
3
+ let(:base_uri) { "http://base.uri:8888" }
4
+ let(:stub_id) { SecureRandom.uuid }
18
5
  let(:trigger_payload) do
19
6
  {
7
+ "base_uri" => base_uri,
20
8
  "uri" => "/a_triggered_path",
21
9
  "method" => "post",
22
10
  "headers" => { "triggered_header" => "triggered_header_value" },
@@ -28,14 +16,14 @@ describe HttpStub::Server::Stub::Stub do
28
16
  }
29
17
  }
30
18
  end
31
- let(:stub_id) { SecureRandom.uuid }
32
19
  let(:stub_payload) do
33
20
  {
34
21
  "id" => stub_id,
22
+ "base_uri" => base_uri,
35
23
  "uri" => "/a_path",
36
- "method" => stub_method,
37
- "headers" => request_header_payload,
38
- "parameters" => request_parameter_payload,
24
+ "method" => "get",
25
+ "headers" => { "header" => "header value" },
26
+ "parameters" => { "parameter" => "parameter value" },
39
27
  "body" => { "schema" => { "json" => "stub schema definition" } },
40
28
  "response" => {
41
29
  "status" => 201,
@@ -44,11 +32,7 @@ describe HttpStub::Server::Stub::Stub do
44
32
  "triggers" => [ trigger_payload ]
45
33
  }
46
34
  end
47
- let(:stub_method) { instance_double(HttpStub::Server::Stub::Match::Rule::Method, matches?: true) }
48
- let(:uri) { instance_double(HttpStub::Server::Stub::Match::Rule::Uri, matches?: true) }
49
- let(:request_headers) { instance_double(HttpStub::Server::Stub::Match::Rule::Headers, matches?: true) }
50
- let(:request_parameters) { instance_double(HttpStub::Server::Stub::Match::Rule::Parameters, matches?: true) }
51
- let(:request_body) { double("HttpStub::Server::Stub::SomeRequestBody", matches?: true) }
35
+ let(:match_rules) { instance_double(HttpStub::Server::Stub::Match::Rules, matches?: true) }
52
36
  let(:response_types) { [ HttpStub::Server::Stub::Response::Text, HttpStub::Server::Stub::Response::File ] }
53
37
  let(:response) { instance_double(response_types.sample) }
54
38
  let(:triggers) { instance_double(HttpStub::Server::Stub::Triggers) }
@@ -56,11 +40,7 @@ describe HttpStub::Server::Stub::Stub do
56
40
  let(:the_stub) { HttpStub::Server::Stub::Stub.new(stub_payload) }
57
41
 
58
42
  before(:example) do
59
- allow(HttpStub::Server::Stub::Match::Rule::Method).to receive(:new).and_return(stub_method)
60
- allow(HttpStub::Server::Stub::Match::Rule::Uri).to receive(:new).and_return(uri)
61
- allow(HttpStub::Server::Stub::Match::Rule::Headers).to receive(:new).and_return(request_headers)
62
- allow(HttpStub::Server::Stub::Match::Rule::Parameters).to receive(:new).and_return(request_parameters)
63
- allow(HttpStub::Server::Stub::Match::Rule::Body).to receive(:create).and_return(request_body)
43
+ allow(HttpStub::Server::Stub::Match::Rules).to receive(:new).and_return(match_rules)
64
44
  allow(HttpStub::Server::Stub::Response).to receive(:create).and_return(response)
65
45
  allow(HttpStub::Server::Stub::Triggers).to receive(:new).and_return(triggers)
66
46
  end
@@ -72,102 +52,25 @@ describe HttpStub::Server::Stub::Stub do
72
52
  context "when a request is provided" do
73
53
 
74
54
  let(:request_method) { request_method_payload }
75
- let(:request) { instance_double(HttpStub::Server::Request::Request, method: request_method_payload) }
55
+ let(:request) { instance_double(HttpStub::Server::Request::Request) }
76
56
 
77
57
  subject { the_stub.matches?(request, logger) }
78
58
 
79
- describe "when the request uri matches" do
80
-
81
- before(:example) { allow(uri).to receive(:matches?).with(request, logger).and_return(true) }
82
-
83
- describe "and the request method matches" do
84
-
85
- describe "and a header match is configured" do
86
-
87
- describe "that matches" do
88
-
89
- before(:example) { allow(request_headers).to receive(:matches?).with(request, logger).and_return(true) }
90
-
91
- describe "and a parameter match is configured" do
92
-
93
- describe "that matches" do
94
-
95
- before(:example) do
96
- allow(request_parameters).to receive(:matches?).with(request, logger).and_return(true)
97
- end
98
-
99
- describe "and a body match is configured" do
100
-
101
- describe "that matches" do
102
-
103
- before(:example) do
104
- allow(request_body).to receive(:matches?).with(request, logger).and_return(true)
105
- end
106
-
107
- it "returns true" do
108
- expect(subject).to be(true)
109
- end
110
-
111
- end
112
-
113
- end
59
+ before(:example) { allow(match_rules).to receive(:matches?).with(request, logger).and_return(match_rules_result) }
114
60
 
115
- end
61
+ describe "and the match rules match the request" do
116
62
 
117
- end
63
+ let(:match_rules_result) { true }
118
64
 
119
- end
120
-
121
- end
122
-
123
- end
124
-
125
- end
126
-
127
-
128
- describe "when the request uri does not match" do
129
-
130
- before(:example) { allow(uri).to receive(:matches?).with(request, logger).and_return(false) }
131
-
132
- it "returns false" do
133
- expect(subject).to be(false)
134
- end
135
-
136
- end
137
-
138
- describe "when the request method does not match" do
139
-
140
- before(:example) { allow(stub_method).to receive(:matches?).with(request, logger).and_return(false) }
141
-
142
- it "returns false" do
143
- expect(subject).to be(false)
144
- end
145
-
146
- end
147
-
148
- describe "when the headers do not match" do
149
-
150
- before(:example) { allow(request_headers).to receive(:matches?).with(request, logger).and_return(false) }
151
-
152
- it "returns false" do
153
- expect(subject).to be(false)
154
- end
155
-
156
- end
157
-
158
- describe "when the parameters do not match" do
159
-
160
- before(:example) { allow(request_parameters).to receive(:matches?).with(request, logger).and_return(false) }
161
-
162
- it "returns false" do
163
- expect(subject).to be(false)
65
+ it "returns true" do
66
+ expect(subject).to be(true)
164
67
  end
165
68
 
166
69
  end
167
70
 
168
- describe "when the bodies do not match" do
71
+ describe "and the match rule do not match the request" do
169
72
 
170
- before(:example) { allow(request_body).to receive(:matches?).with(request, logger).and_return(false) }
73
+ let(:match_rules_result) { false }
171
74
 
172
75
  it "returns false" do
173
76
  expect(subject).to be(false)
@@ -205,7 +108,7 @@ describe HttpStub::Server::Stub::Stub do
205
108
 
206
109
  end
207
110
 
208
- describe "#repsonse_for" do
111
+ describe "#response_for" do
209
112
 
210
113
  let(:request) { instance_double(HttpStub::Server::Request::Request) }
211
114
 
@@ -228,40 +131,30 @@ describe HttpStub::Server::Stub::Stub do
228
131
 
229
132
  describe "#uri" do
230
133
 
231
- it "returns the uri model encapsulating the uri provided in the request body" do
232
- expect(the_stub.uri).to eql(uri)
233
- end
234
-
235
- end
236
-
237
- describe "#method" do
238
-
239
- it "returns the method model encapsulating the method provided in the request body" do
240
- expect(the_stub.method).to eql(stub_method)
241
- end
134
+ subject { the_stub.uri }
242
135
 
243
- end
136
+ context "when an id is provided in the payload" do
244
137
 
245
- describe "#headers" do
138
+ it "returns a absolute uri on the server that includes the id" do
139
+ expect(subject).to eql("#{base_uri}/http_stub/stubs/#{stub_id}")
140
+ end
246
141
 
247
- it "returns the headers model encapsulating the headers provided in the request body" do
248
- expect(the_stub.headers).to eql(request_headers)
249
142
  end
250
143
 
251
- end
144
+ context "when an id is not provided in the payload" do
252
145
 
253
- describe "#parameters" do
146
+ it "returns an absolute uri on the server that includes a generated id" do
147
+ expect(subject).to match(%r{#{base_uri}/http_stub/stubs/[a-zA-Z0-9-]+$})
148
+ end
254
149
 
255
- it "returns the parameters model encapsulating the parameters provided in the request body" do
256
- expect(the_stub.parameters).to eql(request_parameters)
257
150
  end
258
151
 
259
152
  end
260
153
 
261
- describe "#body" do
154
+ describe "#match_rules" do
262
155
 
263
- it "returns the body model encapsulating the body provided in the request body" do
264
- expect(the_stub.body).to eql(request_body)
156
+ it "returns the match rules encapsulating the rules provided in the request body" do
157
+ expect(the_stub.match_rules).to eql(match_rules)
265
158
  end
266
159
 
267
160
  end
@@ -282,20 +175,30 @@ describe HttpStub::Server::Stub::Stub do
282
175
 
283
176
  end
284
177
 
285
- describe "#stub_uri" do
178
+ describe "#to_hash" do
286
179
 
287
- context "when an id is provided in the payload" do
180
+ subject { the_stub.to_hash }
181
+
182
+ describe "supporting creating a JSON representation of the stub" do
288
183
 
289
- it "returns a relative uri to the stub that includes the id" do
290
- expect(the_stub.stub_uri).to eql("/http_stub/stubs/#{stub_id}")
184
+ it "contains the stubs id" do
185
+ expect(subject).to include(id: stub_id)
291
186
  end
292
187
 
293
- end
188
+ it "contains the stubs uri" do
189
+ expect(subject).to include(uri: the_stub.uri)
190
+ end
294
191
 
295
- context "when an id is not provided in the payload" do
192
+ it "contains the stubs match rules" do
193
+ expect(subject).to include(match_rules: the_stub.match_rules)
194
+ end
195
+
196
+ it "contains the stubs response" do
197
+ expect(subject).to include(response: the_stub.response)
198
+ end
296
199
 
297
- it "returns a relative uri to the stub that includes a generated id" do
298
- expect(the_stub.stub_uri).to match(/\/http_stub\/stubs\/[a-zA-Z0-9-]+$/)
200
+ it "contains the stubs triggers" do
201
+ expect(subject).to include(triggers: the_stub.triggers)
299
202
  end
300
203
 
301
204
  end