Skip to content

Commit da66651

Browse files
Add more tests for make_response including Rack 2 streaming.
1 parent 6b347bb commit da66651

File tree

3 files changed

+235
-191
lines changed

3 files changed

+235
-191
lines changed

test/protocol/rack/adapter/rack2.rb

Lines changed: 112 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -3,121 +3,146 @@
33
# Released under the MIT License.
44
# Copyright, 2022-2025, by Samuel Williams.
55

6-
require "sus/fixtures/console"
76
require "protocol/rack/adapter/rack2"
87

8+
require "sus/fixtures/console"
9+
10+
require "rack"
11+
require "protocol/rack/body/streaming"
12+
913
describe Protocol::Rack::Adapter::Rack2 do
1014
include Sus::Fixtures::Console::CapturedLogger
1115

12-
let(:app) {->(env) {[200, {}, []]}}
13-
let(:adapter) {subject.new(app)}
14-
15-
let(:body) {Protocol::HTTP::Body::Buffered.new}
16-
let(:request) {Protocol::HTTP::Request.new("https", "example.com", "GET", "/", "http/1.1", Protocol::HTTP::Headers[{"accept" => "text/html"}], body)}
17-
let(:response) {adapter.call(request)}
18-
19-
with "set-cookie headers that has multiple values" do
20-
let(:app) {->(env) {[200, {"set-cookie" => "a=b\nx=y"}, []]}}
16+
with "#call" do
17+
let(:app) {->(env) {[200, {}, []]}}
18+
let(:adapter) {subject.new(app)}
2119

22-
it "can make a response newline separated headers" do
23-
expect(response.headers["set-cookie"]).to be == ["a=b", "x=y"]
24-
end
25-
end
26-
27-
with "content-length header" do
28-
let(:app) {->(env) {[200, {"content-length" => "10"}, ["1234567890"]]}}
20+
let(:body) {Protocol::HTTP::Body::Buffered.new}
21+
let(:request) {Protocol::HTTP::Request.new("https", "example.com", "GET", "/", "http/1.1", Protocol::HTTP::Headers[{"accept" => "text/html"}], body)}
22+
let(:response) {adapter.call(request)}
2923

30-
it "removes content-length header" do
31-
expect(response.headers).not.to be(:include?, "content-length")
24+
with "set-cookie headers that has multiple values" do
25+
let(:app) {->(env) {[200, {"set-cookie" => "a=b\nx=y"}, []]}}
26+
27+
it "can make a response newline separated headers" do
28+
expect(response.headers["set-cookie"]).to be == ["a=b", "x=y"]
29+
end
3230
end
33-
end
34-
35-
with "connection: close header" do
36-
let(:app) {->(env) {[200, {"connection" => "close"}, []]}}
3731

38-
it "removes content-length header" do
39-
expect(response.headers).not.to be(:include?, "connection")
40-
end
41-
end
42-
43-
with "body that responds to #to_path" do
44-
let(:body) {Array.new}
45-
let(:app) {->(env) {[200, {}, body]}}
46-
47-
it "should generate file body" do
48-
expect(body).to receive(:to_path).and_return("/dev/null")
49-
50-
expect(response.body).to be_a(Protocol::HTTP::Body::File)
51-
end
52-
53-
with "206 partial response status" do
54-
let(:app) {->(env) {[200, {}, body]}}
32+
with "content-length header" do
33+
let(:app) {->(env) {[200, {"content-length" => "10"}, ["1234567890"]]}}
5534

56-
it "should not modify partial responses" do
57-
expect(response.body).to be_a(Protocol::Rack::Body::Enumerable)
35+
it "removes content-length header" do
36+
expect(response.headers).not.to be(:include?, "content-length")
5837
end
5938
end
60-
end
61-
62-
with "a hijacked response" do
63-
let(:callback) {->(stream){}}
64-
let(:app) {->(env){[200, {"rack.hijack" => callback}, []]}}
6539

66-
it "should support hijacking" do
67-
expect(response.body).to be_a(Protocol::Rack::Body::Streaming)
68-
end
69-
end
70-
71-
with "response handling" do
72-
with "array response" do
73-
let(:app) {->(env) {[200, {}, ["Hello"]]}}
40+
with "connection: close header" do
41+
let(:app) {->(env) {[200, {"connection" => "close"}, []]}}
7442

75-
it "handles array response correctly" do
76-
expect(response.body).to be_a(Protocol::Rack::Body::Enumerable)
43+
it "removes content-length header" do
44+
expect(response.headers).not.to be(:include?, "connection")
7745
end
7846
end
7947

