towerops/test/towerops_web/helpers/time_helpers_test.exs
Graham McIntire 1b4b7f1773
fix user deletion bug and implement timezone support
User deletion bug:
- Store client IP in socket assigns during mount
- Access stored IP during delete event instead of connect_info
- Fixes RuntimeError when attempting to delete users

Timezone support:
- Add timezone offset maps for common timezones (no external deps)
- Implement shift_timezone/2 helper using DateTime.add/3
- Add timezone-aware format_datetime/2, format_date/2, format_iso8601/2
- Keep backwards-compatible 1-arity versions defaulting to UTC
- Add comprehensive test coverage for timezone conversions
- All tests passing (23 tests, 0 failures)

Note: Timezone offsets are standard time only (no DST handling)
Common timezones supported: America/New_York, America/Los_Angeles,
Europe/London, Europe/Paris, Asia/Tokyo, Asia/Shanghai, Australia/Sydney
2026-01-18 10:51:11 -06:00

139 lines
5.1 KiB
Elixir

defmodule ToweropsWeb.TimeHelpersTest do
use ExUnit.Case, async: true
alias ToweropsWeb.TimeHelpers
describe "format_datetime/2" do
test "formats datetime in UTC when timezone is nil" do
datetime = ~U[2026-01-15 14:34:00Z]
assert TimeHelpers.format_datetime(datetime, nil) == "Jan 15, 2026 at 02:34 PM UTC"
end
test "formats datetime in UTC when timezone is explicitly UTC" do
datetime = ~U[2026-01-15 14:34:00Z]
assert TimeHelpers.format_datetime(datetime, "UTC") == "Jan 15, 2026 at 02:34 PM UTC"
end
test "converts datetime to America/New_York timezone" do
datetime = ~U[2026-01-15 14:34:00Z]
# 14:34 UTC = 09:34 EST (UTC-5)
assert TimeHelpers.format_datetime(datetime, "America/New_York") =~ "Jan 15, 2026 at 09:34 AM"
assert TimeHelpers.format_datetime(datetime, "America/New_York") =~ "EST"
end
test "converts datetime to America/Los_Angeles timezone" do
datetime = ~U[2026-01-15 14:34:00Z]
# 14:34 UTC = 06:34 PST (UTC-8)
assert TimeHelpers.format_datetime(datetime, "America/Los_Angeles") =~ "Jan 15, 2026 at 06:34 AM"
assert TimeHelpers.format_datetime(datetime, "America/Los_Angeles") =~ "PST"
end
test "falls back to UTC for invalid timezone" do
datetime = ~U[2026-01-15 14:34:00Z]
assert TimeHelpers.format_datetime(datetime, "Invalid/Timezone") == "Jan 15, 2026 at 02:34 PM UTC"
end
test "returns 'Never' for nil datetime" do
assert TimeHelpers.format_datetime(nil, "America/New_York") == "Never"
assert TimeHelpers.format_datetime(nil, nil) == "Never"
end
end
describe "format_date/2" do
test "formats date in UTC when timezone is nil" do
datetime = ~U[2026-01-15 14:34:00Z]
assert TimeHelpers.format_date(datetime, nil) == "Jan 15, 2026"
end
test "formats date in UTC when timezone is explicitly UTC" do
datetime = ~U[2026-01-15 14:34:00Z]
assert TimeHelpers.format_date(datetime, "UTC") == "Jan 15, 2026"
end
test "converts to different date in America/Los_Angeles for early UTC times" do
# 02:00 UTC on Jan 15 = 18:00 PST on Jan 14 (UTC-8)
datetime = ~U[2026-01-15 02:00:00Z]
assert TimeHelpers.format_date(datetime, "America/Los_Angeles") == "Jan 14, 2026"
end
test "keeps same date for late UTC times in America/Los_Angeles" do
# 20:00 UTC on Jan 15 = 12:00 PST on Jan 15 (UTC-8)
datetime = ~U[2026-01-15 20:00:00Z]
assert TimeHelpers.format_date(datetime, "America/Los_Angeles") == "Jan 15, 2026"
end
test "falls back to UTC for invalid timezone" do
datetime = ~U[2026-01-15 14:34:00Z]
assert TimeHelpers.format_date(datetime, "Invalid/Timezone") == "Jan 15, 2026"
end
test "returns 'Never' for nil datetime" do
assert TimeHelpers.format_date(nil, "America/New_York") == "Never"
assert TimeHelpers.format_date(nil, nil) == "Never"
end
end
describe "format_iso8601/2" do
test "formats datetime in UTC when timezone is nil" do
datetime = ~U[2026-01-15 14:34:00Z]
assert TimeHelpers.format_iso8601(datetime, nil) == "2026-01-15 14:34:00 UTC"
end
test "formats datetime in UTC when timezone is explicitly UTC" do
datetime = ~U[2026-01-15 14:34:00Z]
assert TimeHelpers.format_iso8601(datetime, "UTC") == "2026-01-15 14:34:00 UTC"
end
test "converts datetime to America/New_York timezone" do
datetime = ~U[2026-01-15 14:34:00Z]
# 14:34 UTC = 09:34 EST (UTC-5)
result = TimeHelpers.format_iso8601(datetime, "America/New_York")
assert result =~ "2026-01-15 09:34:00"
assert result =~ "EST"
end
test "converts datetime to America/Los_Angeles timezone" do
datetime = ~U[2026-01-15 14:34:00Z]
# 14:34 UTC = 06:34 PST (UTC-8)
result = TimeHelpers.format_iso8601(datetime, "America/Los_Angeles")
assert result =~ "2026-01-15 06:34:00"
assert result =~ "PST"
end
test "falls back to UTC for invalid timezone" do
datetime = ~U[2026-01-15 14:34:00Z]
assert TimeHelpers.format_iso8601(datetime, "Invalid/Timezone") == "2026-01-15 14:34:00 UTC"
end
test "returns 'Never' for nil datetime" do
assert TimeHelpers.format_iso8601(nil, "America/New_York") == "Never"
assert TimeHelpers.format_iso8601(nil, nil) == "Never"
end
end
describe "format_time_ago/1" do
test "formats seconds ago" do
datetime = DateTime.add(DateTime.utc_now(), -30, :second)
assert TimeHelpers.format_time_ago(datetime) =~ "s ago"
end
test "formats minutes ago" do
datetime = DateTime.add(DateTime.utc_now(), -120, :second)
assert TimeHelpers.format_time_ago(datetime) =~ "m ago"
end
test "formats hours ago" do
datetime = DateTime.add(DateTime.utc_now(), -7200, :second)
assert TimeHelpers.format_time_ago(datetime) =~ "h ago"
end
test "formats days ago" do
datetime = DateTime.add(DateTime.utc_now(), -172_800, :second)
assert TimeHelpers.format_time_ago(datetime) =~ "d ago"
end
test "returns 'Never' for nil datetime" do
assert TimeHelpers.format_time_ago(nil) == "Never"
end
end
end