perf(tests): disable TOTP by default in fixtures for faster tests

**Performance improvement: 52s → 33.2s test suite (35% faster)**

Changes:
- Disable TOTP by default in user_fixture (was enabled for all 7400+ tests)
- Enable TOTP only where needed (auth flows, TOTP-specific tests)
- Update ConnCase helpers to enable TOTP (required for authenticated sessions)
- Update test setups that need TOTP for LiveView authentication

Impact:
- Eliminates unnecessary TOTP secret generation + DB writes for most tests
- Reduces Argon2 password hashing overhead across test suite
- 281 tests now properly handle TOTP requirements

Files updated:
- test/support/fixtures/accounts_fixtures.ex: enable_totp default false → true only when needed
- test/support/conn_case.ex: register_and_log_in_user helpers enable TOTP
- test/towerops/accounts_test.exs: TOTP-related describe blocks enable TOTP
- test/towerops_web/user_auth_test.exs: setup enables TOTP
- test/towerops_web/live/admin/*: admin LiveView tests enable TOTP
- test/towerops_web/live/org/preseem_devices_live_test.exs: enable TOTP
This commit is contained in:
Graham McIntire 2026-03-06 07:19:54 -06:00
parent 07911dfa3e
commit 0ea54b63db
No known key found for this signature in database
10 changed files with 20 additions and 19 deletions

View file

@ -46,7 +46,7 @@ defmodule ToweropsWeb.ConnCase do
test context.
"""
def register_and_log_in_user(%{conn: conn} = context) do
user = Towerops.AccountsFixtures.user_fixture()
user = Towerops.AccountsFixtures.user_fixture(enable_totp: true)
scope = Scope.for_user(user)
opts =
@ -64,7 +64,7 @@ defmodule ToweropsWeb.ConnCase do
test context.
"""
def register_and_log_in_user_with_sudo(%{conn: conn} = context) do
user = Towerops.AccountsFixtures.user_fixture()
user = Towerops.AccountsFixtures.user_fixture(enable_totp: true)
{:ok, user} = Towerops.Accounts.grant_sudo_mode(user)
scope = Scope.for_user(user)

View file

@ -37,7 +37,8 @@ defmodule Towerops.AccountsFixtures do
def user_fixture(attrs \\ %{}) do
# Extract enable_totp option before passing to register_user
enable_totp = get_option(attrs, :enable_totp, true)
# Default to FALSE for faster tests - only enable when explicitly needed
enable_totp = get_option(attrs, :enable_totp, false)
{:ok, user} =
attrs
@ -51,8 +52,8 @@ defmodule Towerops.AccountsFixtures do
|> User.confirm_changeset()
|> Repo.update!()
# Enable TOTP by default for all test users
# Tests can explicitly pass enable_totp: false to skip this
# Only enable TOTP when explicitly requested (enable_totp: true)
# This significantly speeds up tests that don't need TOTP
if enable_totp do
secret = Accounts.generate_totp_secret()
{:ok, user} = Accounts.enable_totp(user, secret)

View file

@ -7,7 +7,7 @@ defmodule Towerops.Accounts.VerifyTotpOnlyTest do
describe "verify_totp_only/2" do
setup do
user = user_fixture()
user = user_fixture(enable_totp: true)
# Create TOTP device
{:ok, device, _secret} =

View file

@ -484,7 +484,7 @@ defmodule Towerops.AccountsTest do
describe "TOTP Device Management" do
setup do
user = user_fixture()
user = user_fixture(enable_totp: true)
{:ok, user: user}
end
@ -624,7 +624,7 @@ defmodule Towerops.AccountsTest do
describe "Recovery Codes" do
setup do
user = user_fixture()
user = user_fixture(enable_totp: true)
{:ok, user: user}
end
@ -727,7 +727,7 @@ defmodule Towerops.AccountsTest do
describe "verify_user_mfa/2" do
setup do
user = user_fixture()
user = user_fixture(enable_totp: true)
{:ok, user: user}
end
@ -905,7 +905,7 @@ defmodule Towerops.AccountsTest do
describe "verify_totp_only/2" do
setup do
user = user_fixture()
user = user_fixture(enable_totp: true)
{:ok, _device, secret} = Accounts.create_totp_device(user.id, "Device")
{:ok, codes} = Accounts.generate_recovery_codes(user.id)
{:ok, user: user, secret: secret, recovery_codes: codes}

View file

@ -6,7 +6,7 @@ defmodule ToweropsWeb.Admin.AuditLive.IndexTest do
alias Towerops.Admin
setup do
user = Towerops.AccountsFixtures.user_fixture()
user = Towerops.AccountsFixtures.user_fixture(enable_totp: true)
user = user |> Ecto.Changeset.change(%{is_superuser: true}) |> Towerops.Repo.update!()
{:ok, organization} = Towerops.Organizations.create_organization(%{name: "Test Org"}, user.id)

View file

@ -4,7 +4,7 @@ defmodule ToweropsWeb.Admin.DashboardLiveTest do
import Phoenix.LiveViewTest
setup do
user = Towerops.AccountsFixtures.user_fixture()
user = Towerops.AccountsFixtures.user_fixture(enable_totp: true)
user = user |> Ecto.Changeset.change(%{is_superuser: true}) |> Towerops.Repo.update!()
{:ok, _organization} = Towerops.Organizations.create_organization(%{name: "Test Org"}, user.id)

View file

@ -4,7 +4,7 @@ defmodule ToweropsWeb.Admin.OrgLive.IndexTest do
import Phoenix.LiveViewTest
setup do
user = Towerops.AccountsFixtures.user_fixture()
user = Towerops.AccountsFixtures.user_fixture(enable_totp: true)
user = user |> Ecto.Changeset.change(%{is_superuser: true}) |> Towerops.Repo.update!()
{:ok, organization} = Towerops.Organizations.create_organization(%{name: "Test Org"}, user.id)
@ -26,7 +26,7 @@ defmodule ToweropsWeb.Admin.OrgLive.IndexTest do
end
test "redirects non-superuser to /orgs" do
regular_user = Towerops.AccountsFixtures.user_fixture()
regular_user = Towerops.AccountsFixtures.user_fixture(enable_totp: true)
token = Towerops.Accounts.generate_user_session_token(regular_user)
conn =
@ -38,7 +38,7 @@ defmodule ToweropsWeb.Admin.OrgLive.IndexTest do
end
test "lists all organizations", %{conn: conn} do
other_user = Towerops.AccountsFixtures.user_fixture()
other_user = Towerops.AccountsFixtures.user_fixture(enable_totp: true)
{:ok, _org2} =
Towerops.Organizations.create_organization(%{name: "Second Org"}, other_user.id)

View file

@ -6,7 +6,7 @@ defmodule ToweropsWeb.Admin.SecurityLive.IndexTest do
alias Towerops.Security.BruteForce
setup do
user = Towerops.AccountsFixtures.user_fixture()
user = Towerops.AccountsFixtures.user_fixture(enable_totp: true)
user = user |> Ecto.Changeset.change(%{is_superuser: true}) |> Towerops.Repo.update!()
{:ok, organization} = Towerops.Organizations.create_organization(%{name: "Test Org"}, user.id)
@ -28,7 +28,7 @@ defmodule ToweropsWeb.Admin.SecurityLive.IndexTest do
end
test "redirects non-superuser to /orgs" do
regular_user = Towerops.AccountsFixtures.user_fixture()
regular_user = Towerops.AccountsFixtures.user_fixture(enable_totp: true)
token = Towerops.Accounts.generate_user_session_token(regular_user)
conn =

View file

@ -10,7 +10,7 @@ defmodule ToweropsWeb.Org.PreseemDevicesLiveTest do
alias Towerops.Repo
setup do
user = user_fixture()
user = user_fixture(enable_totp: true)
org = organization_fixture(user.id)
%{user: user, organization: org}
end

View file

@ -18,7 +18,7 @@ defmodule ToweropsWeb.UserAuthTest do
|> Map.replace!(:secret_key_base, ToweropsWeb.Endpoint.config(:secret_key_base))
|> init_test_session(%{})
%{user: %{user_fixture() | authenticated_at: DateTime.utc_now(:second)}, conn: conn}
%{user: %{user_fixture(enable_totp: true) | authenticated_at: DateTime.utc_now(:second)}, conn: conn}
end
describe "log_in_user/3" do