80-
# with "string response" do
81-
# let(:app) {->(env) {[200, {}, "Hello"]}}
82-
83-
# it "handles string response correctly" do
84-
# expect(response.status).to be == 500
85-
# expect(response.read).to be == "ArgumentError: Body must respond to #each!"
86-
# end
87-
# end
88-
end
89-
90-
with "header transformation" do
91-
with "array values" do
92-
let(:app) {->(env) {[200, {"x-custom" => "a\nb"}, []]}}
93-
94-
it "joins array values with newlines in response" do
95-
expect(response.headers["x-custom"]).to be == ["a", "b"]
48+
with "body that responds to #to_path" do
49+
let(:body) {Array.new}
50+
let(:app) {->(env) {[200, {}, body]}}
51+
52+
it "should generate file body" do
53+
expect(body).to receive(:to_path).and_return("/dev/null")
54+
55+
expect(response.body).to be_a(Protocol::HTTP::Body::File)
56+
end
57+
58+
with "206 partial response status" do
59+
let(:app) {->(env) {[200, {}, body]}}
60+
61+
it "should not modify partial responses" do
62+
expect(response.body).to be_a(Protocol::Rack::Body::Enumerable)
63+
end
9664
end
9765
end
9866

99-
with "non-array values" do
100-
let(:app) {->(env) {[200, {"x-custom" => "value"}, []]}}
67+
with "a hijacked response" do
68+
let(:callback) {->(stream){}}
69+
let(:app) {->(env){[200, {"rack.hijack" => callback}, []]}}
10170

102-
it "preserves non-array values" do
103-
expect(response.headers["x-custom"]).to be == ["value"]
71+
it "should support hijacking" do
72+
expect(response.body).to be_a(Protocol::Rack::Body::Streaming)
10473
end
10574
end
10675

107-
with "multiple set-cookie headers" do
108-
let(:app) {->(env) {[200, {"set-cookie" => "a=b\nx=y"}, []]}}
109-
110-
it "joins set-cookie headers with newlines" do
111-
expect(response.headers["set-cookie"]).to be == ["a=b", "x=y"]
76+
with "response handling" do
77+
with "array response" do
78+
let(:app) {->(env) {[200, {}, ["Hello"]]}}
79+
80+
it "handles array response correctly" do
81+
expect(response.body).to be_a(Protocol::Rack::Body::Enumerable)
82+
end
11283
end
11384
end
11485

115-
with "rack specific headers" do
116-
let(:app) {->(env) {[200, {"rack.hijack" => ->(stream){}}, []]}}
86+
with "header transformation" do
87+
with "array values" do
88+
let(:app) {->(env) {[200, {"x-custom" => "a\nb"}, []]}}
89+
90+
it "joins array values with newlines in response" do
91+
expect(response.headers["x-custom"]).to be == ["a", "b"]
92+
end
93+
end
94+
95+
with "non-array values" do
96+
let(:app) {->(env) {[200, {"x-custom" => "value"}, []]}}
97+
98+
it "preserves non-array values" do
99+
expect(response.headers["x-custom"]).to be == ["value"]
100+
end
101+
end
117102

118-
it "preserves rack specific headers in meta" do
119-
expect(response.headers).not.to be(:include?, "rack.hijack")
103+
with "multiple set-cookie headers" do
104+
let(:app) {->(env) {[200, {"set-cookie" => "a=b\nx=y"}, []]}}
105+
106+
it "joins set-cookie headers with newlines" do
107+
expect(response.headers["set-cookie"]).to be == ["a=b", "x=y"]
108+
end
120109
end
110+
111+
with "rack specific headers" do
112+
let(:app) {->(env) {[200, {"rack.hijack" => ->(stream){}}, []]}}
113+
114+
it "preserves rack specific headers in meta" do
115+
expect(response.headers).not.to be(:include?, "rack.hijack")
116+
end
117+
end
118+
end
119+
end
120+
121+
with "#make_response" do
122+
let(:env) {::Rack::MockRequest.env_for("/")}
123+
124+
it "can wrap response" do
125+
response = Protocol::HTTP::Response[200, headers: {}, body: []]
126+
status, headers, body = subject.make_response(env, response)
127+
128+
expect(status).to be == 200
129+
expect(headers).to be == {}
130+
expect(body).to be_a(Protocol::HTTP::Body::Buffered)
131+
expect(body).to be(:empty?)
132+
end
133+
134+
135+
it "can wrap streaming response" do
136+
streaming_body = Protocol::Rack::Body::Streaming.new(->(stream){})
137+
response = Protocol::HTTP::Response[200, headers: {}, body: streaming_body]
138+
139+
env[Protocol::Rack::RACK_IS_HIJACK] = true
140+
141+
status, headers, body = subject.make_response(env, response)
142+
143+
expect(status).to be == 200
144+
expect(headers).to have_keys(Protocol::Rack::RACK_HIJACK)
145+
expect(body).to be == []
121146
end
122147
end
123-
end
148+
end

test/protocol/rack/adapter/rack3.rb

Lines changed: 61 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -11,65 +11,81 @@
1111
describe Protocol::Rack::Adapter::Rack3 do
1212
include Sus::Fixtures::Console::CapturedLogger
1313

