From 1ae326f1e6d670681a6634013e7bad4288b08547 Mon Sep 17 00:00:00 2001 From: doorgan Date: Thu, 6 Jun 2024 19:25:53 -0300 Subject: [PATCH] Fix string vs atom keys issue --- lib/channel_spec/testing.ex | 4 +- mix.exs | 2 +- test/channel_spec/testing_test.exs | 76 ++++++++++++++++++++++++++++++ 3 files changed, 80 insertions(+), 2 deletions(-) diff --git a/lib/channel_spec/testing.ex b/lib/channel_spec/testing.ex index 6b05e8d..018fb05 100644 --- a/lib/channel_spec/testing.ex +++ b/lib/channel_spec/testing.ex @@ -106,6 +106,8 @@ defmodule ChannelSpec.Testing do socket = Process.get(unquote(ref)) assert_reply(unquote(ref), unquote(status), reply = unquote(reply)) + normalized_reply = reply |> Jason.encode!() |> Jason.decode!() + with true <- function_exported?(socket.handler, :__socket_schemas__, 0), socket_schema = socket.handler.__socket_schemas__(), topic = socket.assigns.__channel_topic__, @@ -113,7 +115,7 @@ defmodule ChannelSpec.Testing do status = to_string(unquote(status)), %{} = schema <- socket_schema["channels"][topic]["messages"][event]["replies"][status] do - case Xema.validate(schema, reply) do + case Xema.validate(schema, normalized_reply) do :ok -> :ok diff --git a/mix.exs b/mix.exs index e7829a7..d9b1f4a 100644 --- a/mix.exs +++ b/mix.exs @@ -23,7 +23,7 @@ defmodule ChannelSpec.MixProject do {:mneme, "~> 0.5", only: [:dev, :test]}, {:json_xema, "~> 0.6"}, {:phoenix, "~> 1.7"}, - {:xema, "~> 0.17"} + {:xema, "~> 0.17.2"} ] end diff --git a/test/channel_spec/testing_test.exs b/test/channel_spec/testing_test.exs index d156a2f..1ca9aac 100644 --- a/test/channel_spec/testing_test.exs +++ b/test/channel_spec/testing_test.exs @@ -122,6 +122,82 @@ defmodule ChannelSpec.TestingTest do assert error.message =~ "Channel reply doesn't match reply spec for status ok" end + @tag :capture_log + test "validates atom or string keys in the payload", %{mod: mod} do + defmodule :"#{mod}.ReplySchema" do + def schema() do + %{ + type: :object, + properties: %{foo: %{type: :object, properties: %{bar: %{type: :integer}}}} + } + end + end + + defmodule :"#{mod}.RoomChannel.Handler" do + use ChannelHandler.Handler + use ChannelSpec.Operations + + operation :msg, + payload: %{type: :object, properties: %{body: %{type: :string}}, required: [:body]}, + replies: %{ + ok: %{"$ref": :"#{mod}.ReplySchema"} + } + + def msg(%{"body" => "atom"}, _, socket) do + {:reply, {:ok, %{foo: %{bar: 123}}}, socket} + end + + def msg(%{"body" => "string"}, _, socket) do + {:reply, {:ok, %{"foo" => %{"bar" => 123}}}, socket} + end + end + + defmodule :"#{mod}.RoomChannel" do + use Phoenix.Channel + use ChannelHandler.Router + + def join("room:" <> _, _params, socket) do + {:ok, socket} + end + + event "new_msg", :"#{mod}.RoomChannel.Handler", :msg + end + + defmodule :"#{mod}.UserSocket" do + use ChannelSpec.Socket + + channel "room:*", :"#{mod}.RoomChannel" + end + + defmodule :"#{mod}.Endpoint" do + use Phoenix.Endpoint, otp_app: :channel_spec + + Phoenix.Endpoint.socket("/socket", :"#{mod}.UserSocket") + + defoverridable config: 1, config: 2 + def config(:pubsub_server), do: __MODULE__.PubSub + def config(which), do: super(which) + def config(which, default), do: super(which, default) + end + + start_supervised({Phoenix.PubSub, name: :"#{mod}.Endpoint.PubSub"}) + + {:ok, _endpoint_pid} = start_supervised(:"#{mod}.Endpoint") + + {:ok, _, socket} = + :"#{mod}.UserSocket" + |> build_socket("room:123", %{}, :"#{mod}.Endpoint") + |> subscribe_and_join(:"#{mod}.RoomChannel", "room:123") + + ref = push(socket, "new_msg", %{"body" => "atom"}) + + assert_reply_spec ref, :ok, %{foo: %{bar: 123}} + + ref = push(socket, "new_msg", %{"body" => "string"}) + + assert_reply_spec ref, :ok, %{"foo" => %{"bar" => 123}} + end + @tag :capture_log test "validates response against the schema in a handler module", %{mod: mod} do defmodule :"#{mod}.RoomChannel.Handler" do