summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPierre de Lacroix <pierre@pdelacroix.com>2020-12-09 11:03:21 +0100
committerPierre de Lacroix <pierre@pdelacroix.com>2020-12-09 11:03:21 +0100
commit00c212554e24ea707499859b30f75374d4d3508a (patch)
tree3d8e4a69bf45e52c4fc1b79fa9c64388cbb19aee
parentupdate dependencies (diff)
add bridge context
-rw-r--r--config/config.exs3
-rw-r--r--config/test.exs12
-rw-r--r--lib/matrix_app_service/application.ex3
-rw-r--r--lib/matrix_app_service/bridge.ex3
-rw-r--r--lib/matrix_app_service/bridge/room.ex21
-rw-r--r--lib/matrix_app_service/bridge/user.ex21
-rw-r--r--lib/matrix_app_service/bridge_config.ex221
-rw-r--r--lib/matrix_app_service/migrations.ex26
-rw-r--r--lib/matrix_app_service/repo.ex5
-rw-r--r--mix.exs4
-rw-r--r--mix.lock2
-rw-r--r--priv/repo/migrations/20201209095612_migrate_itself.exs7
-rw-r--r--test/matrix_app_service/bridge_test.exs131
-rw-r--r--test/support/data_case.ex53
14 files changed, 510 insertions, 2 deletions
diff --git a/config/config.exs b/config/config.exs
index 8d782dc..692048a 100644
--- a/config/config.exs
+++ b/config/config.exs
@@ -7,6 +7,9 @@
# General application configuration
use Mix.Config
+config :matrix_app_service,
+ ecto_repos: [MatrixAppService.Repo]
+
# Configures the endpoint
config :matrix_app_service, MatrixAppServiceWeb.Endpoint,
url: [host: "localhost"],
diff --git a/config/test.exs b/config/test.exs
index ed14857..1402cf0 100644
--- a/config/test.exs
+++ b/config/test.exs
@@ -1,5 +1,17 @@
use Mix.Config
+# Configure your database
+#
+# The MIX_TEST_PARTITION environment variable can be used
+# to provide built-in test partitioning in CI environment.
+# Run `mix help test` for more information.
+config :matrix_app_service, MatrixAppService.Repo,
+ username: "postgres",
+ password: "postgres",
+ database: "matrix_app_service_test#{System.get_env("MIX_TEST_PARTITION")}",
+ hostname: "localhost",
+ pool: Ecto.Adapters.SQL.Sandbox
+
# We don't run a server during test. If one is required,
# you can enable the server option below.
config :matrix_app_service, MatrixAppServiceWeb.Endpoint,
diff --git a/lib/matrix_app_service/application.ex b/lib/matrix_app_service/application.ex
index 383c0f9..ae935eb 100644
--- a/lib/matrix_app_service/application.ex
+++ b/lib/matrix_app_service/application.ex
@@ -21,7 +21,8 @@ defmodule MatrixAppService.Application do
if start_endpoint?() do
[
# MatrixAppServiceWeb.Endpoint
- {MatrixAppServiceWeb.Endpoint, endpoint_config()}
+ {MatrixAppServiceWeb.Endpoint, endpoint_config()},
+ MatrixAppService.Repo
| children
]
else
diff --git a/lib/matrix_app_service/bridge.ex b/lib/matrix_app_service/bridge.ex
new file mode 100644
index 0000000..e0e0fee
--- /dev/null
+++ b/lib/matrix_app_service/bridge.ex
@@ -0,0 +1,3 @@
+defmodule MatrixAppService.Bridge do
+ use MatrixAppService.BridgeConfig, repo: MatrixAppService.Repo
+end
diff --git a/lib/matrix_app_service/bridge/room.ex b/lib/matrix_app_service/bridge/room.ex
new file mode 100644
index 0000000..c40e0ed
--- /dev/null
+++ b/lib/matrix_app_service/bridge/room.ex
@@ -0,0 +1,21 @@
+defmodule MatrixAppService.Bridge.Room do
+ use Ecto.Schema
+ import Ecto.Changeset
+
+ schema "rooms" do
+ field :data, :map
+ field :local_id, :string
+ field :remote_id, :string
+
+ timestamps()
+ end
+
+ @doc false
+ def changeset(room, attrs) do
+ room
+ |> cast(attrs, [:local_id, :remote_id, :data])
+ # |> validate_required([:local_id, :remote_id, :data])
+ |> unique_constraint(:local_id)
+ |> unique_constraint(:remote_id)
+ end
+end
diff --git a/lib/matrix_app_service/bridge/user.ex b/lib/matrix_app_service/bridge/user.ex
new file mode 100644
index 0000000..aaa3c46
--- /dev/null
+++ b/lib/matrix_app_service/bridge/user.ex
@@ -0,0 +1,21 @@
+defmodule MatrixAppService.Bridge.User do
+ use Ecto.Schema
+ import Ecto.Changeset
+
+ schema "users" do
+ field :data, :map
+ field :local_id, :string
+ field :remote_id, :string
+
+ timestamps()
+ end
+
+ @doc false
+ def changeset(user, attrs) do
+ user
+ |> cast(attrs, [:local_id, :remote_id, :data])
+ # |> validate_required([:local_id, :remote_id, :data])
+ |> unique_constraint(:local_id)
+ |> unique_constraint(:remote_id)
+ end
+end
diff --git a/lib/matrix_app_service/bridge_config.ex b/lib/matrix_app_service/bridge_config.ex
new file mode 100644
index 0000000..5356caf
--- /dev/null
+++ b/lib/matrix_app_service/bridge_config.ex
@@ -0,0 +1,221 @@
+defmodule MatrixAppService.BridgeConfig do
+ @moduledoc """
+ The Bridge config.
+ """
+
+ defmacro __using__([repo: repo]) do
+ quote bind_quoted: [repo: repo] do
+ @repo repo
+
+ import Ecto.Query, warn: false
+ # alias MatrixAppService.Repo
+
+ alias MatrixAppService.Bridge.User
+
+ @doc """
+ Returns the list of users.
+
+ ## Examples
+
+ iex> list_users()
+ [%User{}, ...]
+
+ """
+ def list_users do
+ @repo.all(User)
+ end
+
+ @doc """
+ Gets a single user.
+
+ Raises `Ecto.NoResultsError` if the User does not exist.
+
+ ## Examples
+
+ iex> get_user!(123)
+ %User{}
+
+ iex> get_user!(456)
+ ** (Ecto.NoResultsError)
+
+ """
+ def get_user!(id), do: @repo.get!(User, id)
+
+ def get_user_by_local_id(local_id), do: @repo.get_by(User, local_id: local_id) || %User{local_id: local_id}
+ def get_user_by_remote_id(remote_id), do: @repo.get_by(User, remote_id: remote_id) || %User{remote_id: remote_id}
+
+ @doc """
+ Creates a user.
+
+ ## Examples
+
+ iex> create_user(%{field: value})
+ {:ok, %User{}}
+
+ iex> create_user(%{field: bad_value})
+ {:error, %Ecto.Changeset{}}
+
+ """
+ def create_user(attrs \\ %{}) do
+ %User{}
+ |> User.changeset(attrs)
+ |> @repo.insert()
+ end
+
+ def upsert_user(attrs, selectors) do
+ with %User{} = user <- @repo.get_by(User, selectors) do
+ update_user(user, attrs)
+ else
+ _ ->
+ create_user(Enum.into(selectors, attrs, fn {k, v} -> {to_string(k), v} end))
+ end
+ end
+
+ @doc """
+ Updates a user.
+
+ ## Examples
+
+ iex> update_user(user, %{field: new_value})
+ {:ok, %User{}}
+
+ iex> update_user(user, %{field: bad_value})
+ {:error, %Ecto.Changeset{}}
+
+ """
+ def update_user(%User{} = user, attrs) do
+ user
+ |> User.changeset(attrs)
+ |> @repo.update()
+ end
+
+ @doc """
+ Deletes a user.
+
+ ## Examples
+
+ iex> delete_user(user)
+ {:ok, %User{}}
+
+ iex> delete_user(user)
+ {:error, %Ecto.Changeset{}}
+
+ """
+ def delete_user(%User{} = user) do
+ @repo.delete(user)
+ end
+
+ @doc """
+ Returns an `%Ecto.Changeset{}` for tracking user changes.
+
+ ## Examples
+
+ iex> change_user(user)
+ %Ecto.Changeset{data: %User{}}
+
+ """
+ def change_user(%User{} = user, attrs \\ %{}) do
+ User.changeset(user, attrs)
+ end
+
+ alias MatrixAppService.Bridge.Room
+
+ @doc """
+ Returns the list of rooms.
+
+ ## Examples
+
+ iex> list_rooms()
+ [%Room{}, ...]
+
+ """
+ def list_rooms do
+ @repo.all(Room)
+ end
+
+ @doc """
+ Gets a single room.
+
+ Raises `Ecto.NoResultsError` if the Room does not exist.
+
+ ## Examples
+
+ iex> get_room!(123)
+ %Room{}
+
+ iex> get_room!(456)
+ ** (Ecto.NoResultsError)
+
+ """
+ def get_room!(id), do: @repo.get!(Room, id)
+
+ def get_room_by_local_id(local_id), do: @repo.get_by(Room, local_id: local_id) || %Room{local_id: local_id}
+ def get_room_by_remote_id(remote_id), do: @repo.get_by(Room, remote_id: remote_id) || %Room{remote_id: remote_id}
+
+ @doc """
+ Creates a room.
+
+ ## Examples
+
+ iex> create_room(%{field: value})
+ {:ok, %Room{}}
+
+ iex> create_room(%{field: bad_value})
+ {:error, %Ecto.Changeset{}}
+
+ """
+ def create_room(attrs \\ %{}) do
+ %Room{}
+ |> Room.changeset(attrs)
+ |> @repo.insert()
+ end
+
+ @doc """
+ Updates a room.
+
+ ## Examples
+
+ iex> update_room(room, %{field: new_value})
+ {:ok, %Room{}}
+
+ iex> update_room(room, %{field: bad_value})
+ {:error, %Ecto.Changeset{}}
+
+ """
+ def update_room(%Room{} = room, attrs) do
+ room
+ |> Room.changeset(attrs)
+ |> @repo.update()
+ end
+
+ @doc """
+ Deletes a room.
+
+ ## Examples
+
+ iex> delete_room(room)
+ {:ok, %Room{}}
+
+ iex> delete_room(room)
+ {:error, %Ecto.Changeset{}}
+
+ """
+ def delete_room(%Room{} = room) do
+ @repo.delete(room)
+ end
+
+ @doc """
+ Returns an `%Ecto.Changeset{}` for tracking room changes.
+
+ ## Examples
+
+ iex> change_room(room)
+ %Ecto.Changeset{data: %Room{}}
+
+ """
+ def change_room(%Room{} = room, attrs \\ %{}) do
+ Room.changeset(room, attrs)
+ end
+ end
+ end
+end
diff --git a/lib/matrix_app_service/migrations.ex b/lib/matrix_app_service/migrations.ex
new file mode 100644
index 0000000..e6ce469
--- /dev/null
+++ b/lib/matrix_app_service/migrations.ex
@@ -0,0 +1,26 @@
+defmodule MatrixAppService.Migrations do
+ use Ecto.Migration
+
+ def change do
+ create table(:users) do
+ add :local_id, :string
+ add :remote_id, :string
+ add :data, :map
+
+ timestamps()
+ end
+ create unique_index(:users, [:local_id])
+ create unique_index(:users, [:remote_id])
+
+
+ create table(:rooms) do
+ add :local_id, :string
+ add :remote_id, :string
+ add :data, :map
+
+ timestamps()
+ end
+ create unique_index(:rooms, [:local_id])
+ create unique_index(:rooms, [:remote_id])
+ end
+end
diff --git a/lib/matrix_app_service/repo.ex b/lib/matrix_app_service/repo.ex
new file mode 100644
index 0000000..c52348a
--- /dev/null
+++ b/lib/matrix_app_service/repo.ex
@@ -0,0 +1,5 @@
+defmodule MatrixAppService.Repo do
+ use Ecto.Repo,
+ otp_app: :matrix_app_service,
+ adapter: Ecto.Adapters.Postgres
+end
diff --git a/mix.exs b/mix.exs
index bb0fe80..e0cffe4 100644
--- a/mix.exs
+++ b/mix.exs
@@ -59,11 +59,13 @@ defmodule MatrixAppService.MixProject do
{:telemetry_poller, "~> 0.4"},
{:jason, "~> 1.0"},
{:plug_cowboy, "~> 2.0"},
+ {:phoenix_ecto, "~> 4.1"},
{:ecto_sql, "~> 3.4"},
{:polyjuice_client, "~> 0.3.1"},
{:ex_doc, "~> 0.22", only: :dev, runtime: false},
{:junit_formatter, "~> 3.1", only: :test},
- {:cobertura_cover, "~> 0.9.0", only: :test}
+ {:cobertura_cover, "~> 0.9.0", only: :test},
+ {:postgrex, ">= 0.0.0", only: :test}
]
end
diff --git a/mix.lock b/mix.lock
index 951e330..9782076 100644
--- a/mix.lock
+++ b/mix.lock
@@ -24,6 +24,7 @@
"nimble_parsec": {:hex, :nimble_parsec, "1.1.0", "3a6fca1550363552e54c216debb6a9e95bd8d32348938e13de5eda962c0d7f89", [:mix], [], "hexpm", "08eb32d66b706e913ff748f11694b17981c0b04a33ef470e33e11b3d3ac8f54b"},
"parse_trans": {:hex, :parse_trans, "3.3.0", "09765507a3c7590a784615cfd421d101aec25098d50b89d7aa1d66646bc571c1", [:rebar3], [], "hexpm", "17ef63abde837ad30680ea7f857dd9e7ced9476cdd7b0394432af4bfc241b960"},
"phoenix": {:hex, :phoenix, "1.5.7", "2923bb3af924f184459fe4fa4b100bd25fa6468e69b2803dfae82698269aa5e0", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix_html, "~> 2.13", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 2.0", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:plug, "~> 1.10", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 1.0 or ~> 2.2", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:plug_crypto, "~> 1.1.2 or ~> 1.2", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "774cd64417c5a3788414fdbb2be2eb9bcd0c048d9e6ad11a0c1fd67b7c0d0978"},
+ "phoenix_ecto": {:hex, :phoenix_ecto, "4.2.1", "13f124cf0a3ce0f1948cf24654c7b9f2347169ff75c1123f44674afee6af3b03", [:mix], [{:ecto, "~> 3.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.14.2 or ~> 2.15", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "478a1bae899cac0a6e02be1deec7e2944b7754c04e7d4107fc5a517f877743c0"},
"phoenix_pubsub": {:hex, :phoenix_pubsub, "2.0.0", "a1ae76717bb168cdeb10ec9d92d1480fec99e3080f011402c0a2d68d47395ffb", [:mix], [], "hexpm", "c52d948c4f261577b9c6fa804be91884b381a7f8f18450c5045975435350f771"},
"plug": {:hex, :plug, "1.11.0", "f17217525597628298998bc3baed9f8ea1fa3f1160aa9871aee6df47a6e4d38e", [:mix], [{:mime, "~> 1.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.1.1 or ~> 1.2", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "2d9c633f0499f9dc5c2fd069161af4e2e7756890b81adcbb2ceaa074e8308876"},
"plug_cowboy": {:hex, :plug_cowboy, "2.4.1", "779ba386c0915027f22e14a48919a9545714f849505fa15af2631a0d298abf0f", [:mix], [{:cowboy, "~> 2.7", [hex: :cowboy, repo: "hexpm", optional: false]}, {:cowboy_telemetry, "~> 0.3", [hex: :cowboy_telemetry, repo: "hexpm", optional: false]}, {:plug, "~> 1.7", [hex: :plug, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "d72113b6dff7b37a7d9b2a5b68892808e3a9a752f2bf7e503240945385b70507"},
@@ -32,6 +33,7 @@
"polyjuice_client": {:hex, :polyjuice_client, "0.3.1", "cc312602a8da0d4d61b0a890bb72d9c6662f17cd0fc5782d8f7358274e3e6e4b", [:mix], [{:hackney, "~> 1.12", [hex: :hackney, repo: "hexpm", optional: false]}, {:jason, "~> 1.2", [hex: :jason, repo: "hexpm", optional: false]}, {:mutex, "~> 1.1.3", [hex: :mutex, repo: "hexpm", optional: false]}, {:polyjuice_util, "~> 0.1.0", [hex: :polyjuice_util, repo: "hexpm", optional: false]}], "hexpm", "e9585faab7562cac3e91a64d328905cefabc74219fafa9e77e09f4e5e4e82957"},
"polyjuice_util": {:hex, :polyjuice_util, "0.1.0", "69901959c143245b47829c8302d0605dff6c0e1c3b116730c162982e0f512ee0", [:mix], [], "hexpm", "af5d1f614f52ce1da59a1f5a7c49249a2dbfda279d99d52d1b4e83e84c19a8d5"},
"poolboy": {:hex, :poolboy, "1.5.2", "392b007a1693a64540cead79830443abf5762f5d30cf50bc95cb2c1aaafa006b", [:rebar3], [], "hexpm", "dad79704ce5440f3d5a3681c8590b9dc25d1a561e8f5a9c995281012860901e3"},
+ "postgrex": {:hex, :postgrex, "0.15.7", "724410acd48abac529d0faa6c2a379fb8ae2088e31247687b16cacc0e0883372", [:mix], [{:connection, "~> 1.0", [hex: :connection, repo: "hexpm", optional: false]}, {:db_connection, "~> 2.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.5 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm", "88310c010ff047cecd73d5ceca1d99205e4b1ab1b9abfdab7e00f5c9d20ef8f9"},
"ranch": {:hex, :ranch, "1.7.1", "6b1fab51b49196860b733a49c07604465a47bdb78aa10c1c16a3d199f7f8c881", [:rebar3], [], "hexpm", "451d8527787df716d99dc36162fca05934915db0b6141bbdac2ea8d3c7afc7d7"},
"ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.6", "cf344f5692c82d2cd7554f5ec8fd961548d4fd09e7d22f5b62482e5aeaebd4b0", [:make, :mix, :rebar3], [], "hexpm", "bdb0d2471f453c88ff3908e7686f86f9be327d065cc1ec16fa4540197ea04680"},
"telemetry": {:hex, :telemetry, "0.4.2", "2808c992455e08d6177322f14d3bdb6b625fbcfd233a73505870d8738a2f4599", [:rebar3], [], "hexpm", "2d1419bd9dda6a206d7b5852179511722e2b18812310d304620c7bd92a13fcef"},
diff --git a/priv/repo/migrations/20201209095612_migrate_itself.exs b/priv/repo/migrations/20201209095612_migrate_itself.exs
new file mode 100644
index 0000000..04df688
--- /dev/null
+++ b/priv/repo/migrations/20201209095612_migrate_itself.exs
@@ -0,0 +1,7 @@
+defmodule MatrixAppService.Repo.Migrations.MigrateItself do
+ use Ecto.Migration
+
+ def change do
+ MatrixAppService.Migrations.change()
+ end
+end
diff --git a/test/matrix_app_service/bridge_test.exs b/test/matrix_app_service/bridge_test.exs
new file mode 100644
index 0000000..46acffb
--- /dev/null
+++ b/test/matrix_app_service/bridge_test.exs
@@ -0,0 +1,131 @@
+defmodule MatrixAppService.BridgeTest do
+ use MatrixAppService.DataCase
+
+ alias MatrixAppService.Bridge
+
+ describe "users" do
+ alias MatrixAppService.Bridge.User
+
+ @valid_attrs %{data: %{}, local_id: "some local_id", remote_id: "some remote_id"}
+ @update_attrs %{data: %{}, local_id: "some updated local_id", remote_id: "some updated remote_id"}
+ # @invalid_attrs %{data: nil, local_id: nil, remote_id: nil}
+
+ def user_fixture(attrs \\ %{}) do
+ {:ok, user} =
+ attrs
+ |> Enum.into(@valid_attrs)
+ |> Bridge.create_user()
+
+ user
+ end
+
+ test "list_users/0 returns all users" do
+ user = user_fixture()
+ assert Bridge.list_users() == [user]
+ end
+
+ test "get_user!/1 returns the user with given id" do
+ user = user_fixture()
+ assert Bridge.get_user!(user.id) == user
+ end
+
+ test "create_user/1 with valid data creates a user" do
+ assert {:ok, %User{} = user} = Bridge.create_user(@valid_attrs)
+ assert user.data == %{}
+ assert user.local_id == "some local_id"
+ assert user.remote_id == "some remote_id"
+ end
+
+# test "create_user/1 with invalid data returns error changeset" do
+# assert {:error, %Ecto.Changeset{}} = Bridge.create_user(@invalid_attrs)
+# end
+
+ test "update_user/2 with valid data updates the user" do
+ user = user_fixture()
+ assert {:ok, %User{} = user} = Bridge.update_user(user, @update_attrs)
+ assert user.data == %{}
+ assert user.local_id == "some updated local_id"
+ assert user.remote_id == "some updated remote_id"
+ end
+
+# test "update_user/2 with invalid data returns error changeset" do
+# user = user_fixture()
+# assert {:error, %Ecto.Changeset{}} = Bridge.update_user(user, @invalid_attrs)
+# assert user == Bridge.get_user!(user.id)
+# end
+
+ test "delete_user/1 deletes the user" do
+ user = user_fixture()
+ assert {:ok, %User{}} = Bridge.delete_user(user)
+ assert_raise Ecto.NoResultsError, fn -> Bridge.get_user!(user.id) end
+ end
+
+ test "change_user/1 returns a user changeset" do
+ user = user_fixture()
+ assert %Ecto.Changeset{} = Bridge.change_user(user)
+ end
+ end
+
+ describe "rooms" do
+ alias MatrixAppService.Bridge.Room
+
+ @valid_attrs %{data: %{}, local_id: "some local_id", remote_id: "some remote_id"}
+ @update_attrs %{data: %{}, local_id: "some updated local_id", remote_id: "some updated remote_id"}
+ # @invalid_attrs %{data: nil, local_id: nil, remote_id: nil}
+
+ def room_fixture(attrs \\ %{}) do
+ {:ok, room} =
+ attrs
+ |> Enum.into(@valid_attrs)
+ |> Bridge.create_room()
+
+ room
+ end
+
+ test "list_rooms/0 returns all rooms" do
+ room = room_fixture()
+ assert Bridge.list_rooms() == [room]
+ end
+
+ test "get_room!/1 returns the room with given id" do
+ room = room_fixture()
+ assert Bridge.get_room!(room.id) == room
+ end
+
+ test "create_room/1 with valid data creates a room" do
+ assert {:ok, %Room{} = room} = Bridge.create_room(@valid_attrs)
+ assert room.data == %{}
+ assert room.local_id == "some local_id"
+ assert room.remote_id == "some remote_id"
+ end
+
+# test "create_room/1 with invalid data returns error changeset" do
+# assert {:error, %Ecto.Changeset{}} = Bridge.create_room(@invalid_attrs)
+# end
+
+ test "update_room/2 with valid data updates the room" do
+ room = room_fixture()
+ assert {:ok, %Room{} = room} = Bridge.update_room(room, @update_attrs)
+ assert room.data == %{}
+ assert room.local_id == "some updated local_id"
+ assert room.remote_id == "some updated remote_id"
+ end
+
+# test "update_room/2 with invalid data returns error changeset" do
+# room = room_fixture()
+# assert {:error, %Ecto.Changeset{}} = Bridge.update_room(room, @invalid_attrs)
+# assert room == Bridge.get_room!(room.id)
+# end
+
+ test "delete_room/1 deletes the room" do
+ room = room_fixture()
+ assert {:ok, %Room{}} = Bridge.delete_room(room)
+ assert_raise Ecto.NoResultsError, fn -> Bridge.get_room!(room.id) end
+ end
+
+ test "change_room/1 returns a room changeset" do
+ room = room_fixture()
+ assert %Ecto.Changeset{} = Bridge.change_room(room)
+ end
+ end
+end
diff --git a/test/support/data_case.ex b/test/support/data_case.ex
new file mode 100644
index 0000000..475f748
--- /dev/null
+++ b/test/support/data_case.ex
@@ -0,0 +1,53 @@
+defmodule MatrixAppService.DataCase do
+ @moduledoc """
+ This module defines the setup for tests requiring
+ access to the application's data layer.
+ You may define functions here to be used as helpers in
+ your tests.
+ Finally, if the test case interacts with the database,
+ it cannot be async. For this reason, every test runs
+ inside a transaction which is reset at the beginning
+ of the test unless the test case is marked as async.
+ """
+
+ use ExUnit.CaseTemplate
+
+ alias Ecto.Adapters.SQL.Sandbox
+ alias Ecto.Changeset
+ alias MatrixAppService.Repo
+
+ using do
+ quote do
+ alias MatrixAppService.Repo
+
+ import Ecto
+ import Ecto.Changeset
+ import Ecto.Query
+ import MatrixAppService.DataCase
+ end
+ end
+
+ setup tags do
+ :ok = Sandbox.checkout(Repo)
+
+ unless tags[:async] do
+ Sandbox.mode(Repo, {:shared, self()})
+ end
+
+ :ok
+ end
+
+ @doc """
+ A helper that transform changeset errors to a map of messages.
+ assert {:error, changeset} = Accounts.create_user(%{password: "short"})
+ assert "password is too short" in errors_on(changeset).password
+ assert %{password: ["password is too short"]} = errors_on(changeset)
+ """
+ def errors_on(changeset) do
+ Changeset.traverse_errors(changeset, fn {message, opts} ->
+ Enum.reduce(opts, message, fn {key, value}, acc ->
+ String.replace(acc, "%{#{key}}", to_string(value))
+ end)
+ end)
+ end
+end