Skip to content

Commit

Permalink
fix(tests): increase test coverage (#60)
Browse files Browse the repository at this point in the history
* fix(tests): increase test coverage
  • Loading branch information
jksalazar authored Nov 27, 2024
1 parent 81803ec commit b05c85a
Show file tree
Hide file tree
Showing 7 changed files with 387 additions and 4 deletions.
7 changes: 6 additions & 1 deletion lib/core/structure/root.ex
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,14 @@ defmodule Structure.Root do
"{app_snake}/resources/cloud/Dockerfile-build" => @base <> "Dockerfile-build.txt",
"{app_snake}/test/infrastructure/entry_points/api_rest_test.exs" =>
@base <> "api_rest_test.exs",
"{app_snake}/test/infrastructure/entry_points/health_check_test.exs" =>
@base <> "health_check_test.exs",
"{app_snake}/test/{app_snake}_application_test.exs" => @base <> "test_application.exs",
"{app_snake}/test/test_helper.exs" => @base <> "test_helper.exs",
"{app_snake}/coveralls.json" => @base <> "coveralls.json"
"{app_snake}/coveralls.json" => @base <> "coveralls.json",
"{app_snake}/test/utils/custom_telemetry_test.exs" =>
@base <> "custom_telemetry_test.exs",
"{app_snake}/test/utils/data_type_utils_test.exs" => @base <> "data_type_utils_test.exs"
},
folders: [
"{app_snake}/lib/infrastructure/driven_adapters/",
Expand Down
2 changes: 1 addition & 1 deletion priv/templates/structure/api_rest.ex
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
defmodule {app}.Infrastructure.EntryPoint.ApiRest do

@compile if Mix.env() == :test, do: :export_all
@moduledoc """
Access point to the rest exposed services
"""
Expand Down
55 changes: 54 additions & 1 deletion priv/templates/structure/api_rest_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ defmodule {app}.Infrastructure.EntryPoint.ApiRestTets do
|> ApiRest.call(@opts)

assert conn.state == :sent
assert conn.status in [200, 500] # TODO: Implement mocks correctly when needed
# TODO: Implement mocks correctly when needed
assert conn.status in [200, 500]
end

test "test Hello" do
Expand All @@ -26,4 +27,56 @@ defmodule {app}.Infrastructure.EntryPoint.ApiRestTets do
assert conn.status == 200
end

test "put_resp_content_type/2" do
conn = conn(:get, "/test_content_type")
conn = put_resp_content_type(conn, "application/json")

assert get_resp_header(conn, "content-type") == ["application/json; charset=utf-8"]
end

test "test non-existent endpoint" do
conn =
:get
|> conn("/api/nonexistent", "")
|> ApiRest.call(@opts)

assert conn.state == :sent
assert conn.status == 404
end

test "test POST on /api/health" do
conn =
:post
|> conn("/api/health", "")
|> ApiRest.call(@opts)

assert conn.state == :sent
assert conn.status in [200, 500]
end

describe "handle_not_found/2" do
test "returns 404 status with path in debug mode" do
Logger.configure(level: :debug)

# Simulate a request to a nonexistent path
conn = conn(:get, "/nonexistent_path")
conn = ApiRest.call(conn, @opts)

# Verify the response
assert conn.state == :sent
assert conn.status == 404
assert conn.resp_body == Poison.encode!(%{status: 404, path: "/nonexistent_path"})
end

test "returns 404 status without body in non-debug mode" do
Logger.configure(level: :info)

conn = conn(:get, "/test_not_found/info")
conn = ApiRest.call(conn, @opts)

assert conn.state == :sent
assert conn.status == 404
assert conn.resp_body == ""
end
end
end
153 changes: 153 additions & 0 deletions priv/templates/structure/custom_telemetry_test.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
defmodule {app}.Utils.CustomTelemetryTest do
alias {app}.Utils.CustomTelemetry
use ExUnit.Case

setup do
:telemetry.detach("test-handler")
:ok
end

test "execute_custom_event emits the event with correct metric, value, and metadata" do
event_name = [:elixir, :custom, :metric]
metric = [:custom, :metric]
value = 200
metadata = %{source: "api"}
service_name = "{app_snake}_test"

Application.put_env(:test, :service_name, service_name)

:telemetry.attach(
"test-handler",
event_name,
fn _event_name, measurements, event_metadata, _config ->
send(self(), {:event_received, measurements, event_metadata})
end,
nil
)

CustomTelemetry.execute_custom_event(metric, value, metadata)

assert_receive {:event_received, %{duration: ^value},
%{source: "api", service: ^service_name}}

:telemetry.detach("test-handler")
end

test "execute_custom_event adds service name to metadata" do
event_name = [:elixir, :another, :metric]
metric = [:another, :metric]
value = 100
metadata = %{}
service_name = "{app_snake}_test"

Application.put_env(:test, :service_name, service_name)

:telemetry.attach(
"test-handler",
event_name,
fn _event_name, measurements, event_metadata, _config ->
send(self(), {:event_received, measurements, event_metadata})
end,
nil
)

CustomTelemetry.execute_custom_event(metric, value, metadata)

assert_receive {:event_received, %{duration: ^value}, %{service: ^service_name}}

:telemetry.detach("test-handler")
end

test "handle_custom_event emits the event with correct metric, measures, and metadata" do
event_name = [:elixir, :custom, :metric]
metric = [:custom, :metric]
measures = %{duration: 200}
metadata = %{source: "api"}
service_name = "{app_snake}_test"

Application.put_env(:test, :service_name, service_name)

:telemetry.attach(
"test-handler",
event_name,
fn _event_name, event_measures, event_metadata, _config ->
send(self(), {:event_received, event_measures, event_metadata})
end,
nil
)

CustomTelemetry.handle_custom_event(metric, measures, metadata, nil)

assert_receive {:event_received, ^measures, %{source: "api", service: ^service_name}}

:telemetry.detach("test-handler")
end

test "handle_custom_event adds service name to metadata" do
event_name = [:elixir, :another, :metric]
metric = [:another, :metric]
measures = %{count: 100}
metadata = %{}
service_name = "{app_snake}_test"

Application.put_env(:{app_snake}, :service_name, service_name)

:telemetry.attach(
"test-handler",
event_name,
fn _event_name, event_measures, event_metadata, _config ->
send(self(), {:event_received, event_measures, event_metadata})
end,
nil
)

CustomTelemetry.handle_custom_event(metric, measures, metadata, nil)

assert_receive {:event_received, ^measures, %{service: ^service_name}}

:telemetry.detach("test-handler")
end

test "execute_custom_event handles atom metric by delegating to list implementation" do
metric = :custom_event
value = 100
metadata = %{source: "test_source"}
expected_metric_list = [metric]

:telemetry.attach(
"test-handler",
[:elixir | expected_metric_list],
fn _event_name, measurements, event_metadata, _config ->
send(self(), {:event_received, measurements, event_metadata})
end,
nil
)

CustomTelemetry.execute_custom_event(metric, value, metadata)

assert_receive {:event_received, %{duration: ^value}, event_metadata}

assert event_metadata[:source] == "test_source"
end

test "execute_custom_event emits the correct event with default metadata" do
metric = [:custom, :event]
value = 200
expected_metadata = %{service: "{app_snake}_test"}

:telemetry.attach(
"test-handler-default-metadata",
[:elixir | metric],
fn _event_name, measurements, event_metadata, _config ->
send(self(), {:event_received, measurements, event_metadata})
end,
nil
)

CustomTelemetry.execute_custom_event(metric, value)

assert_receive {:event_received, %{duration: ^value}, event_metadata}
assert event_metadata == expected_metadata
end

end
135 changes: 135 additions & 0 deletions priv/templates/structure/data_type_utils_test.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
defmodule {app}.Utils.DataTypeUtilsTest do
alias {app}.Utils.DataTypeUtils
use ExUnit.Case

describe "normalize/1" do
test "normalizes a struct" do
struct = %DateTime{
year: 2023,
month: 1,
day: 1,
hour: 0,
minute: 0,
second: 0,
time_zone: "Etc/UTC",
zone_abbr: "UTC",
utc_offset: 0,
std_offset: 0
}

assert DataTypeUtils.normalize(struct) == struct
end

test "normalizes a map" do
map = %{"key" => "value"}
assert DataTypeUtils.normalize(map) == %{key: "value"}
end

test "normalizes a list" do
list = [%{"key" => "value"}]
assert DataTypeUtils.normalize(list) == [%{key: "value"}]
end
end

describe "base64_decode/1" do
test "decodes a base64 string" do
assert DataTypeUtils.base64_decode("SGVsbG8gd29ybGQ=") == "Hello world"
end
end

describe "extract_header/2" do
test "returns {:ok, value} when the header is found and value is not nil" do
headers = [{"content-type", "application/json"}, {"authorization", "Bearer token"}]
assert DataTypeUtils.extract_header(headers, "content-type") == {:ok, "application/json"}
end

test "returns {:error, :not_found} when the header is not found" do
headers = [{"content-type", "application/json"}, {"authorization", "Bearer token"}]
assert DataTypeUtils.extract_header(headers, "accept") == {:error, :not_found}
end
end

describe "extract_header/2 with non-list headers" do
test "returns an error when headers is a map" do
headers = %{"content-type" => "application/json"}

assert DataTypeUtils.extract_header(headers, "content-type") ==
{:error,
"headers is not a list when finding \"content-type\": %{\"content-type\" => \"application/json\"}"}
end

test "returns an error when headers is a string" do
headers = "content-type: application/json"

assert DataTypeUtils.extract_header(headers, "content-type") ==
{:error,
"headers is not a list when finding \"content-type\": \"content-type: application/json\""}
end

test "returns an error when headers is a tuple" do
headers = {"content-type", "application/json"}

assert DataTypeUtils.extract_header(headers, "content-type") ==
{:error,
"headers is not a list when finding \"content-type\": {\"content-type\", \"application/json\"}"}
end

test "returns an error when headers is nil" do
headers = nil

assert DataTypeUtils.extract_header(headers, "content-type") ==
{:error, "headers is not a list when finding \"content-type\": nil"}
end

test "returns an error when headers is an integer" do
headers = 123

assert DataTypeUtils.extract_header(headers, "content-type") ==
{:error, "headers is not a list when finding \"content-type\": 123"}
end
end

describe "format/2" do
test "returns true when input is 'true' and type is 'boolean'" do
assert DataTypeUtils.format("true", "boolean") == true
end

test "returns false when input is 'false' and type is 'boolean'" do
assert DataTypeUtils.format("false", "boolean") == false
end
end

test "returns the input value when type is ignored" do
assert DataTypeUtils.format(123, "any_type") == 123
end

test "converts system time in nanoseconds to milliseconds" do
assert DataTypeUtils.system_time_to_milliseconds(1_000_000_000) == 1000
end

test "converts monotonic time in native units to milliseconds" do
assert DataTypeUtils.monotonic_time_to_milliseconds(1_000_000) == 1
end

test "returns different numbers on subsequent calls" do
{:ok, confirm_number1} = DataTypeUtils.create_confirm_number()
{:ok, confirm_number2} = DataTypeUtils.create_confirm_number()

refute confirm_number1 == confirm_number2
end

test "returns the current monotonic time as an integer" do
start_time = DataTypeUtils.start_time()

assert is_integer(start_time)
end

test "calculates the duration time in milliseconds" do
start_time = System.monotonic_time()
:timer.sleep(100)
duration = DataTypeUtils.duration_time(start_time)

assert is_integer(duration)
assert duration >= 100
end
end
12 changes: 12 additions & 0 deletions priv/templates/structure/health_check_test.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
defmodule {app}.Infrastructure.EntryPoints.HealthCheckTest do
alias {app}.Infrastructure.EntryPoint.HealthCheck

use ExUnit.Case

describe "check_http/0" do
test "returns :ok" do
assert HealthCheck.check_http() == :ok
end
end

end
Loading

0 comments on commit b05c85a

Please sign in to comment.