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

fix(#567): validation error array query params #568

Open
wants to merge 2 commits into
base: master
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
15 changes: 14 additions & 1 deletion lib/open_api_spex/cast_parameters.ex
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,12 @@ defmodule OpenApiSpex.CastParameters do
end

defp get_params_by_location(conn, :query, _) do
Plug.Conn.fetch_query_params(conn).query_params
params = Plug.Conn.fetch_query_params(conn).query_params

Enum.reduce(params, %{}, fn param, acc ->
{updated_key, updated_value} = parse_query_param(param)
Map.update(acc, updated_key, updated_value, &[&1 | updated_value])
end)
end

defp get_params_by_location(conn, :path, _) do
Expand All @@ -61,6 +66,14 @@ defmodule OpenApiSpex.CastParameters do
do: {property_name, value}
end

defp parse_query_param({key, value}) when is_list(value) do
{"#{key}[]", value}
end

defp parse_query_param(param) do
param
end

defp create_location_schema(parameters, components) do
{
%Schema{
Expand Down
42 changes: 35 additions & 7 deletions test/operation2_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,12 @@ defmodule OpenApiSpex.Operation2Test do
@user_index %Operation{
operationId: "UserController.index",
parameters: [
Operation.parameter(
:"ids[]",
:query,
%Schema{type: :array, items: %Schema{type: :integer}},
"Filter by user ids"
),
Operation.parameter(:name, :query, :string, "Filter by user name"),
Operation.parameter(:age, :query, :integer, "Filter by user age"),
%Reference{"$ref": "#/components/parameters/member"},
Expand Down Expand Up @@ -299,29 +305,51 @@ defmodule OpenApiSpex.Operation2Test do
end

test "casts valid query params and respects defaults" do
valid_query_params = %{"name" => "Rubi", "age" => "31", "member" => "true"}
valid_query_params = %{"ids[]" => 1, "name" => "Rubi", "age" => "31", "member" => "true"}
assert {:ok, conn} = do_index_cast(valid_query_params)
assert conn.params == %{age: 31, member: true, name: "Rubi", include_archived: false}

assert conn.params == %{
"ids[]": [1],
age: 31,
member: true,
name: "Rubi",
include_archived: false
}
end

test "casts valid query params and overrides defaults" do
valid_query_params = %{
"ids[]" => 1,
"name" => "Rubi",
"age" => "31",
"member" => "true",
"include_archived" => "true"
}

assert {:ok, conn} = do_index_cast(valid_query_params)
assert conn.params == %{age: 31, member: true, name: "Rubi", include_archived: true}

assert conn.params == %{
"ids[]": [1],
age: 31,
member: true,
name: "Rubi",
include_archived: true
}
end

test "cast valid query params with replace_params: false" do
valid_query_params = %{"name" => "Rubi", "age" => "31", "member" => "true"}
valid_query_params = %{"ids[]" => 1, "name" => "Rubi", "age" => "31", "member" => "true"}
assert {:ok, conn} = do_index_cast(valid_query_params, replace_params: false)
assert Plug.Conn.fetch_query_params(conn).params == valid_query_params

assert Plug.Conn.fetch_query_params(conn).params == %{
"ids" => ["1"],
"name" => "Rubi",
"age" => "31",
"member" => "true"
}

assert conn.private.open_api_spex.params == %{
"ids[]": [1],
age: 31,
member: true,
name: "Rubi",
Expand All @@ -330,9 +358,9 @@ defmodule OpenApiSpex.Operation2Test do
end

test "casts valid query params without applying defaults" do
valid_query_params = %{"name" => "Rubi", "age" => "31", "member" => "true"}
valid_query_params = %{"ids[]" => 1, "name" => "Rubi", "age" => "31", "member" => "true"}
assert {:ok, conn} = do_index_cast(valid_query_params, apply_defaults: false)
assert conn.params == %{age: 31, member: true, name: "Rubi"}
assert conn.params == %{"ids[]": [1], age: 31, member: true, name: "Rubi"}
end

test "validate invalid data type for query param" do
Expand Down
12 changes: 12 additions & 0 deletions test/plug/cast_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,18 @@ defmodule OpenApiSpex.Plug.CastTest do
assert OpenApiSpex.params(conn) == %{validParam: true}
end

test "ids[] param" do
conn =
:get
|> Plug.Test.conn("/api/users?ids[]=123")
|> OpenApiSpexTest.Router.call([])

assert conn.status == 200
assert conn.private.open_api_spex.params == conn.params

assert OpenApiSpex.params(conn) == %{"ids[]": [123]}
end

test "valid param with replace_params false" do
conn =
:get
Expand Down
10 changes: 8 additions & 2 deletions test/support/user_controller.ex
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ defmodule OpenApiSpexTest.UserController do
Show a user by ID
"""
@doc parameters: [
id: [
ids: [
in: :path,
type: %Schema{type: :integer, minimum: 1},
description: "User ID",
Expand All @@ -41,7 +41,13 @@ defmodule OpenApiSpexTest.UserController do
List all users
"""
@doc parameters: [
validParam: [in: :query, type: :boolean, description: "Valid Param", example: true]
validParam: [in: :query, type: :boolean, description: "Valid Param", example: true],
"ids[]": [
in: :query,
type: %Schema{type: :array, items: %Schema{type: :integer}},
description: "User IDs",
example: 123
]
],
responses: [
ok: {"User List Response", "application/json", Schemas.UsersResponse}
Expand Down
Loading