mirror of
https://github.com/wanderer-industries/wanderer
synced 2025-12-12 02:35:42 +00:00
Some checks are pending
Build / 🚀 Deploy to test env (fly.io) (push) Waiting to run
Build / Manual Approval (push) Blocked by required conditions
Build / 🛠 Build (1.17, 18.x, 27) (push) Blocked by required conditions
Build / 🛠 Build Docker Images (linux/amd64) (push) Blocked by required conditions
Build / 🛠 Build Docker Images (linux/arm64) (push) Blocked by required conditions
Build / merge (push) Blocked by required conditions
Build / 🏷 Create Release (push) Blocked by required conditions
335 lines
11 KiB
Elixir
335 lines
11 KiB
Elixir
# Standalone test for the CharacterAPIController
|
|
#
|
|
# This file can be run directly with:
|
|
# elixir test/standalone/character_api_controller_test.exs
|
|
#
|
|
# It doesn't require any database connections or external dependencies.
|
|
|
|
# Start ExUnit
|
|
ExUnit.start()
|
|
|
|
defmodule CharacterAPIControllerTest do
|
|
use ExUnit.Case
|
|
|
|
# Mock modules to simulate the behavior of the controller's dependencies
|
|
defmodule MockUtil do
|
|
def require_param(params, key) do
|
|
case params[key] do
|
|
nil -> {:error, "Missing required param: #{key}"}
|
|
"" -> {:error, "Param #{key} cannot be empty"}
|
|
val -> {:ok, val}
|
|
end
|
|
end
|
|
|
|
def parse_int(str) do
|
|
case Integer.parse(str) do
|
|
{num, ""} -> {:ok, num}
|
|
_ -> {:error, "Invalid integer for param id=#{str}"}
|
|
end
|
|
end
|
|
|
|
def parse_bool(str) do
|
|
case str do
|
|
"true" -> {:ok, true}
|
|
"false" -> {:ok, false}
|
|
_ -> {:error, "Invalid boolean value: #{str}"}
|
|
end
|
|
end
|
|
end
|
|
|
|
defmodule MockCharacterRepo do
|
|
# In-memory storage for character tracking data
|
|
def init_storage do
|
|
:ets.new(:character_tracking, [:set, :public, :named_table])
|
|
|
|
# Initialize with some test data
|
|
:ets.insert(:character_tracking, {"user1", [
|
|
%{eve_id: "123456", name: "Character One", tracked: true, followed: true},
|
|
%{eve_id: "234567", name: "Character Two", tracked: true, followed: false},
|
|
%{eve_id: "345678", name: "Character Three", tracked: false, followed: false}
|
|
]})
|
|
|
|
:ets.insert(:character_tracking, {"user2", [
|
|
%{eve_id: "456789", name: "Character Four", tracked: true, followed: true}
|
|
]})
|
|
end
|
|
|
|
def get_tracking_data(user_id) do
|
|
case :ets.lookup(:character_tracking, user_id) do
|
|
[{^user_id, data}] -> {:ok, data}
|
|
[] -> {:ok, []}
|
|
end
|
|
end
|
|
|
|
def update_tracking_data(user_id, new_data) do
|
|
:ets.insert(:character_tracking, {user_id, new_data})
|
|
{:ok, new_data}
|
|
end
|
|
|
|
def toggle_character_follow(user_id, character_id, follow_state) do
|
|
case get_tracking_data(user_id) do
|
|
{:ok, data} ->
|
|
# Find the character and update its followed state
|
|
updated_data = Enum.map(data, fn char ->
|
|
if char.eve_id == character_id do
|
|
%{char | followed: follow_state}
|
|
else
|
|
char
|
|
end
|
|
end)
|
|
|
|
# Update the storage
|
|
update_tracking_data(user_id, updated_data)
|
|
|
|
# Return the updated character
|
|
updated_char = Enum.find(updated_data, fn char -> char.eve_id == character_id end)
|
|
{:ok, updated_char}
|
|
|
|
error -> error
|
|
end
|
|
end
|
|
|
|
def toggle_character_track(user_id, character_id, track_state) do
|
|
case get_tracking_data(user_id) do
|
|
{:ok, data} ->
|
|
# Find the character and update its tracked state
|
|
updated_data = Enum.map(data, fn char ->
|
|
if char.eve_id == character_id do
|
|
%{char | tracked: track_state}
|
|
else
|
|
char
|
|
end
|
|
end)
|
|
|
|
# Update the storage
|
|
update_tracking_data(user_id, updated_data)
|
|
|
|
# Return the updated character
|
|
updated_char = Enum.find(updated_data, fn char -> char.eve_id == character_id end)
|
|
{:ok, updated_char}
|
|
|
|
error -> error
|
|
end
|
|
end
|
|
end
|
|
|
|
defmodule MockTrackingUtils do
|
|
def check_tracking_consistency(tracking_data) do
|
|
# Log warnings for characters that are followed but not tracked
|
|
inconsistent_chars = Enum.filter(tracking_data, fn char ->
|
|
char[:followed] == true && char[:tracked] == false
|
|
end)
|
|
|
|
if length(inconsistent_chars) > 0 do
|
|
Enum.each(inconsistent_chars, fn char ->
|
|
eve_id = Map.get(char, :eve_id, "unknown")
|
|
name = Map.get(char, :name, "Unknown Character")
|
|
IO.puts("WARNING: Inconsistent state detected - Character (ID: #{eve_id}, Name: #{name}) is followed but not tracked")
|
|
end)
|
|
end
|
|
|
|
# Return the original data unchanged
|
|
tracking_data
|
|
end
|
|
end
|
|
|
|
# Mock controller that uses our mock dependencies
|
|
defmodule MockCharacterAPIController do
|
|
# Simplified version of toggle_follow from CharacterAPIController
|
|
def toggle_follow(params, user_id) do
|
|
with {:ok, character_id} <- MockUtil.require_param(params, "character_id"),
|
|
{:ok, follow_str} <- MockUtil.require_param(params, "follow"),
|
|
{:ok, follow} <- MockUtil.parse_bool(follow_str) do
|
|
|
|
case MockCharacterRepo.toggle_character_follow(user_id, character_id, follow) do
|
|
{:ok, updated_char} ->
|
|
# Get all tracking data to check consistency
|
|
{:ok, all_tracking} = MockCharacterRepo.get_tracking_data(user_id)
|
|
|
|
# Check for inconsistencies (characters followed but not tracked)
|
|
MockTrackingUtils.check_tracking_consistency(all_tracking)
|
|
|
|
# Return the updated character
|
|
{:ok, %{data: updated_char}}
|
|
|
|
{:error, reason} ->
|
|
{:error, :internal_server_error, "Failed to update character: #{reason}"}
|
|
end
|
|
else
|
|
{:error, msg} ->
|
|
{:error, :bad_request, msg}
|
|
end
|
|
end
|
|
|
|
# Simplified version of toggle_track from CharacterAPIController
|
|
def toggle_track(params, user_id) do
|
|
with {:ok, character_id} <- MockUtil.require_param(params, "character_id"),
|
|
{:ok, track_str} <- MockUtil.require_param(params, "track"),
|
|
{:ok, track} <- MockUtil.parse_bool(track_str) do
|
|
|
|
# If we're untracking a character, we should also unfollow it
|
|
result = if track == false do
|
|
# First unfollow if needed
|
|
MockCharacterRepo.toggle_character_follow(user_id, character_id, false)
|
|
# Then untrack
|
|
MockCharacterRepo.toggle_character_track(user_id, character_id, false)
|
|
else
|
|
# Just track
|
|
MockCharacterRepo.toggle_character_track(user_id, character_id, true)
|
|
end
|
|
|
|
case result do
|
|
{:ok, updated_char} ->
|
|
# Get all tracking data to check consistency
|
|
{:ok, all_tracking} = MockCharacterRepo.get_tracking_data(user_id)
|
|
|
|
# Check for inconsistencies (characters followed but not tracked)
|
|
MockTrackingUtils.check_tracking_consistency(all_tracking)
|
|
|
|
# Return the updated character
|
|
{:ok, %{data: updated_char}}
|
|
|
|
{:error, reason} ->
|
|
{:error, :internal_server_error, "Failed to update character: #{reason}"}
|
|
end
|
|
else
|
|
{:error, msg} ->
|
|
{:error, :bad_request, msg}
|
|
end
|
|
end
|
|
|
|
# Simplified version of list_tracking from CharacterAPIController
|
|
def list_tracking(user_id) do
|
|
case MockCharacterRepo.get_tracking_data(user_id) do
|
|
{:ok, tracking_data} ->
|
|
# Check for inconsistencies
|
|
checked_data = MockTrackingUtils.check_tracking_consistency(tracking_data)
|
|
|
|
# Return the data
|
|
{:ok, %{data: checked_data}}
|
|
|
|
{:error, reason} ->
|
|
{:error, :internal_server_error, "Failed to get tracking data: #{reason}"}
|
|
end
|
|
end
|
|
end
|
|
|
|
# Setup for tests
|
|
setup do
|
|
# Initialize the mock storage
|
|
MockCharacterRepo.init_storage()
|
|
:ok
|
|
end
|
|
|
|
describe "toggle_follow/2" do
|
|
test "follows a character successfully" do
|
|
params = %{"character_id" => "345678", "follow" => "true"}
|
|
result = MockCharacterAPIController.toggle_follow(params, "user1")
|
|
|
|
assert {:ok, %{data: data}} = result
|
|
assert data.eve_id == "345678"
|
|
assert data.name == "Character Three"
|
|
assert data.followed == true
|
|
assert data.tracked == false
|
|
|
|
# This should have created an inconsistency (followed but not tracked)
|
|
# The check_tracking_consistency function should have logged a warning
|
|
end
|
|
|
|
test "unfollows a character successfully" do
|
|
params = %{"character_id" => "123456", "follow" => "false"}
|
|
result = MockCharacterAPIController.toggle_follow(params, "user1")
|
|
|
|
assert {:ok, %{data: data}} = result
|
|
assert data.eve_id == "123456"
|
|
assert data.followed == false
|
|
assert data.tracked == true
|
|
end
|
|
|
|
test "returns error when character_id is missing" do
|
|
params = %{"follow" => "true"}
|
|
result = MockCharacterAPIController.toggle_follow(params, "user1")
|
|
|
|
assert {:error, :bad_request, message} = result
|
|
assert message == "Missing required param: character_id"
|
|
end
|
|
|
|
test "returns error when follow is not a valid boolean" do
|
|
params = %{"character_id" => "123456", "follow" => "not-a-boolean"}
|
|
result = MockCharacterAPIController.toggle_follow(params, "user1")
|
|
|
|
assert {:error, :bad_request, message} = result
|
|
assert message =~ "Invalid boolean value"
|
|
end
|
|
end
|
|
|
|
describe "toggle_track/2" do
|
|
test "tracks a character successfully" do
|
|
params = %{"character_id" => "345678", "track" => "true"}
|
|
result = MockCharacterAPIController.toggle_track(params, "user1")
|
|
|
|
assert {:ok, %{data: data}} = result
|
|
assert data.eve_id == "345678"
|
|
assert data.tracked == true
|
|
end
|
|
|
|
test "untracks and unfollows a character" do
|
|
# First, make sure the character is followed
|
|
follow_params = %{"character_id" => "123456", "follow" => "true"}
|
|
MockCharacterAPIController.toggle_follow(follow_params, "user1")
|
|
|
|
# Now untrack the character
|
|
params = %{"character_id" => "123456", "track" => "false"}
|
|
result = MockCharacterAPIController.toggle_track(params, "user1")
|
|
|
|
assert {:ok, %{data: data}} = result
|
|
assert data.eve_id == "123456"
|
|
assert data.tracked == false
|
|
assert data.followed == false # Should also be unfollowed
|
|
end
|
|
|
|
test "returns error when character_id is missing" do
|
|
params = %{"track" => "true"}
|
|
result = MockCharacterAPIController.toggle_track(params, "user1")
|
|
|
|
assert {:error, :bad_request, message} = result
|
|
assert message == "Missing required param: character_id"
|
|
end
|
|
|
|
test "returns error when track is not a valid boolean" do
|
|
params = %{"character_id" => "123456", "track" => "not-a-boolean"}
|
|
result = MockCharacterAPIController.toggle_track(params, "user1")
|
|
|
|
assert {:error, :bad_request, message} = result
|
|
assert message =~ "Invalid boolean value"
|
|
end
|
|
end
|
|
|
|
describe "list_tracking/1" do
|
|
test "returns tracking data for a user" do
|
|
result = MockCharacterAPIController.list_tracking("user1")
|
|
|
|
assert {:ok, %{data: data}} = result
|
|
assert length(data) == 3
|
|
|
|
# Check that the data contains the expected characters
|
|
char_one = Enum.find(data, fn char -> char.eve_id == "123456" end)
|
|
assert char_one.name == "Character One"
|
|
assert char_one.tracked == true
|
|
assert char_one.followed == true
|
|
|
|
char_two = Enum.find(data, fn char -> char.eve_id == "234567" end)
|
|
assert char_two.name == "Character Two"
|
|
assert char_two.tracked == true
|
|
assert char_two.followed == false
|
|
end
|
|
|
|
test "returns empty list for user with no tracking data" do
|
|
result = MockCharacterAPIController.list_tracking("non-existent-user")
|
|
|
|
assert {:ok, %{data: data}} = result
|
|
assert data == []
|
|
end
|
|
end
|
|
end
|