Skip to content

Commit

Permalink
fix: Improve coverage of Realtime.API tests
Browse files Browse the repository at this point in the history
We lacked tests for one of the functions from Realtime.API. Added said coverage and refactored tests a bit
  • Loading branch information
filipecabaco committed Aug 22, 2023
1 parent 3959454 commit d6df7b6
Show file tree
Hide file tree
Showing 3 changed files with 106 additions and 92 deletions.
7 changes: 7 additions & 0 deletions lib/realtime/api.ex
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,13 @@ defmodule Realtime.Api do
|> repo_replica.preload(:extensions)
end

@doc """
Returns list of tenants with filter options:
* order_by
* search external id
* limit
* ordering (desc / asc)
"""
def list_tenants(opts) when is_list(opts) do
repo_replica = Repo.replica()

Expand Down
2 changes: 1 addition & 1 deletion mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ defmodule Realtime.MixProject do
def project do
[
app: :realtime,
version: "2.20.3",
version: "2.20.4",
elixir: "~> 1.14.0",
elixirc_paths: elixirc_paths(Mix.env()),
start_permanent: Mix.env() == :prod,
Expand Down
189 changes: 98 additions & 91 deletions test/realtime/api_test.exs
Original file line number Diff line number Diff line change
@@ -1,73 +1,90 @@
defmodule Realtime.ApiTest do
use Realtime.DataCase
use Realtime.DataCase, async: false

import Mock

alias Realtime.Api
alias Realtime.{Api, RateCounter, GenCounter}
alias Realtime.Api.Extensions
alias Realtime.Api.Tenant
alias Realtime.GenCounter
alias Realtime.RateCounter

@db_conf Application.compile_env(:realtime, Realtime.Repo)

@valid_attrs %{
external_id: "external_id",
name: "localhost",
extensions: [
%{
"type" => "postgres_cdc_rls",
"settings" => %{
"db_host" => @db_conf[:hostname],
"db_name" => @db_conf[:database],
"db_user" => @db_conf[:username],
"db_password" => @db_conf[:password],
"db_port" => "5432",
"poll_interval" => 100,
"poll_max_changes" => 100,
"poll_max_record_bytes" => 1_048_576,
"region" => "us-east-1"
}
}
],
postgres_cdc_default: "postgres_cdc_rls",
jwt_secret: "new secret",
max_concurrent_users: 200,
max_events_per_second: 100
}

@update_attrs %{
external_id: "external_id1",
jwt_secret: "some updated jwt_secret",
name: "some updated name"
}
@invalid_attrs %{external_id: nil, jwt_secret: nil, name: nil}

setup do
tenants = [
tenant_fixture(%{external_id: "external_id1", max_concurrent_users: 10}),
tenant_fixture(%{external_id: "external_id2", max_concurrent_users: 5}),
tenant_fixture(%{external_id: "external_id3", max_concurrent_users: 15}),
tenant_fixture(%{external_id: "external_id4", max_concurrent_users: 20}),
tenant_fixture(%{external_id: "external_id5", max_concurrent_users: 25})
]

dev_tenant = Api.list_tenants(search: "dev_tenant")
tenants = tenants ++ dev_tenant

%{tenants: tenants}
end

describe "tenants" do
alias Realtime.Api.{Tenant, Extensions}
db_conf = Application.compile_env(:realtime, Realtime.Repo)

@valid_attrs %{
external_id: "external_id",
name: "localhost",
extensions: [
%{
"type" => "postgres_cdc_rls",
"settings" => %{
"db_host" => db_conf[:hostname],
"db_name" => db_conf[:database],
"db_user" => db_conf[:username],
"db_password" => db_conf[:password],
"db_port" => "5432",
"poll_interval" => 100,
"poll_max_changes" => 100,
"poll_max_record_bytes" => 1_048_576,
"region" => "us-east-1"
}
}
],
postgres_cdc_default: "postgres_cdc_rls",
jwt_secret: "new secret",
max_concurrent_users: 200,
max_events_per_second: 100
}

@update_attrs %{
external_id: "external_id",
jwt_secret: "some updated jwt_secret",
name: "some updated name"
}
@invalid_attrs %{external_id: nil, jwt_secret: nil, name: nil}

def tenant_fixture(attrs \\ %{}) do
{:ok, tenant} =
attrs
|> Enum.into(@valid_attrs)
|> Api.create_tenant()

tenant
test "list_tenants/0 returns all tenants", %{tenants: tenants} do
assert Enum.sort(Api.list_tenants()) == Enum.sort(tenants)
end

test "list_tenants/0 returns all tenants" do
tenant = tenant_fixture()
test "list_tenants/1 returns filtered tenants", %{tenants: tenants} do
assert hd(Api.list_tenants(search: hd(tenants).external_id)) == hd(tenants)

assert Api.list_tenants() |> Enum.filter(fn e -> e.external_id == "external_id" end) == [
tenant
]
end
assert Api.list_tenants(order_by: "max_concurrent_users") ==
Enum.sort_by(tenants, & &1.max_concurrent_users, :desc)

test "get_tenant!/1 returns the tenant with given id" do
tenant = tenant_fixture()
assert Api.list_tenants(order_by: "max_concurrent_users", order: "asc") ==
Enum.sort_by(tenants, & &1.max_concurrent_users, :asc)

assert Api.get_tenant!(tenant.id) |> Map.delete(:extensions) ==
tenant |> Map.delete(:extensions)
assert Api.list_tenants(order_by: "max_concurrent_users", order: "asc", limit: 2) ==
tenants |> Enum.sort_by(& &1.max_concurrent_users, :asc) |> Enum.take(2)
end

test "get_tenant!/1 returns the tenant with given id", %{tenants: [tenant | _]} do
result = Api.get_tenant!(tenant.id) |> Map.delete(:extensions)
expected = tenant |> Map.delete(:extensions)
assert result == expected
end

test "create_tenant/1 with valid data creates a tenant" do
assert {:ok, %Tenant{} = tenant} = Api.create_tenant(@valid_attrs)

assert tenant.external_id == "external_id"
assert tenant.jwt_secret == "YIriPuuJO1uerq5hSZ1W5Q=="
assert tenant.name == "localhost"
Expand All @@ -77,73 +94,54 @@ defmodule Realtime.ApiTest do
assert {:error, %Ecto.Changeset{}} = Api.create_tenant(@invalid_attrs)
end

test "check get_tenant_by_external_id/1" do
tenant_fixture()

test "check get_tenant_by_external_id/1", %{tenants: [tenant | _]} do
%Tenant{extensions: [%Extensions{} = extension]} =
Api.get_tenant_by_external_id("external_id")
Api.get_tenant_by_external_id(tenant.external_id)

assert Map.has_key?(extension.settings, "db_password")
password = extension.settings["db_password"]
assert ^password = "v1QVng3N+pZd/0AEObABwg=="
end

test "update_tenant/2 with valid data updates the tenant" do
tenant = tenant_fixture()
assert {:ok, %Tenant{} = tenant} = Api.update_tenant(tenant, @update_attrs)
assert tenant.external_id == "external_id"
test "update_tenant/2 with valid data updates the tenant", %{tenants: [tenant | _]} do
db_enc_key = Application.get_env(:realtime, :db_enc_key)

assert tenant.jwt_secret ==
Realtime.Helpers.encrypt!(
"some updated jwt_secret",
Application.get_env(:realtime, :db_enc_key)
)
assert {:ok, %Tenant{} = tenant} = Api.update_tenant(tenant, @update_attrs)
assert tenant.external_id == "external_id1"

assert tenant.jwt_secret == Realtime.Helpers.encrypt!("some updated jwt_secret", db_enc_key)
assert tenant.name == "some updated name"
end

test "update_tenant/2 with invalid data returns error changeset" do
tenant = tenant_fixture()
test "update_tenant/2 with invalid data returns error changeset", %{tenants: [tenant | _]} do
assert {:error, %Ecto.Changeset{}} = Api.update_tenant(tenant, @invalid_attrs)
end

test "delete_tenant/1 deletes the tenant" do
tenant = tenant_fixture()
test "delete_tenant/1 deletes the tenant", %{tenants: [tenant | _]} do
assert {:ok, %Tenant{}} = Api.delete_tenant(tenant)
assert_raise Ecto.NoResultsError, fn -> Api.get_tenant!(tenant.id) end
end

test "delete_tenant_by_external_id/1 deletes the tenant" do
tenant = tenant_fixture()
test "delete_tenant_by_external_id/1 deletes the tenant", %{tenants: [tenant | _]} do
assert true == Api.delete_tenant_by_external_id(tenant.external_id)
assert false == Api.delete_tenant_by_external_id("undef_tenant")
assert_raise Ecto.NoResultsError, fn -> Api.get_tenant!(tenant.id) end
end

test "change_tenant/1 returns a tenant changeset" do
tenant = tenant_fixture()
test "change_tenant/1 returns a tenant changeset", %{tenants: [tenant | _]} do
assert %Ecto.Changeset{} = Api.change_tenant(tenant)
end

test "list_extensions/1 " do
assert length(Api.list_extensions()) == 1
test "list_extensions/1 ", %{tenants: tenants} do
assert length(Api.list_extensions()) == length(tenants)
end

test "preload_counters/1 " do
tenant = tenant_fixture()
test "preload_counters/1 ", %{tenants: [tenant | _]} do
assert Api.preload_counters(nil) == nil

with_mocks([
{GenCounter, [],
[
get: fn _ ->
{:ok, 1}
end
]},
{RateCounter, [],
[
get: fn _ -> {:ok, %RateCounter{avg: 2}} end
]}
{GenCounter, [], [get: fn _ -> {:ok, 1} end]},
{RateCounter, [], [get: fn _ -> {:ok, %RateCounter{avg: 2}} end]}
]) do
counters = Api.preload_counters(tenant)
assert counters.events_per_second_rolling == 2
Expand All @@ -153,9 +151,18 @@ defmodule Realtime.ApiTest do
assert Api.preload_counters(nil, :any) == nil
end

test "rename_settings_field/2" do
test "rename_settings_field/2", %{tenants: [tenant | _]} do
Api.rename_settings_field("poll_interval_ms", "poll_interval")
assert %{extensions: [%{settings: %{"poll_interval" => _}}]} = tenant_fixture()
assert %{extensions: [%{settings: %{"poll_interval" => _}}]} = tenant
end
end

defp tenant_fixture(attrs) do
{:ok, tenant} =
attrs
|> Enum.into(@valid_attrs)
|> Api.create_tenant()

tenant
end
end

0 comments on commit d6df7b6

Please sign in to comment.