From bbfdea46e2c1b4f4d4617162dfa22bc226686814 Mon Sep 17 00:00:00 2001 From: Graham McIntire Date: Fri, 8 May 2026 12:19:05 -0500 Subject: [PATCH] test: KMZ controller paths + plug session activity baseline --- .../api/v1/coverages_controller_test.exs | 82 +++++++++++++++++++ .../plugs/update_session_activity_test.exs | 2 +- 2 files changed, 83 insertions(+), 1 deletion(-) diff --git a/test/towerops_web/controllers/api/v1/coverages_controller_test.exs b/test/towerops_web/controllers/api/v1/coverages_controller_test.exs index 29f33c21..728bd59e 100644 --- a/test/towerops_web/controllers/api/v1/coverages_controller_test.exs +++ b/test/towerops_web/controllers/api/v1/coverages_controller_test.exs @@ -1,11 +1,13 @@ defmodule ToweropsWeb.Api.V1.CoveragesControllerTest do use ToweropsWeb.ConnCase, async: false + import Ecto.Query import Towerops.AccountsFixtures import Towerops.CoveragesFixtures import Towerops.OrganizationsFixtures alias Towerops.ApiTokens + alias Towerops.Coverages.Coverage setup %{conn: conn} do user = user_fixture() @@ -121,6 +123,86 @@ defmodule ToweropsWeb.Api.V1.CoveragesControllerTest do end end + describe "GET /api/v1/coverages/:id/kmz" do + defp set_coverage_state(cov, attrs) do + Towerops.Repo.update_all( + Ecto.Query.from(c in Coverage, where: c.id == ^cov.id), + set: Map.to_list(attrs) + ) + + Towerops.Repo.get!(Coverage, cov.id) + end + + test "returns 409 when coverage is not ready", %{conn: conn, org: org, site: site} do + cov = org.id |> coverage_fixture(site.id) |> set_coverage_state(%{status: "queued"}) + resp = conn |> get(~p"/api/v1/coverages/#{cov.id}/kmz") |> json_response(409) + assert resp["error"] =~ "not ready" + end + + test "returns 409 when coverage is ready but png_path is nil", + %{conn: conn, org: org, site: site} do + cov = + org.id + |> coverage_fixture(site.id) + |> set_coverage_state(%{status: "ready", png_path: nil}) + + resp = conn |> get(~p"/api/v1/coverages/#{cov.id}/kmz") |> json_response(409) + assert resp["error"] =~ "not ready" + end + + test "returns 500 when png file is missing on disk", + %{conn: conn, org: org, site: site} do + cov = + org.id + |> coverage_fixture(site.id) + |> set_coverage_state(%{ + status: "ready", + png_path: "/coverage/missing/#{System.unique_integer([:positive])}.png", + bbox_min_lat: 30.0, + bbox_max_lat: 30.5, + bbox_min_lon: -97.5, + bbox_max_lon: -97.0 + }) + + resp = conn |> get(~p"/api/v1/coverages/#{cov.id}/kmz") |> json_response(500) + assert resp["error"] =~ "Failed to build KMZ" + end + + test "returns 404 for an unknown coverage id", %{conn: conn} do + conn = get(conn, ~p"/api/v1/coverages/#{Ecto.UUID.generate()}/kmz") + assert response(conn, 404) + end + + test "returns 200 + KMZ bytes when png exists on disk", + %{conn: conn, org: org, site: site} do + png_dir = Path.join([Application.app_dir(:towerops, "priv/static"), "coverage", "kmztest"]) + File.mkdir_p!(png_dir) + png_path_rel = "/coverage/kmztest/cov-#{System.unique_integer([:positive])}.png" + png_abs = Path.join(Application.app_dir(:towerops, "priv/static"), Path.relative_to(png_path_rel, "/")) + File.write!(png_abs, <<137, 80, 78, 71, 13, 10, 26, 10>>) + on_exit(fn -> File.rm(png_abs) end) + + cov = + org.id + |> coverage_fixture(site.id) + |> set_coverage_state(%{ + status: "ready", + png_path: png_path_rel, + name: "T<&> coverage", + bbox_min_lat: 30.1, + bbox_max_lat: 30.5, + bbox_min_lon: -97.5, + bbox_max_lon: -97.0 + }) + + conn = get(conn, ~p"/api/v1/coverages/#{cov.id}/kmz") + assert response(conn, 200) + + assert [disposition] = get_resp_header(conn, "content-disposition") + assert disposition =~ "coverage-#{cov.id}.kmz" + end + end + describe "auth" do test "rejects requests without a Bearer token" do conn = get(build_conn(), ~p"/api/v1/coverages") diff --git a/test/towerops_web/plugs/update_session_activity_test.exs b/test/towerops_web/plugs/update_session_activity_test.exs index 89ddfcef..689087f9 100644 --- a/test/towerops_web/plugs/update_session_activity_test.exs +++ b/test/towerops_web/plugs/update_session_activity_test.exs @@ -1,5 +1,5 @@ defmodule ToweropsWeb.Plugs.UpdateSessionActivityTest do - use ToweropsWeb.ConnCase, async: true + use ToweropsWeb.ConnCase, async: false alias ToweropsWeb.Plugs.UpdateSessionActivity