Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Plug.Test.sent_chunks/2 #1160

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions lib/plug/adapters/test/conn.ex
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,10 @@ defmodule Plug.Adapters.Test.Conn do

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

def chunk(%{chunks: chunks} = state, body) do
body = chunks <> IO.iodata_to_binary(body)
def chunk(%{owner: owner, ref: ref, chunks: chunks} = state, chunk) do
chunk = IO.iodata_to_binary(chunk)
send(owner, {ref, :chunk, chunk})
body = chunks <> chunk
{:ok, body, %{state | chunks: body}}
end

Expand Down
28 changes: 27 additions & 1 deletion lib/plug/test.ex
Original file line number Diff line number Diff line change
Expand Up @@ -99,13 +99,39 @@ defmodule Plug.Test do
end
end

@doc """
Returns the sent body chunks.

This function depends on gathering the messages sent by the test adapter when
response body chunks are sent. Calling this function will clear the chunk
messages from the inbox for the process. To assert on multiple informs, the
result of the function should be stored in a variable.

## Examples

conn = conn(:get, "/")
assert Plug.Test.sent_chunks(conn) == ["foo", "bar"]
"""
def sent_chunks(%Plug.Conn{adapter: {Plug.Adapters.Test.Conn, %{ref: ref}}}) do
Enum.reverse(receive_chunks(ref, []))
end

defp receive_chunks(ref, chunks) do
receive do
{^ref, :chunk, chunk} ->
receive_chunks(ref, [chunk | chunks])
after
0 -> chunks
end
end

@doc """
Returns the informational requests that have been sent.

This function depends on gathering the messages sent by the test adapter when
informational messages, such as an early hint, are sent. Calling this
function will clear the informational request messages from the inbox for the
process. To assert on multiple informs, the result of the function should be
process. To assert on multiple informs, the result of the function should be
stored in a variable.

## Examples
Expand Down
18 changes: 18 additions & 0 deletions test/plug/adapters/test/conn_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,24 @@ defmodule Plug.Adapters.Test.ConnTest do
assert child_conn.host == "www.elixir-lang.org"
end

test "sent chunks" do
conn = conn(:get, "/")
conn = Plug.Conn.send_chunked(conn, 200)
{:ok, conn} = Plug.Conn.chunk(conn, "foo")
{:ok, conn} = Plug.Conn.chunk(conn, "bar")

assert conn.resp_body == "foobar"
assert Plug.Test.sent_chunks(conn) == ["foo", "bar"]
end

test "sent chunks on send_resp" do
conn = conn(:get, "/")
conn = Plug.Conn.send_resp(conn, 200, "foobar")

assert conn.resp_body == "foobar"
assert Plug.Test.sent_chunks(conn) == []
end
Comment on lines +127 to +133
Copy link
Contributor Author

@wojtekmach wojtekmach Nov 29, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When doing Req.get(plug: plug, into: stream), I'm using this new sent_chunks/1 function however as seen in this test it doesn't behave correctly (for Req) when the plug is not sending chunks. Maybe the function should raise?


test "inform adds to the informational responses to the list" do
conn =
conn(:get, "/")
Expand Down
Loading