elixirphoenix-frameworkectophoenix-channelselixir-poison

How to test or serialize struct in Phoenix.Socket.Broadcast payload?


How to automatically serialize ecto struct to json response in channel test? As I can see in documentation The event’s message must be a serializable map, I found in answer and in tutorial that when I use Poison.Encoder in model then any message passed via Transport (as I understand) layer should be encoded.

Example model:

use PhoenixTrello.Web, :model
  # ...

  @derive {Poison.Encoder, only: [:id, :first_name, :last_name, :email]}

  # ...
end

broadcast from one of channel functions:

broadcast_from! socket, "card:created", %{card: card}

finally attempt to receive payload from broadcast in test:

assert_receive %Phoenix.Socket.Broadcast{topic: ^t1, event: "card:created", payload: ^payload}

then it rises not match error with not serialized struct in payload (I'm trying to match only derived model filelds):

Process mailbox:
  %Phoenix.Socket.Broadcast{event: "card:created", payload: %{card: %PhoenixTrello.Card{__meta__: #Ecto.Schema.Metadata<:loaded, "cards">, ... user: #Ecto.Association.NotLoaded<association :user is not loaded>, user_id: 1833}}, topic: "boards:1833"}

How to get serialized json message in test as if it was the client app?


Solution

  • I'd first assert_receive the raw message and then Poison.encode! and do a second assert:

    payload = "{\"card\": ...}"
    assert_receive %Phoenix.Socket.Broadcast{topic: ^t1, event: "card:created", payload: raw_payload}
    assert Poison.encode!(raw_payload) == payload