14-
let(:app) {->(env) {[200, {}, []]}}
15-
let(:adapter) {subject.new(app)}
16-
17-
let(:body) {Protocol::HTTP::Body::Buffered.new}
18-
let(:request) {Protocol::HTTP::Request.new("https", "example.com", "GET", "/", "http/1.1", Protocol::HTTP::Headers[{"accept" => "text/html"}], body)}
19-
let(:response) {adapter.call(request)}
20-
21-
with "set-cookie headers that has multiple values" do
22-
let(:app) {->(env) {[200, {"set-cookie" => ["a=b", "x=y"]}, []]}}
14+
with "#call" do
15+
let(:app) {->(env) {[200, {}, []]}}
16+
let(:adapter) {subject.new(app)}
2317

24-
it "can make a response newline separated headers" do
25-
expect(response.headers["set-cookie"]).to be == ["a=b", "x=y"]
26-
end
27-
end
28-
29-
with "content-length header" do
30-
let(:app) {->(env) {[200, {"content-length" => "10"}, ["1234567890"]]}}
18+
let(:body) {Protocol::HTTP::Body::Buffered.new}
19+
let(:request) {Protocol::HTTP::Request.new("https", "example.com", "GET", "/", "http/1.1", Protocol::HTTP::Headers[{"accept" => "text/html"}], body)}
20+
let(:response) {adapter.call(request)}
3121

32-
it "removes content-length header" do
33-
expect(response.headers).not.to be(:include?, "content-length")
22+
with "set-cookie headers that has multiple values" do
23+
let(:app) {->(env) {[200, {"set-cookie" => ["a=b", "x=y"]}, []]}}
24+
25+
it "can make a response newline separated headers" do
26+
expect(response.headers["set-cookie"]).to be == ["a=b", "x=y"]
27+
end
3428
end
35-
end
36-
37-
with "connection: close header" do
38-
let(:app) {->(env) {[200, {"connection" => "close"}, []]}}
3929

40-
it "removes content-length header" do
41-
expect(response.headers).not.to be(:include?, "connection")
30+
with "content-length header" do
31+
let(:app) {->(env) {[200, {"content-length" => "10"}, ["1234567890"]]}}
32+
33+
it "removes content-length header" do
34+
expect(response.headers).not.to be(:include?, "content-length")
35+
end
4236
end
43-
end
44-
45-
with "body that responds to #to_path" do
46-
let(:fake_file) {Array.new}
47-
let(:app) {->(env) {[200, {}, fake_file]}}
4837

49-
it "should generate file body" do
50-
expect(fake_file).to receive(:to_path).and_return("/dev/null")
38+
with "connection: close header" do
39+
let(:app) {->(env) {[200, {"connection" => "close"}, []]}}
5140

52-
expect(response.body).to be(:kind_of?, Protocol::HTTP::Body::File)
41+
it "removes content-length header" do
42+
expect(response.headers).not.to be(:include?, "connection")
43+
end
5344
end
54-
55-
with "206 partial response status" do
45+
46+
with "body that responds to #to_path" do
47+
let(:fake_file) {Array.new}
5648
let(:app) {->(env) {[200, {}, fake_file]}}
5749

58-
it "should not modify partial responses" do
59-
expect(response.body).to be(:kind_of?, Protocol::Rack::Body::Enumerable)
50+
it "should generate file body" do
51+
expect(fake_file).to receive(:to_path).and_return("/dev/null")
52+
53+
expect(response.body).to be(:kind_of?, Protocol::HTTP::Body::File)
54+
end
55+
56+
with "206 partial response status" do
57+
let(:app) {->(env) {[200, {}, fake_file]}}
58+
59+
it "should not modify partial responses" do
60+
expect(response.body).to be(:kind_of?, Protocol::Rack::Body::Enumerable)
61+
end
6062
end
6163
end
62-
end
63-
64-
with "a request that has response finished callbacks" do
65-
let(:callback) {->(env, status, headers, error){}}
66-
let(:app) {->(env) {env["rack.response_finished"] << callback; [200, {}, ["Hello World!"]]}}
6764

68-
it "should call the callbacks" do
69-
expect(callback).to receive(:call)
65+
with "a request that has response finished callbacks" do
66+
let(:callback) {->(env, status, headers, error){}}
67+
let(:app) {->(env) {env["rack.response_finished"] << callback; [200, {}, ["Hello World!"]]}}
7068

71-
expect(response).to be(:success?)
72-
expect(response.read).to be == "Hello World!"
69+
it "should call the callbacks" do
70+
expect(callback).to receive(:call)
71+
72+
expect(response).to be(:success?)
73+
expect(response.read).to be == "Hello World!"
74+
end
75+
end
76+
end
77+
78+
with "#make_response" do
79+
let(:env) {::Rack::MockRequest.env_for("/")}
80+
let(:response) {Protocol::HTTP::Response[200, headers: {}, body: []]}
81+
82+
it "can wrap headers" do
83+
status, headers, body = subject.make_response(env, response)
84+
85+
expect(status).to be == 200
86+
expect(headers).to be == {}
87+
expect(body).to be_a(Protocol::HTTP::Body::Buffered)
88+
expect(body).to be(:empty?)
7389
end
7490
end
7591
end

0 commit comments

Comments
 (0)