Merge remote-tracking branch 'origin/main' into feature/ui-for-adding-members-groups
This commit is contained in:
commit
03f27a5938
33 changed files with 2765 additions and 501 deletions
73
test/mv_web/live/global_settings_live_config_test.exs
Normal file
73
test/mv_web/live/global_settings_live_config_test.exs
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
defmodule MvWeb.GlobalSettingsLiveConfigTest do
|
||||
@moduledoc """
|
||||
Tests for GlobalSettingsLive that modify global Application configuration.
|
||||
|
||||
These tests run with `async: false` to prevent race conditions when
|
||||
modifying global Application environment variables (Application.put_env).
|
||||
This follows the same pattern as Mv.ConfigTest.
|
||||
"""
|
||||
use MvWeb.ConnCase, async: false
|
||||
import Phoenix.LiveViewTest
|
||||
|
||||
# Helper function to upload CSV file in tests
|
||||
defp upload_csv_file(view, csv_content, filename) do
|
||||
view
|
||||
|> file_input("#csv-upload-form", :csv_file, [
|
||||
%{
|
||||
last_modified: System.system_time(:second),
|
||||
name: filename,
|
||||
content: csv_content,
|
||||
size: byte_size(csv_content),
|
||||
type: "text/csv"
|
||||
}
|
||||
])
|
||||
|> render_upload(filename)
|
||||
end
|
||||
|
||||
describe "CSV Import - Configuration Tests" do
|
||||
setup %{conn: conn} do
|
||||
# Ensure admin user
|
||||
admin_user = Mv.Fixtures.user_with_role_fixture("admin")
|
||||
conn = MvWeb.ConnCase.conn_with_password_user(conn, admin_user)
|
||||
|
||||
{:ok, conn: conn, admin_user: admin_user}
|
||||
end
|
||||
|
||||
test "configured row limit is enforced", %{conn: conn} do
|
||||
# Business rule: CSV import respects configured row limits
|
||||
# Test that a custom limit (500) is enforced, not just the default (1000)
|
||||
original_config = Application.get_env(:mv, :csv_import, [])
|
||||
|
||||
try do
|
||||
Application.put_env(:mv, :csv_import, max_rows: 500)
|
||||
|
||||
{:ok, view, _html} = live(conn, ~p"/settings")
|
||||
|
||||
# Generate CSV with 501 rows (exceeding custom limit of 500)
|
||||
header = "first_name;last_name;email;street;postal_code;city\n"
|
||||
|
||||
rows =
|
||||
for i <- 1..501 do
|
||||
"Row#{i};Last#{i};email#{i}@example.com;Street#{i};12345;City#{i}\n"
|
||||
end
|
||||
|
||||
large_csv = header <> Enum.join(rows)
|
||||
|
||||
# Simulate file upload using helper function
|
||||
upload_csv_file(view, large_csv, "too_many_rows_custom.csv")
|
||||
|
||||
view
|
||||
|> form("#csv-upload-form", %{})
|
||||
|> render_submit()
|
||||
|
||||
html = render(view)
|
||||
# Business rule: import should be rejected when exceeding configured limit
|
||||
assert html =~ "exceeds" or html =~ "maximum" or html =~ "limit" or
|
||||
html =~ "Failed to prepare"
|
||||
after
|
||||
# Restore original config
|
||||
Application.put_env(:mv, :csv_import, original_config)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -110,7 +110,7 @@ defmodule MvWeb.GlobalSettingsLiveTest do
|
|||
{:ok, _view, html} = live(conn, ~p"/settings")
|
||||
|
||||
# Check for custom fields notice text
|
||||
assert html =~ "Custom fields" or html =~ "custom field"
|
||||
assert html =~ "Use the data field name"
|
||||
end
|
||||
|
||||
test "admin user sees template download links", %{conn: conn} do
|
||||
|
|
@ -158,15 +158,12 @@ defmodule MvWeb.GlobalSettingsLiveTest do
|
|||
end
|
||||
|
||||
test "non-admin user does not see import section", %{conn: conn} do
|
||||
# Create non-admin user (member role)
|
||||
# Member (own_data) is redirected when accessing /settings (no page permission)
|
||||
member_user = Mv.Fixtures.user_with_role_fixture("own_data")
|
||||
conn = MvWeb.ConnCase.conn_with_password_user(conn, member_user)
|
||||
|
||||
{:ok, _view, html} = live(conn, ~p"/settings")
|
||||
|
||||
# Import section should not be visible
|
||||
refute html =~ "Import Members" or html =~ "CSV Import" or
|
||||
(html =~ "Import" and html =~ "CSV")
|
||||
assert {:error, {:redirect, %{to: to}}} = live(conn, ~p"/settings")
|
||||
assert to == "/users/#{member_user.id}"
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -236,15 +233,12 @@ defmodule MvWeb.GlobalSettingsLiveTest do
|
|||
end
|
||||
|
||||
test "non-admin cannot start import", %{conn: conn} do
|
||||
# Create non-admin user
|
||||
# Member (own_data) is redirected when accessing /settings (no page permission)
|
||||
member_user = Mv.Fixtures.user_with_role_fixture("own_data")
|
||||
conn = MvWeb.ConnCase.conn_with_password_user(conn, member_user)
|
||||
|
||||
{:ok, view, _html} = live(conn, ~p"/settings")
|
||||
|
||||
# Since non-admin shouldn't see the section, we check that import section is not visible
|
||||
html = render(view)
|
||||
refute html =~ "Import Members" or html =~ "CSV Import" or html =~ "start_import"
|
||||
assert {:error, {:redirect, %{to: to}}} = live(conn, ~p"/settings")
|
||||
assert to == "/users/#{member_user.id}"
|
||||
end
|
||||
|
||||
test "invalid CSV shows user-friendly error", %{conn: conn} do
|
||||
|
|
|
|||
|
|
@ -11,17 +11,8 @@ defmodule MvWeb.MembershipFeeTypeLive.FormTest do
|
|||
require Ash.Query
|
||||
|
||||
setup %{conn: conn} do
|
||||
system_actor = Mv.Helpers.SystemActor.get_system_actor()
|
||||
|
||||
# Create admin user
|
||||
{:ok, user} =
|
||||
Mv.Accounts.User
|
||||
|> Ash.Changeset.for_create(:register_with_password, %{
|
||||
email: "admin#{System.unique_integer([:positive])}@mv.local",
|
||||
password: "testpassword123"
|
||||
})
|
||||
|> Ash.create(actor: system_actor)
|
||||
|
||||
# User must have admin role (or normal_user) to access /membership_fee_types pages
|
||||
user = Mv.Fixtures.user_with_role_fixture("admin")
|
||||
authenticated_conn = conn_with_password_user(conn, user)
|
||||
%{conn: authenticated_conn, user: user}
|
||||
end
|
||||
|
|
|
|||
|
|
@ -29,8 +29,8 @@ defmodule MvWeb.MembershipFeeTypeLive.IndexTest do
|
|||
|> Ash.create!(actor: admin_user)
|
||||
end
|
||||
|
||||
# Helper to create a member
|
||||
# Uses admin actor from global setup to ensure authorization; falls back to system_actor when nil
|
||||
# Helper to create a member. Requires actor (e.g. admin_user from setup); no fallback so
|
||||
# missing-actor bugs are not masked in tests.
|
||||
defp create_member(attrs, actor) do
|
||||
default_attrs = %{
|
||||
first_name: "Test",
|
||||
|
|
@ -39,8 +39,7 @@ defmodule MvWeb.MembershipFeeTypeLive.IndexTest do
|
|||
}
|
||||
|
||||
attrs = Map.merge(default_attrs, attrs)
|
||||
effective_actor = actor || Mv.Helpers.SystemActor.get_system_actor()
|
||||
{:ok, member} = Mv.Membership.create_member(attrs, actor: effective_actor)
|
||||
{:ok, member} = Mv.Membership.create_member(attrs, actor: actor)
|
||||
member
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -9,8 +9,8 @@ defmodule MvWeb.ProfileNavigationTest do
|
|||
|
||||
describe "profile navigation" do
|
||||
test "clicking profile button redirects to current user profile", %{conn: conn} do
|
||||
# Setup: Create and login a user
|
||||
user = create_test_user(%{email: "test@example.com"})
|
||||
# User needs a role with page permission for "/" (e.g. admin)
|
||||
user = Mv.Fixtures.user_with_role_fixture("admin")
|
||||
conn = conn_with_password_user(conn, user)
|
||||
{:ok, view, _html} = live(conn, "/")
|
||||
|
||||
|
|
@ -21,9 +21,18 @@ defmodule MvWeb.ProfileNavigationTest do
|
|||
assert_redirected(view, "/users/#{user.id}")
|
||||
end
|
||||
|
||||
test "profile navigation shows correct user data", %{conn: conn} do
|
||||
# Setup: Create and login a user
|
||||
test "profile navigation shows correct user data", %{conn: conn, actor: actor} do
|
||||
# User with password (from create_test_user) and admin role so they can access "/"
|
||||
user = create_test_user(%{email: "test@example.com"})
|
||||
admin_role = Mv.Fixtures.role_fixture("admin")
|
||||
|
||||
{:ok, user} =
|
||||
user
|
||||
|> Ash.Changeset.for_update(:update, %{})
|
||||
|> Ash.Changeset.manage_relationship(:role, admin_role, type: :append_and_remove)
|
||||
|> Ash.update(actor: actor)
|
||||
|
||||
user = Ash.load!(user, :role, domain: Mv.Accounts, actor: actor)
|
||||
conn = conn_with_password_user(conn, user)
|
||||
|
||||
# Navigate to profile
|
||||
|
|
@ -40,8 +49,8 @@ defmodule MvWeb.ProfileNavigationTest do
|
|||
|
||||
describe "sidebar" do
|
||||
test "renders profile button with correct attributes", %{conn: conn} do
|
||||
# Setup: Create and login a user
|
||||
user = create_test_user(%{email: "test@example.com"})
|
||||
# User needs a role with page permission for "/"
|
||||
user = Mv.Fixtures.user_with_role_fixture("admin")
|
||||
conn = conn_with_password_user(conn, user)
|
||||
{:ok, _view, html} = live(conn, "/")
|
||||
|
||||
|
|
@ -85,16 +94,27 @@ defmodule MvWeb.ProfileNavigationTest do
|
|||
})
|
||||
|> Ash.create!(domain: Mv.Accounts, actor: actor)
|
||||
|
||||
# Assign role so user can access "/" (page permission)
|
||||
admin_role = Mv.Fixtures.role_fixture("admin")
|
||||
|
||||
{:ok, user_with_role} =
|
||||
user
|
||||
|> Ash.Changeset.for_update(:update, %{})
|
||||
|> Ash.Changeset.manage_relationship(:role, admin_role, type: :append_and_remove)
|
||||
|> Ash.update(actor: actor)
|
||||
|
||||
user_with_role = Ash.load!(user_with_role, :role, domain: Mv.Accounts, actor: actor)
|
||||
|
||||
# Login user via OIDC
|
||||
conn = sign_in_user_via_oidc(conn, user)
|
||||
conn = sign_in_user_via_oidc(conn, user_with_role)
|
||||
|
||||
# Navigate to home and click profile
|
||||
{:ok, view, _html} = live(conn, "/")
|
||||
view |> element("a", "Profil") |> render_click()
|
||||
|
||||
# Verify we're on the correct profile page with OIDC specific information
|
||||
{:ok, _profile_view, html} = live(conn, "/users/#{user.id}")
|
||||
assert html =~ to_string(user.email)
|
||||
{:ok, _profile_view, html} = live(conn, "/users/#{user_with_role.id}")
|
||||
assert html =~ to_string(user_with_role.email)
|
||||
# Password auth should be disabled for OIDC users
|
||||
assert html =~ "Not enabled"
|
||||
end
|
||||
|
|
@ -103,14 +123,10 @@ defmodule MvWeb.ProfileNavigationTest do
|
|||
conn: conn,
|
||||
actor: actor
|
||||
} do
|
||||
# Create password user
|
||||
password_user =
|
||||
create_test_user(%{
|
||||
email: "password2@example.com",
|
||||
password: "test_password123"
|
||||
})
|
||||
# Users need a role with page permission for "/"
|
||||
password_user = Mv.Fixtures.user_with_role_fixture("admin")
|
||||
|
||||
# Create OIDC user
|
||||
# Create OIDC user and assign admin role
|
||||
user_info = %{
|
||||
"sub" => "oidc_789",
|
||||
"preferred_username" => "oidc@example.com"
|
||||
|
|
@ -129,6 +145,17 @@ defmodule MvWeb.ProfileNavigationTest do
|
|||
})
|
||||
|> Ash.create!(domain: Mv.Accounts, actor: actor)
|
||||
|
||||
admin_role = Mv.Fixtures.role_fixture("admin")
|
||||
|
||||
{:ok, oidc_user_with_role} =
|
||||
oidc_user
|
||||
|> Ash.Changeset.for_update(:update, %{})
|
||||
|> Ash.Changeset.manage_relationship(:role, admin_role, type: :append_and_remove)
|
||||
|> Ash.update(actor: actor)
|
||||
|
||||
oidc_user_with_role =
|
||||
Ash.load!(oidc_user_with_role, :role, domain: Mv.Accounts, actor: actor)
|
||||
|
||||
# Test with password user
|
||||
conn_password = conn_with_password_user(conn, password_user)
|
||||
{:ok, view_password, _html} = live(conn_password, "/")
|
||||
|
|
@ -136,16 +163,17 @@ defmodule MvWeb.ProfileNavigationTest do
|
|||
assert_redirected(view_password, "/users/#{password_user.id}")
|
||||
|
||||
# Test with OIDC user
|
||||
conn_oidc = sign_in_user_via_oidc(conn, oidc_user)
|
||||
conn_oidc = sign_in_user_via_oidc(conn, oidc_user_with_role)
|
||||
{:ok, view_oidc, _html} = live(conn_oidc, "/")
|
||||
view_oidc |> element("a", "Profil") |> render_click()
|
||||
assert_redirected(view_oidc, "/users/#{oidc_user.id}")
|
||||
assert_redirected(view_oidc, "/users/#{oidc_user_with_role.id}")
|
||||
end
|
||||
end
|
||||
|
||||
describe "authenticated views" do
|
||||
# User must have a role with page permission to access /members, /users, etc.
|
||||
setup %{conn: conn} do
|
||||
user = create_test_user(%{email: "test@example.com"})
|
||||
user = Mv.Fixtures.user_with_role_fixture("admin")
|
||||
conn = conn_with_password_user(conn, user)
|
||||
{:ok, conn: conn, user: user}
|
||||
end
|
||||
|
|
|
|||
|
|
@ -441,18 +441,11 @@ defmodule MvWeb.RoleLiveTest do
|
|||
end
|
||||
|
||||
test "only admin can access /admin/roles", %{conn: conn, actor: actor} do
|
||||
{conn, _user} = create_non_admin_user(conn, actor)
|
||||
{conn, user} = create_non_admin_user(conn, actor)
|
||||
|
||||
# Non-admin should be redirected or see error
|
||||
# Note: Authorization is checked via can_access_page? which returns false
|
||||
# The page might still mount but show no content or redirect
|
||||
# For now, we just verify the page doesn't work as expected for non-admin
|
||||
{:ok, _view, html} = live(conn, "/admin/roles")
|
||||
|
||||
# Non-admin should not see "New Role" button (can? returns false)
|
||||
# But the button might still be in HTML, just hidden or disabled
|
||||
# We verify that the page loads but admin features are restricted
|
||||
assert html =~ "Listing Roles" || html =~ "Roles"
|
||||
# Non-admin (no role or non-admin role) is redirected by CheckPagePermission plug
|
||||
assert {:error, {:redirect, %{to: to}}} = live(conn, "/admin/roles")
|
||||
assert to == "/users/#{user.id}"
|
||||
end
|
||||
|
||||
test "admin can access /admin/roles", %{conn: conn, actor: actor} do
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue