From 0ea54b63db9cf5b90b16b6dbdc129c4806a51e89 Mon Sep 17 00:00:00 2001 From: Graham McIntire Date: Fri, 6 Mar 2026 07:19:54 -0600 Subject: [PATCH] perf(tests): disable TOTP by default in fixtures for faster tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit **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 --- test/support/conn_case.ex | 4 ++-- test/support/fixtures/accounts_fixtures.ex | 7 ++++--- test/towerops/accounts/verify_totp_only_test.exs | 2 +- test/towerops/accounts_test.exs | 8 ++++---- test/towerops_web/live/admin/audit_live/index_test.exs | 2 +- test/towerops_web/live/admin/dashboard_live_test.exs | 2 +- test/towerops_web/live/admin/org_live/index_test.exs | 6 +++--- test/towerops_web/live/admin/security_live/index_test.exs | 4 ++-- test/towerops_web/live/org/preseem_devices_live_test.exs | 2 +- test/towerops_web/user_auth_test.exs | 2 +- 10 files changed, 20 insertions(+), 19 deletions(-) diff --git a/test/support/conn_case.ex b/test/support/conn_case.ex index a9e2895e..413e4947 100644 --- a/test/support/conn_case.ex +++ b/test/support/conn_case.ex @@ -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) diff --git a/test/support/fixtures/accounts_fixtures.ex b/test/support/fixtures/accounts_fixtures.ex index 0a865047..4a84627f 100644 --- a/test/support/fixtures/accounts_fixtures.ex +++ b/test/support/fixtures/accounts_fixtures.ex @@ -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) diff --git a/test/towerops/accounts/verify_totp_only_test.exs b/test/towerops/accounts/verify_totp_only_test.exs index f33a090c..e2d3ffea 100644 --- a/test/towerops/accounts/verify_totp_only_test.exs +++ b/test/towerops/accounts/verify_totp_only_test.exs @@ -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} = diff --git a/test/towerops/accounts_test.exs b/test/towerops/accounts_test.exs index 8a63affa..ba74f574 100644 --- a/test/towerops/accounts_test.exs +++ b/test/towerops/accounts_test.exs @@ -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} diff --git a/test/towerops_web/live/admin/audit_live/index_test.exs b/test/towerops_web/live/admin/audit_live/index_test.exs index 06bc68a1..0798103a 100644 --- a/test/towerops_web/live/admin/audit_live/index_test.exs +++ b/test/towerops_web/live/admin/audit_live/index_test.exs @@ -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) diff --git a/test/towerops_web/live/admin/dashboard_live_test.exs b/test/towerops_web/live/admin/dashboard_live_test.exs index 75a6b0ed..5954f034 100644 --- a/test/towerops_web/live/admin/dashboard_live_test.exs +++ b/test/towerops_web/live/admin/dashboard_live_test.exs @@ -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) diff --git a/test/towerops_web/live/admin/org_live/index_test.exs b/test/towerops_web/live/admin/org_live/index_test.exs index 0dc1a34a..d46927e5 100644 --- a/test/towerops_web/live/admin/org_live/index_test.exs +++ b/test/towerops_web/live/admin/org_live/index_test.exs @@ -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) diff --git a/test/towerops_web/live/admin/security_live/index_test.exs b/test/towerops_web/live/admin/security_live/index_test.exs index 1f0477bb..eac21cb1 100644 --- a/test/towerops_web/live/admin/security_live/index_test.exs +++ b/test/towerops_web/live/admin/security_live/index_test.exs @@ -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 = diff --git a/test/towerops_web/live/org/preseem_devices_live_test.exs b/test/towerops_web/live/org/preseem_devices_live_test.exs index 542e72f1..63efd1a0 100644 --- a/test/towerops_web/live/org/preseem_devices_live_test.exs +++ b/test/towerops_web/live/org/preseem_devices_live_test.exs @@ -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 diff --git a/test/towerops_web/user_auth_test.exs b/test/towerops_web/user_auth_test.exs index 47b3488a..29e3daec 100644 --- a/test/towerops_web/user_auth_test.exs +++ b/test/towerops_web/user_auth_test.exs @@ -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