Skip to content

Commit 7952914

Browse files
committed
Add Plug.Test.sent_chunks/2
Before this patch there was no way to reconstruct the invidual chunks that were sent. All we got was the full resulting body in `conn.resp_body`. For completeness, I believe instead of messaging we could store chunks in a list in the test adapter state and simply append: - def send_chunked(state, _status, _headers), do: {:ok, "", %{state | chunks: ""}} + def send_chunked(state, _status, _headers), do: {:ok, "", %{state | chunks: []}} - def chunk(%{owner: owner, ref: ref, chunks: chunks} = state, chunk) do - send(owner, {ref, :chunk, chunk}) - body = chunks <> IO.iodata_to_binary(chunk) - {:ok, body, %{state | chunks: body}} - end + def chunk(%{owner: owner, ref: ref, chunks: chunks} = state, chunk) do + chunk = IO.iodata_to_binary(chunk) + body = IO.iodata_to_binary([chunks, chunk]) + {:ok, body, %{state | chunks: chunks ++ [chunk]}} + end but I was following the existing functions `sent_informs` and `sent_upgrades`. My use case is to be able to test response streaming using Req :plug adapter: req = Req.new( plug: fn conn -> conn = Plug.Conn.send_chunked(conn, 200) {:ok, conn} = Plug.Conn.chunk(conn, "foo") {:ok, conn} = Plug.Conn.chunk(conn, "bar") conn end, into: [] ) resp = Req.request!(req) assert resp.body == ["foo", "bar"]
1 parent 7b859ef commit 7952914

File tree

3 files changed

+41
-3
lines changed

3 files changed

+41
-3
lines changed

lib/plug/adapters/test/conn.ex

+4-2
Original file line numberDiff line numberDiff line change
@@ -90,8 +90,10 @@ defmodule Plug.Adapters.Test.Conn do
9090

9191
def chunk(%{method: "HEAD"} = state, _body), do: {:ok, "", state}
9292

93-
def chunk(%{chunks: chunks} = state, body) do
94-
body = chunks <> IO.iodata_to_binary(body)
93+
def chunk(%{owner: owner, ref: ref, chunks: chunks} = state, chunk) do
94+
chunk = IO.iodata_to_binary(chunk)
95+
send(owner, {ref, :chunk, chunk})
96+
body = chunks <> chunk
9597
{:ok, body, %{state | chunks: body}}
9698
end
9799

lib/plug/test.ex

+27-1
Original file line numberDiff line numberDiff line change
@@ -99,13 +99,39 @@ defmodule Plug.Test do
9999
end
100100
end
101101

102+
@doc """
103+
Returns the sent body chunks.
104+
105+
This function depends on gathering the messages sent by the test adapter when
106+
response body chunks are sent. Calling this function will clear the chunk
107+
messages from the inbox for the process. To assert on multiple informs, the
108+
result of the function should be stored in a variable.
109+
110+
## Examples
111+
112+
conn = conn(:get, "/")
113+
assert Plug.Test.sent_chunks(conn) == ["foo", "bar"]
114+
"""
115+
def sent_chunks(%Plug.Conn{adapter: {Plug.Adapters.Test.Conn, %{ref: ref}}}) do
116+
Enum.reverse(receive_chunks(ref, []))
117+
end
118+
119+
defp receive_chunks(ref, chunks) do
120+
receive do
121+
{^ref, :chunk, chunk} ->
122+
receive_chunks(ref, [chunk | chunks])
123+
after
124+
0 -> chunks
125+
end
126+
end
127+
102128
@doc """
103129
Returns the informational requests that have been sent.
104130
105131
This function depends on gathering the messages sent by the test adapter when
106132
informational messages, such as an early hint, are sent. Calling this
107133
function will clear the informational request messages from the inbox for the
108-
process. To assert on multiple informs, the result of the function should be
134+
process. To assert on multiple informs, the result of the function should be
109135
stored in a variable.
110136
111137
## Examples

test/plug/adapters/test/conn_test.exs

+10
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,16 @@ defmodule Plug.Adapters.Test.ConnTest do
114114
assert child_conn.host == "www.elixir-lang.org"
115115
end
116116

117+
test "sent chunks" do
118+
conn = conn(:get, "/")
119+
conn = Plug.Conn.send_chunked(conn, 200)
120+
{:ok, conn} = Plug.Conn.chunk(conn, "foo")
121+
{:ok, conn} = Plug.Conn.chunk(conn, "bar")
122+
123+
assert conn.resp_body == "foobar"
124+
assert Plug.Test.sent_chunks(conn) == ["foo", "bar"]
125+
end
126+
117127
test "inform adds to the informational responses to the list" do
118128
conn =
119129
conn(:get, "/")

0 commit comments

Comments
 (0)