mirror of
https://github.com/wanderer-industries/wanderer
synced 2025-12-11 02:05:58 +00:00
473 lines
14 KiB
Elixir
473 lines
14 KiB
Elixir
defmodule WandererAppWeb.MapAPIControllerTest do
|
|
use WandererAppWeb.ApiCase, async: true
|
|
|
|
import Mox
|
|
|
|
# Make sure mocks are verified when the test exits
|
|
setup :verify_on_exit!
|
|
|
|
# These endpoints require :api_map pipeline with authentication
|
|
# We'll need to create test maps and mock authentication
|
|
|
|
setup do
|
|
# Create test data
|
|
user = insert(:user)
|
|
map = insert(:map, %{name: "Test Map", owner_id: user.id})
|
|
character = insert(:character, %{user_id: user.id})
|
|
|
|
{:ok, %{user: user, map: map, character: character}}
|
|
end
|
|
|
|
describe "GET /api/maps/:map_id/systems" do
|
|
setup do
|
|
scenario = create_test_scenario(with_systems: true)
|
|
%{scenario: scenario}
|
|
end
|
|
|
|
test "returns systems for valid map with API key", %{conn: conn, scenario: scenario} do
|
|
conn =
|
|
conn
|
|
|> authenticate_map_api(scenario.map)
|
|
|> get(~p"/api/maps/#{scenario.map.id}/systems")
|
|
|
|
response = assert_json_response(conn, 200)
|
|
|
|
assert %{"data" => systems} = response
|
|
assert is_list(systems)
|
|
assert length(systems) == 2
|
|
|
|
# Verify we have the expected systems
|
|
system_ids = Enum.map(systems, & &1["solar_system_id"])
|
|
# Jita
|
|
assert 30_000_142 in system_ids
|
|
# Dodixie
|
|
assert 30_002659 in system_ids
|
|
end
|
|
|
|
test "returns 401 without API key", %{conn: conn, scenario: scenario} do
|
|
conn = get(conn, ~p"/api/maps/#{scenario.map.id}/systems")
|
|
|
|
assert_error_response(conn, 401, "unauthorized")
|
|
end
|
|
|
|
test "returns 404 for non-existent map", %{conn: conn} do
|
|
fake_map_id = Ecto.UUID.generate()
|
|
|
|
conn =
|
|
conn
|
|
|> put_api_key("fake_api_key")
|
|
|> get(~p"/api/maps/#{fake_map_id}/systems")
|
|
|
|
assert_error_response(conn, 404, "not found")
|
|
end
|
|
end
|
|
|
|
describe "GET /api/maps/:map_id/connections" do
|
|
setup do
|
|
scenario = create_test_scenario(with_systems: true, with_connections: true)
|
|
%{scenario: scenario}
|
|
end
|
|
|
|
test "returns connections for valid map", %{conn: conn, scenario: scenario} do
|
|
conn =
|
|
conn
|
|
|> authenticate_map_api(scenario.map)
|
|
|> get(~p"/api/maps/#{scenario.map.id}/connections")
|
|
|
|
response = assert_json_response(conn, 200)
|
|
|
|
assert %{"data" => connections} = response
|
|
assert is_list(connections)
|
|
assert length(connections) == 1
|
|
|
|
# Verify connection details
|
|
[connection] = connections
|
|
assert connection["solar_system_source"] == 30_000_142
|
|
assert connection["solar_system_target"] == 30_002659
|
|
end
|
|
|
|
test "returns empty list for map with no connections", %{conn: conn} do
|
|
scenario = create_test_scenario(with_systems: true, with_connections: false)
|
|
|
|
conn =
|
|
conn
|
|
|> authenticate_map_api(scenario.map)
|
|
|> get(~p"/api/maps/#{scenario.map.id}/connections")
|
|
|
|
response = assert_json_response(conn, 200)
|
|
|
|
assert %{"data" => connections} = response
|
|
assert connections == []
|
|
end
|
|
end
|
|
|
|
describe "POST /api/maps/:map_id/systems" do
|
|
setup do
|
|
scenario = create_test_scenario(with_systems: false)
|
|
%{scenario: scenario}
|
|
end
|
|
|
|
test "creates system with valid data", %{conn: conn, scenario: scenario} do
|
|
system_params = %{
|
|
# Amarr
|
|
"solar_system_id" => 30_000_144,
|
|
"position_x" => 150,
|
|
"position_y" => 250,
|
|
"status" => 1,
|
|
"visible" => true
|
|
}
|
|
|
|
conn =
|
|
conn
|
|
|> authenticate_map_api(scenario.map)
|
|
|> post(~p"/api/maps/#{scenario.map.id}/systems", system_params)
|
|
|
|
response = assert_json_response(conn, 201)
|
|
|
|
assert %{"data" => system_data} = response
|
|
assert system_data["solar_system_id"] == 30_000_144
|
|
assert system_data["position_x"] == 150
|
|
assert system_data["position_y"] == 250
|
|
assert system_data["status"] == 1
|
|
assert system_data["visible"] == true
|
|
end
|
|
|
|
test "returns 422 with invalid solar_system_id", %{conn: conn, scenario: scenario} do
|
|
system_params = %{
|
|
"solar_system_id" => "invalid",
|
|
"position_x" => 150,
|
|
"position_y" => 250
|
|
}
|
|
|
|
conn =
|
|
conn
|
|
|> authenticate_map_api(scenario.map)
|
|
|> post(~p"/api/maps/#{scenario.map.id}/systems", system_params)
|
|
|
|
assert_error_response(conn, 422)
|
|
end
|
|
|
|
test "returns 400 with missing required fields", %{conn: conn, scenario: scenario} do
|
|
system_params = %{
|
|
"position_x" => 150
|
|
# Missing solar_system_id and position_y
|
|
}
|
|
|
|
conn =
|
|
conn
|
|
|> authenticate_map_api(scenario.map)
|
|
|> post(~p"/api/maps/#{scenario.map.id}/systems", system_params)
|
|
|
|
assert_error_response(conn, 400)
|
|
end
|
|
end
|
|
|
|
describe "PUT /api/maps/:map_id/systems/:system_id" do
|
|
setup do
|
|
scenario = create_test_scenario(with_systems: true)
|
|
%{scenario: scenario}
|
|
end
|
|
|
|
test "updates system with valid data", %{conn: conn, scenario: scenario} do
|
|
[system | _] = scenario.systems
|
|
|
|
update_params = %{
|
|
"status" => 2,
|
|
"custom_name" => "Updated System Name",
|
|
"description" => "Updated description"
|
|
}
|
|
|
|
conn =
|
|
conn
|
|
|> authenticate_map_api(scenario.map)
|
|
|> put(~p"/api/maps/#{scenario.map.id}/systems/#{system.id}", update_params)
|
|
|
|
response = assert_json_response(conn, 200)
|
|
|
|
assert %{"data" => updated_system} = response
|
|
assert updated_system["status"] == 2
|
|
assert updated_system["custom_name"] == "Updated System Name"
|
|
assert updated_system["description"] == "Updated description"
|
|
end
|
|
|
|
test "returns 404 for non-existent system", %{conn: conn, scenario: scenario} do
|
|
fake_system_id = Ecto.UUID.generate()
|
|
|
|
update_params = %{
|
|
"status" => 2
|
|
}
|
|
|
|
conn =
|
|
conn
|
|
|> authenticate_map_api(scenario.map)
|
|
|> put(~p"/api/maps/#{scenario.map.id}/systems/#{fake_system_id}", update_params)
|
|
|
|
assert_error_response(conn, 404)
|
|
end
|
|
end
|
|
|
|
describe "DELETE /api/maps/:map_id/systems/:system_id" do
|
|
setup do
|
|
scenario = create_test_scenario(with_systems: true)
|
|
%{scenario: scenario}
|
|
end
|
|
|
|
test "deletes system successfully", %{conn: conn, scenario: scenario} do
|
|
[system | _] = scenario.systems
|
|
|
|
conn =
|
|
conn
|
|
|> authenticate_map_api(scenario.map)
|
|
|> delete(~p"/api/maps/#{scenario.map.id}/systems/#{system.id}")
|
|
|
|
assert response(conn, 204)
|
|
|
|
# Verify system is actually deleted by trying to fetch it
|
|
conn =
|
|
build_conn()
|
|
|> authenticate_map_api(scenario.map)
|
|
|> get(~p"/api/maps/#{scenario.map.id}/systems")
|
|
|
|
response = assert_json_response(conn, 200)
|
|
assert %{"data" => systems} = response
|
|
system_ids = Enum.map(systems, & &1["id"])
|
|
refute system.id in system_ids
|
|
end
|
|
|
|
test "returns 404 for non-existent system", %{conn: conn, scenario: scenario} do
|
|
fake_system_id = Ecto.UUID.generate()
|
|
|
|
conn =
|
|
conn
|
|
|> authenticate_map_api(scenario.map)
|
|
|> delete(~p"/api/maps/#{scenario.map.id}/systems/#{fake_system_id}")
|
|
|
|
assert_error_response(conn, 404)
|
|
end
|
|
end
|
|
|
|
describe "GET /api/map/user_characters" do
|
|
test "returns user characters for valid map", %{conn: conn, map: map} do
|
|
response =
|
|
conn
|
|
|> authenticate_map_api(map)
|
|
|> get("/api/map/user_characters?map_id=#{map.id}")
|
|
|> assert_json_response(200)
|
|
|
|
assert %{"data" => user_groups} = response
|
|
assert is_list(user_groups)
|
|
end
|
|
|
|
test "returns user characters when using slug", %{conn: conn, map: map} do
|
|
response =
|
|
conn
|
|
|> authenticate_map_api(map)
|
|
|> get("/api/map/user_characters?slug=#{map.slug}")
|
|
|> assert_json_response(200)
|
|
|
|
assert %{"data" => user_groups} = response
|
|
assert is_list(user_groups)
|
|
end
|
|
|
|
test "returns 400 when both map_id and slug provided", %{conn: conn, map: map} do
|
|
response =
|
|
conn
|
|
|> authenticate_map_api(map)
|
|
|> get("/api/map/user_characters?map_id=#{map.id}&slug=#{map.slug}")
|
|
|> assert_json_response(400)
|
|
|
|
assert %{"error" => error_msg} = response
|
|
assert error_msg =~ "both"
|
|
end
|
|
|
|
test "returns 400 when neither map_id nor slug provided", %{conn: conn, map: map} do
|
|
response =
|
|
conn
|
|
|> authenticate_map_api(map)
|
|
|> get("/api/map/user_characters")
|
|
|> assert_json_response(400)
|
|
|
|
assert %{"error" => error_msg} = response
|
|
end
|
|
end
|
|
|
|
describe "GET /api/maps/:map_identifier/user-characters" do
|
|
test "returns user characters using unified endpoint with UUID", %{conn: conn, map: map} do
|
|
response =
|
|
conn
|
|
|> authenticate_map_api(map)
|
|
|> get("/api/maps/#{map.id}/user-characters")
|
|
|> assert_json_response(200)
|
|
|
|
assert %{"data" => user_groups} = response
|
|
assert is_list(user_groups)
|
|
end
|
|
|
|
test "returns user characters using unified endpoint with slug", %{conn: conn, map: map} do
|
|
response =
|
|
conn
|
|
|> authenticate_map_api(map)
|
|
|> get("/api/maps/#{map.slug}/user-characters")
|
|
|> assert_json_response(200)
|
|
|
|
assert %{"data" => user_groups} = response
|
|
assert is_list(user_groups)
|
|
end
|
|
|
|
test "returns 404 for non-existent map", %{conn: conn} do
|
|
fake_uuid = Ecto.UUID.generate()
|
|
|
|
response =
|
|
conn
|
|
|> put_req_header("content-type", "application/json")
|
|
|> get("/api/maps/#{fake_uuid}/user-characters")
|
|
|> json_response(404)
|
|
|
|
assert %{"error" => _} = response
|
|
end
|
|
end
|
|
|
|
describe "GET /api/maps/:map_identifier/tracked-characters" do
|
|
test "returns tracked characters for map", %{conn: conn, map: map, character: character} do
|
|
# Create a character tracking record
|
|
_tracking =
|
|
insert(:map_character_settings, %{
|
|
map_id: map.id,
|
|
character_id: character.id,
|
|
tracked: true
|
|
})
|
|
|
|
response =
|
|
conn
|
|
|> authenticate_map_api(map)
|
|
|> get("/api/maps/#{map.id}/tracked-characters")
|
|
|> assert_json_response(200)
|
|
|
|
assert %{"data" => tracked_chars} = response
|
|
assert is_list(tracked_chars)
|
|
end
|
|
|
|
test "returns empty list when no characters tracked", %{conn: conn, map: map} do
|
|
response =
|
|
conn
|
|
|> authenticate_map_api(map)
|
|
|> get("/api/maps/#{map.id}/tracked-characters")
|
|
|> assert_json_response(200)
|
|
|
|
assert %{"data" => []} = response
|
|
end
|
|
end
|
|
|
|
describe "GET /api/map/structure-timers" do
|
|
test "returns structure timers for map", %{conn: conn, map: map} do
|
|
response =
|
|
conn
|
|
|> authenticate_map_api(map)
|
|
|> get("/api/map/structure-timers?map_id=#{map.id}")
|
|
|> assert_json_response(200)
|
|
|
|
assert %{"data" => timers} = response
|
|
assert is_list(timers)
|
|
end
|
|
|
|
test "returns structure timers filtered by system", %{conn: conn, map: map} do
|
|
system_id = 30_000_142
|
|
|
|
response =
|
|
conn
|
|
|> authenticate_map_api(map)
|
|
|> get("/api/map/structure-timers?map_id=#{map.id}&system_id=#{system_id}")
|
|
|> assert_json_response(200)
|
|
|
|
assert %{"data" => timers} = response
|
|
assert is_list(timers)
|
|
end
|
|
|
|
test "returns 400 for invalid system_id", %{conn: conn, map: map} do
|
|
response =
|
|
conn
|
|
|> authenticate_map_api(map)
|
|
|> get("/api/map/structure-timers?map_id=#{map.id}&system_id=invalid")
|
|
|> assert_json_response(400)
|
|
|
|
assert %{"error" => error_msg} = response
|
|
assert error_msg =~ "system_id must be int"
|
|
end
|
|
end
|
|
|
|
describe "GET /api/map/systems-kills" do
|
|
test "returns systems kills data", %{conn: conn, map: map} do
|
|
response =
|
|
conn
|
|
|> authenticate_map_api(map)
|
|
|> get("/api/map/systems-kills/")
|
|
|> assert_json_response(200)
|
|
|
|
assert %{"data" => systems_kills} = response
|
|
assert is_list(systems_kills)
|
|
|
|
# Verify structure of systems kills data
|
|
if length(systems_kills) > 0 do
|
|
system_kills = hd(systems_kills)
|
|
assert %{"solar_system_id" => _, "kills" => kills} = system_kills
|
|
assert is_integer(system_kills["solar_system_id"])
|
|
assert is_list(kills)
|
|
end
|
|
end
|
|
end
|
|
|
|
describe "authentication and authorization" do
|
|
test "returns 403 when map API is disabled", %{conn: conn, map: map} do
|
|
# This would require mocking the API disabled state
|
|
# For now, we'll test that proper headers are required
|
|
response =
|
|
conn
|
|
|> get("/api/maps/#{map.id}/user-characters")
|
|
|
|
# Should fail due to missing authentication
|
|
assert response.status in [401, 403, 404]
|
|
end
|
|
|
|
test "handles missing authentication headers", %{conn: conn, map: map} do
|
|
response =
|
|
conn
|
|
|> get("/api/maps/#{map.id}/user-characters")
|
|
|
|
# Should fail due to missing authentication
|
|
assert response.status in [401, 403, 404]
|
|
end
|
|
|
|
test "handles invalid map identifier", %{conn: conn} do
|
|
response =
|
|
conn
|
|
|> put_req_header("content-type", "application/json")
|
|
|> get("/api/maps/invalid-identifier/user-characters")
|
|
|
|
# Should return not found or bad request
|
|
assert response.status in [400, 404]
|
|
end
|
|
end
|
|
|
|
describe "deprecated endpoints" do
|
|
test "legacy user_characters endpoint still works", %{conn: conn, map: map} do
|
|
response =
|
|
conn
|
|
|> authenticate_map_api(map)
|
|
|> get("/api/map/user_characters?map_id=#{map.id}")
|
|
|> assert_json_response(200)
|
|
|
|
assert %{"data" => _} = response
|
|
end
|
|
|
|
test "legacy characters endpoint works", %{conn: conn, map: map} do
|
|
response =
|
|
conn
|
|
|> authenticate_map_api(map)
|
|
|> get("/api/map/characters?map_id=#{map.id}")
|
|
|> assert_json_response(200)
|
|
|
|
assert %{"data" => _} = response
|
|
end
|
|
end
|
|
end
|