From d56f2649995fea72207d8dfbbcf310c5947c1792 Mon Sep 17 00:00:00 2001 From: Fabio Pellegrini Date: Mon, 28 Apr 2025 16:04:31 +0100 Subject: [PATCH] fix: properly build open api spec for arrays --- lib/open_api/open_api.ex | 2 +- lib/open_api/type.ex | 6 +++--- test/unit/command/open_api/open_api_test.exs | 8 ++++---- test/unit/command/open_api/type_test.exs | 12 ++++++------ 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/lib/open_api/open_api.ex b/lib/open_api/open_api.ex index 2d89e88..e2895e8 100644 --- a/lib/open_api/open_api.ex +++ b/lib/open_api/open_api.ex @@ -126,7 +126,7 @@ defmodule EctoCommand.OpenApi do defp parse_option({:required, _}, acc), do: acc defp base_schema({:array, inner_type}, opts) do - %{type: :array, items: [schema_for(inner_type, Keyword.drop(opts, [:doc, :default]))]} + %{type: :array, items: schema_for(inner_type, Keyword.drop(opts, [:doc, :default]))} end defp base_schema(type, _opts), do: base_schema(type) diff --git a/lib/open_api/type.ex b/lib/open_api/type.ex index c9581b3..ae2b290 100644 --- a/lib/open_api/type.ex +++ b/lib/open_api/type.ex @@ -39,7 +39,7 @@ defmodule EctoCommand.OpenApi.Type do [example: true] ++ options end - def example_for(%Schema{type: :array, items: [%{enum: values}]} = _schema) when is_list(values), + def example_for(%Schema{type: :array, items: %{enum: values}} = _schema) when is_list(values), do: Enum.take(values, 2) def example_for(%Schema{default: default}) when not is_nil(default), do: default @@ -49,8 +49,8 @@ defmodule EctoCommand.OpenApi.Type do def example_for(%Schema{type: :string, format: :password}), do: Keyword.get(password(), :example) def example_for(%Schema{type: :integer} = schema), do: trunc(number_example(schema)) def example_for(%Schema{type: :number} = schema), do: number_example(schema) - def example_for(%Schema{type: :array, items: [%{example: nil}]}), do: [] - def example_for(%Schema{type: :array, items: [%{example: example}]}), do: [example] + def example_for(%Schema{type: :array, items: %{example: nil}}), do: [] + def example_for(%Schema{type: :array, items: %{example: example}}), do: [example] def example_for(%Schema{type: :object, properties: properties}) do Map.new(properties, fn {name, %Schema{example: example} = schema} -> diff --git a/test/unit/command/open_api/open_api_test.exs b/test/unit/command/open_api/open_api_test.exs index 816b370..b6af55b 100644 --- a/test/unit/command/open_api/open_api_test.exs +++ b/test/unit/command/open_api/open_api_test.exs @@ -119,25 +119,25 @@ defmodule Unit.EctoCommand.OpenApi.OpenApiTest do a_date: %OpenApiSpex.Schema{type: :string, format: :date, example: "2020-04-20"}, a_list_of_enums: %OpenApiSpex.Schema{ type: :array, - items: [%OpenApiSpex.Schema{enum: ["a", "b", "c"], type: :string, example: "a"}], + items: %OpenApiSpex.Schema{enum: ["a", "b", "c"], type: :string, example: "a"}, example: ["a", "b"], description: "A list of enums" }, a_list_of_strings_a: %OpenApiSpex.Schema{ type: :array, - items: [%OpenApiSpex.Schema{type: :string, example: ""}], + items: %OpenApiSpex.Schema{type: :string, example: ""}, default: [], example: [] }, a_list_of_strings_b: %OpenApiSpex.Schema{ type: :array, - items: [%OpenApiSpex.Schema{type: :string, example: ""}], + items: %OpenApiSpex.Schema{type: :string, example: ""}, description: "A list of strings A", example: [""] }, a_list_of_strings_c: %OpenApiSpex.Schema{ type: :array, - items: [%OpenApiSpex.Schema{enum: ["a", "b", "c"], type: :string, example: "a"}], + items: %OpenApiSpex.Schema{enum: ["a", "b", "c"], type: :string, example: "a"}, example: ["a", "b"], description: "A list of strings B" }, diff --git a/test/unit/command/open_api/type_test.exs b/test/unit/command/open_api/type_test.exs index db4e061..c41bddb 100644 --- a/test/unit/command/open_api/type_test.exs +++ b/test/unit/command/open_api/type_test.exs @@ -8,8 +8,8 @@ defmodule Unit.EctoCommand.OpenApi.TypeTest do describe "example_for/1 generates a valid example" do test "for arrays of enums" do - assert [1, 2] == Type.example_for(%Schema{type: :array, items: [%{type: :integer, enum: [1, 2, 3]}]}) - assert ["a", "b"] == Type.example_for(%Schema{type: :array, items: [%{type: :string, enum: ["a", "b", "c"]}]}) + assert [1, 2] == Type.example_for(%Schema{type: :array, items: %{type: :integer, enum: [1, 2, 3]}}) + assert ["a", "b"] == Type.example_for(%Schema{type: :array, items: %{type: :string, enum: ["a", "b", "c"]}}) end test "for enums" do @@ -138,16 +138,16 @@ defmodule Unit.EctoCommand.OpenApi.TypeTest do end test "for arrays without inner type example and without default" do - assert [] == Type.example_for(%Schema{type: :array, items: [%Schema{type: :integer}]}) + assert [] == Type.example_for(%Schema{type: :array, items: %Schema{type: :integer}}) end test "for arrays with inner type example and without default" do - assert [1] == Type.example_for(%Schema{type: :array, items: [%Schema{type: :integer, example: 1}]}) + assert [1] == Type.example_for(%Schema{type: :array, items: %Schema{type: :integer, example: 1}}) end test "for arrays with inner type example and with default" do assert [1, 2, 3] == - Type.example_for(%Schema{type: :array, items: [%Schema{type: :integer, example: 1}], default: [1, 2, 3]}) + Type.example_for(%Schema{type: :array, items: %Schema{type: :integer, example: 1}, default: [1, 2, 3]}) end test "for object" do @@ -159,7 +159,7 @@ defmodule Unit.EctoCommand.OpenApi.TypeTest do id: %OpenApiSpex.Schema{type: :string}, name: %OpenApiSpex.Schema{type: :string}, type: %OpenApiSpex.Schema{enum: ["a", "b"], type: :string, example: "a"}, - tags: %OpenApiSpex.Schema{type: :array, items: [%OpenApiSpex.Schema{type: :string}], default: []}, + tags: %OpenApiSpex.Schema{type: :array, items: %OpenApiSpex.Schema{type: :string}, default: []}, non_required_id: %OpenApiSpex.Schema{type: :string} } }