towerops/test/towerops/workers/session_cleanup_worker_test.exs
Graham McIntire 348975dcc9 Rewrite polling_offset, changelog_parser, and user_agent_parser in Gleam (#103)
Migrate three pure-function modules from Elixir to Gleam:

- polling_offset: deterministic hash-based polling offset (pure Gleam, no FFI)
- changelog_parser: text parsing logic in Gleam, thin Elixir wrapper for File I/O
- user_agent_parser: regex-based UA parsing in Gleam with Erlang FFI for
  atom-keyed map conversion

Add gleam_regexp dependency for regex support in Gleam modules.
Update all call sites and tests to use Gleam module atoms.

Reviewed-on: graham/towerops-web#103
2026-03-21 10:11:06 -05:00

150 lines
4.8 KiB
Elixir

defmodule Towerops.Workers.SessionCleanupWorkerTest do
use Towerops.DataCase, async: true
import Towerops.AccountsFixtures
alias Towerops.Accounts
alias Towerops.Accounts.BrowserSession
alias Towerops.Workers.SessionCleanupWorker
describe "perform/1" do
test "deletes expired browser sessions" do
user = user_fixture()
{_token, user_token} = Accounts.generate_user_session_token_with_record(user)
# Create an expired session (1 day ago)
expired_session =
insert_browser_session(%{
user_id: user.id,
user_token_id: user_token.id,
expires_at: DateTime.add(DateTime.utc_now(), -1, :day)
})
# Execute the worker
assert {:ok, %{sessions_deleted: 1}} =
SessionCleanupWorker.perform(%Oban.Job{args: %{}})
# Verify expired session was deleted
refute Repo.get(BrowserSession, expired_session.id)
end
test "keeps non-expired browser sessions" do
user = user_fixture()
{_token, user_token} = Accounts.generate_user_session_token_with_record(user)
# Create a valid session (expires in 1 day)
valid_session =
insert_browser_session(%{
user_id: user.id,
user_token_id: user_token.id,
expires_at: DateTime.add(DateTime.utc_now(), 1, :day)
})
# Execute the worker
assert {:ok, %{sessions_deleted: 0}} =
SessionCleanupWorker.perform(%Oban.Job{args: %{}})
# Verify valid session still exists
assert Repo.get(BrowserSession, valid_session.id)
end
test "deletes only expired sessions among mixed sessions" do
user = user_fixture()
{_token1, user_token1} = Accounts.generate_user_session_token_with_record(user)
{_token2, user_token2} = Accounts.generate_user_session_token_with_record(user)
{_token3, user_token3} = Accounts.generate_user_session_token_with_record(user)
# Create 2 expired sessions
expired1 =
insert_browser_session(%{
user_id: user.id,
user_token_id: user_token1.id,
expires_at: DateTime.add(DateTime.utc_now(), -2, :day)
})
expired2 =
insert_browser_session(%{
user_id: user.id,
user_token_id: user_token2.id,
expires_at: DateTime.add(DateTime.utc_now(), -1, :hour)
})
# Create 1 valid session
valid_session =
insert_browser_session(%{
user_id: user.id,
user_token_id: user_token3.id,
expires_at: DateTime.add(DateTime.utc_now(), 7, :day)
})
# Execute the worker
assert {:ok, %{sessions_deleted: 2}} =
SessionCleanupWorker.perform(%Oban.Job{args: %{}})
# Verify expired sessions were deleted
refute Repo.get(BrowserSession, expired1.id)
refute Repo.get(BrowserSession, expired2.id)
# Verify valid session still exists
assert Repo.get(BrowserSession, valid_session.id)
end
test "returns zero count when no expired sessions exist" do
user = user_fixture()
{_token, user_token} = Accounts.generate_user_session_token_with_record(user)
# Create only valid sessions
insert_browser_session(%{
user_id: user.id,
user_token_id: user_token.id,
expires_at: DateTime.add(DateTime.utc_now(), 1, :day)
})
# Execute the worker
assert {:ok, %{sessions_deleted: 0}} =
SessionCleanupWorker.perform(%Oban.Job{args: %{}})
end
test "works when no sessions exist at all" do
# Execute the worker with no sessions in the database
assert {:ok, %{sessions_deleted: 0}} =
SessionCleanupWorker.perform(%Oban.Job{args: %{}})
end
test "handles sessions that expire at boundary conditions" do
user = user_fixture()
{_token, user_token} = Accounts.generate_user_session_token_with_record(user)
# Create a session that expires 1 minute in the future
# The query uses `expires_at < now`, so this should NOT be deleted
almost_expired =
insert_browser_session(%{
user_id: user.id,
user_token_id: user_token.id,
expires_at: DateTime.add(DateTime.utc_now(), 60, :second)
})
# Execute the worker
assert {:ok, %{sessions_deleted: count}} =
SessionCleanupWorker.perform(%Oban.Job{args: %{}})
# The session should NOT be deleted (expires_at is still in the future)
assert count == 0
assert Repo.get(BrowserSession, almost_expired.id)
end
end
# Helper function to create browser sessions
defp insert_browser_session(attrs) do
default_attrs = %{
ip_address: "192.168.1.1",
last_activity_at: DateTime.utc_now()
}
attrs = Map.merge(default_attrs, attrs)
%BrowserSession{}
|> BrowserSession.create_changeset(attrs)
|> Repo.insert!()
end
end