api-surface #1
2 changed files with 39 additions and 1 deletions
fix(api/endpoint): stop silently discarding non-map form bodies
stringify_values/1 had a catch-all that coerced any non-map payload to
%{}, silently dropping all form fields on the files: :form path. Narrow
the catch-all to nil only (the legitimate payload || %{} case); any other
non-map now raises FunctionClauseError instead of vanishing on the wire.
Add prepare_body/3 form-field tests covering the map, nil, and
non-map-raises cases.
commit
bd911d6205
|
|
@ -251,7 +251,9 @@ defmodule Dexcord.Api.Endpoint do
|
|||
defp stringify_values(payload) when is_map(payload),
|
||||
do: Map.new(payload, fn {k, v} -> {k, to_string(v)} end)
|
||||
|
||||
defp stringify_values(_payload), do: %{}
|
||||
# A nil payload is legitimate (payload || %{} semantics); any other non-map
|
||||
# is a caller error and must raise rather than silently drop the form fields.
|
||||
defp stringify_values(nil), do: %{}
|
||||
|
||||
@doc false
|
||||
def encode_body(nil, _spec), do: nil
|
||||
|
|
|
|||
|
|
@ -136,6 +136,42 @@ defmodule Dexcord.Api.EndpointTest do
|
|||
end
|
||||
end
|
||||
|
||||
describe "prepare_body/3 with form-field files (sticker create)" do
|
||||
defp form_spec do
|
||||
%{body: true, files: :form, binary_wrap: nil}
|
||||
end
|
||||
|
||||
test "stringifies every payload value onto bare form parts" do
|
||||
file = %{filename: "s.png", data: <<1>>}
|
||||
|
||||
assert {:form_multipart, fields, out_file} =
|
||||
Endpoint.prepare_body(form_spec(), [name: "sticker", tags: "cat"], files: [file])
|
||||
|
||||
assert fields == %{"name" => "sticker", "tags" => "cat"}
|
||||
assert out_file.filename == "s.png"
|
||||
refute Map.has_key?(out_file, :description)
|
||||
end
|
||||
|
||||
test "a nil body is legitimate and yields empty form fields" do
|
||||
file = %{filename: "s.png", data: <<1>>}
|
||||
|
||||
assert {:form_multipart, %{}, out_file} =
|
||||
Endpoint.prepare_body(form_spec(), nil, files: [file])
|
||||
|
||||
assert out_file.filename == "s.png"
|
||||
end
|
||||
|
||||
test "a non-map, non-nil payload raises rather than silently vanishing" do
|
||||
file = %{filename: "s.png", data: <<1>>}
|
||||
# A top-level list body encodes to a list, which must not be coerced to %{}.
|
||||
assert_raise FunctionClauseError, fn ->
|
||||
Endpoint.prepare_body(form_spec(), [%Dexcord.Test.Gadget{id: 1, name: "a"}],
|
||||
files: [file]
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "decode_response/2 (AC1.6 + passthrough)" do
|
||||
test "decodes a single map to the returns struct" do
|
||||
assert {:ok, %Dexcord.User{id: 1}} =
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue