Add actor parameter to all tests requiring authorization
All checks were successful
continuous-integration/drone/push Build is passing

This commit adds actor: system_actor to all Ash operations in tests that
require authorization.
This commit is contained in:
Moritz 2026-01-23 20:00:24 +01:00
parent 4c846f8bba
commit a6cdeaa18d
Signed by: moritz
GPG key ID: 1020A035E5DD0824
75 changed files with 4649 additions and 2865 deletions

View file

@ -12,6 +12,8 @@ defmodule MvWeb.MemberLive.FormErrorHandlingTest do
describe "error handling - flash messages" do
test "shows flash message when member creation fails with validation error", %{conn: conn} do
system_actor = Mv.Helpers.SystemActor.get_system_actor()
# Create a member with the same email to trigger uniqueness error
{:ok, _existing_member} =
Member
@ -20,7 +22,7 @@ defmodule MvWeb.MemberLive.FormErrorHandlingTest do
last_name: "Member",
email: "duplicate@example.com"
})
|> Ash.create()
|> Ash.create(actor: system_actor)
conn = conn_with_oidc_user(conn)
{:ok, view, _html} = live(conn, "/members/new")
@ -73,6 +75,8 @@ defmodule MvWeb.MemberLive.FormErrorHandlingTest do
end
test "shows flash message when member update fails", %{conn: conn} do
system_actor = Mv.Helpers.SystemActor.get_system_actor()
# Create a member to edit
{:ok, member} =
Member
@ -81,7 +85,7 @@ defmodule MvWeb.MemberLive.FormErrorHandlingTest do
last_name: "Member",
email: "original@example.com"
})
|> Ash.create()
|> Ash.create(actor: system_actor)
# Create another member with different email
{:ok, _other_member} =
@ -91,7 +95,7 @@ defmodule MvWeb.MemberLive.FormErrorHandlingTest do
last_name: "Member",
email: "other@example.com"
})
|> Ash.create()
|> Ash.create(actor: system_actor)
conn = conn_with_oidc_user(conn)
{:ok, view, _html} = live(conn, "/members/#{member.id}/edit")

View file

@ -13,6 +13,8 @@ defmodule MvWeb.MemberLive.FormMembershipFeeTypeTest do
# Helper to create a membership fee type
defp create_fee_type(attrs) do
system_actor = Mv.Helpers.SystemActor.get_system_actor()
default_attrs = %{
name: "Test Fee Type #{System.unique_integer([:positive])}",
amount: Decimal.new("50.00"),
@ -23,11 +25,13 @@ defmodule MvWeb.MemberLive.FormMembershipFeeTypeTest do
MembershipFeeType
|> Ash.Changeset.for_create(:create, attrs)
|> Ash.create!()
|> Ash.create!(actor: system_actor)
end
# Helper to create a member
defp create_member(attrs) do
system_actor = Mv.Helpers.SystemActor.get_system_actor()
default_attrs = %{
first_name: "Test",
last_name: "Member",
@ -38,7 +42,7 @@ defmodule MvWeb.MemberLive.FormMembershipFeeTypeTest do
Member
|> Ash.Changeset.for_create(:create_member, attrs)
|> Ash.create!()
|> Ash.create!(actor: system_actor)
end
describe "membership fee type dropdown" do
@ -123,10 +127,12 @@ defmodule MvWeb.MemberLive.FormMembershipFeeTypeTest do
|> render_submit()
# Verify member was created with fee type
system_actor = Mv.Helpers.SystemActor.get_system_actor()
member =
Member
|> Ash.Query.filter(email == ^form_data["member[email]"])
|> Ash.read_one!()
|> Ash.read_one!(actor: system_actor)
assert member.membership_fee_type_id == fee_type.id
end
@ -135,13 +141,14 @@ defmodule MvWeb.MemberLive.FormMembershipFeeTypeTest do
# Set default fee type in settings
fee_type = create_fee_type(%{interval: :yearly})
system_actor = Mv.Helpers.SystemActor.get_system_actor()
{:ok, settings} = Mv.Membership.get_settings()
settings
|> Ash.Changeset.for_update(:update_membership_fee_settings, %{
default_membership_fee_type_id: fee_type.id
})
|> Ash.update!()
|> Ash.update!(actor: system_actor)
{:ok, view, _html} = live(conn, "/members/new")
@ -156,6 +163,8 @@ defmodule MvWeb.MemberLive.FormMembershipFeeTypeTest do
conn: conn,
current_user: admin_user
} do
system_actor = Mv.Helpers.SystemActor.get_system_actor()
# Create custom field
custom_field =
Mv.Membership.CustomField
@ -164,7 +173,7 @@ defmodule MvWeb.MemberLive.FormMembershipFeeTypeTest do
value_type: :string,
required: false
})
|> Ash.create!()
|> Ash.create!(actor: system_actor)
# Create two fee types with same interval
fee_type1 = create_fee_type(%{name: "Type 1", interval: :yearly})
@ -250,6 +259,8 @@ defmodule MvWeb.MemberLive.FormMembershipFeeTypeTest do
end
test "removing custom field values works correctly", %{conn: conn, current_user: admin_user} do
system_actor = Mv.Helpers.SystemActor.get_system_actor()
# Create custom field
custom_field =
Mv.Membership.CustomField
@ -258,7 +269,7 @@ defmodule MvWeb.MemberLive.FormMembershipFeeTypeTest do
value_type: :string,
required: false
})
|> Ash.create!()
|> Ash.create!(actor: system_actor)
fee_type = create_fee_type(%{interval: :yearly})

View file

@ -13,6 +13,8 @@ defmodule MvWeb.MemberLive.Index.MembershipFeeStatusTest do
# Helper to create a membership fee type
defp create_fee_type(attrs) do
system_actor = Mv.Helpers.SystemActor.get_system_actor()
default_attrs = %{
name: "Test Fee Type #{System.unique_integer([:positive])}",
amount: Decimal.new("50.00"),
@ -23,11 +25,13 @@ defmodule MvWeb.MemberLive.Index.MembershipFeeStatusTest do
MembershipFeeType
|> Ash.Changeset.for_create(:create, attrs)
|> Ash.create!()
|> Ash.create!(actor: system_actor)
end
# Helper to create a member
defp create_member(attrs) do
system_actor = Mv.Helpers.SystemActor.get_system_actor()
default_attrs = %{
first_name: "Test",
last_name: "Member",
@ -38,13 +42,15 @@ defmodule MvWeb.MemberLive.Index.MembershipFeeStatusTest do
Member
|> Ash.Changeset.for_create(:create_member, attrs)
|> Ash.create!()
|> Ash.create!(actor: system_actor)
end
# Helper to create a cycle
# Note: Does not delete existing cycles - tests should manage their own test data
# If cleanup is needed, it should be done in setup or explicitly in the test
defp create_cycle(member, fee_type, attrs) do
system_actor = Mv.Helpers.SystemActor.get_system_actor()
default_attrs = %{
cycle_start: ~D[2023-01-01],
amount: Decimal.new("50.00"),
@ -57,7 +63,7 @@ defmodule MvWeb.MemberLive.Index.MembershipFeeStatusTest do
MembershipFeeCycle
|> Ash.Changeset.for_create(:create, attrs)
|> Ash.create!()
|> Ash.create!(actor: system_actor)
end
describe "load_cycles_for_members/2" do
@ -75,7 +81,8 @@ defmodule MvWeb.MemberLive.Index.MembershipFeeStatusTest do
|> Ash.Query.filter(id in [^member1.id, ^member2.id])
|> MembershipFeeStatus.load_cycles_for_members()
members = Ash.read!(query)
system_actor = Mv.Helpers.SystemActor.get_system_actor()
members = Ash.read!(query, actor: system_actor)
assert length(members) == 2
@ -94,19 +101,21 @@ defmodule MvWeb.MemberLive.Index.MembershipFeeStatusTest do
# Create member without fee type to avoid auto-generation
member = create_member(%{})
system_actor = Mv.Helpers.SystemActor.get_system_actor()
# Assign fee type
member =
member
|> Ash.Changeset.for_update(:update_member, %{membership_fee_type_id: fee_type.id})
|> Ash.update!()
|> Ash.update!(actor: system_actor)
# Delete any auto-generated cycles
cycles =
Mv.MembershipFees.MembershipFeeCycle
|> Ash.Query.filter(member_id == ^member.id)
|> Ash.read!()
|> Ash.read!(actor: system_actor)
Enum.each(cycles, fn cycle -> Ash.destroy!(cycle) end)
Enum.each(cycles, fn cycle -> Ash.destroy!(cycle, actor: system_actor) end)
# Create cycles with dates that ensure 2023 is last completed
# Use a fixed "today" date in 2024 to make 2023 the last completed
@ -137,19 +146,21 @@ defmodule MvWeb.MemberLive.Index.MembershipFeeStatusTest do
# Create member without fee type to avoid auto-generation
member = create_member(%{})
system_actor = Mv.Helpers.SystemActor.get_system_actor()
# Assign fee type
member =
member
|> Ash.Changeset.for_update(:update_member, %{membership_fee_type_id: fee_type.id})
|> Ash.update!()
|> Ash.update!(actor: system_actor)
# Delete any auto-generated cycles
cycles =
Mv.MembershipFees.MembershipFeeCycle
|> Ash.Query.filter(member_id == ^member.id)
|> Ash.read!()
|> Ash.read!(actor: system_actor)
Enum.each(cycles, fn cycle -> Ash.destroy!(cycle) end)
Enum.each(cycles, fn cycle -> Ash.destroy!(cycle, actor: system_actor) end)
# Create cycles - use current year for current cycle
today = Date.utc_today()
@ -176,19 +187,21 @@ defmodule MvWeb.MemberLive.Index.MembershipFeeStatusTest do
# Create member without fee type to avoid auto-generation
member = create_member(%{})
system_actor = Mv.Helpers.SystemActor.get_system_actor()
# Assign fee type
member =
member
|> Ash.Changeset.for_update(:update_member, %{membership_fee_type_id: fee_type.id})
|> Ash.update!()
|> Ash.update!(actor: system_actor)
# Delete any auto-generated cycles
cycles =
Mv.MembershipFees.MembershipFeeCycle
|> Ash.Query.filter(member_id == ^member.id)
|> Ash.read!()
|> Ash.read!(actor: system_actor)
Enum.each(cycles, fn cycle -> Ash.destroy!(cycle) end)
Enum.each(cycles, fn cycle -> Ash.destroy!(cycle, actor: system_actor) end)
# Load cycles and fee type first (will be empty)
member =

View file

@ -14,6 +14,8 @@ defmodule MvWeb.MemberLive.IndexCustomFieldsAccessibilityTest do
alias Mv.Membership.{CustomField, CustomFieldValue, Member}
setup do
system_actor = Mv.Helpers.SystemActor.get_system_actor()
# Create test member
{:ok, member} =
Member
@ -22,7 +24,7 @@ defmodule MvWeb.MemberLive.IndexCustomFieldsAccessibilityTest do
last_name: "Anderson",
email: "alice@example.com"
})
|> Ash.create()
|> Ash.create(actor: system_actor)
# Create custom field with show_in_overview: true
{:ok, field} =
@ -32,7 +34,7 @@ defmodule MvWeb.MemberLive.IndexCustomFieldsAccessibilityTest do
value_type: :string,
show_in_overview: true
})
|> Ash.create()
|> Ash.create(actor: system_actor)
# Create custom field value
{:ok, _cfv} =
@ -42,7 +44,7 @@ defmodule MvWeb.MemberLive.IndexCustomFieldsAccessibilityTest do
custom_field_id: field.id,
value: %{"_union_type" => "string", "_union_value" => "A001"}
})
|> Ash.create()
|> Ash.create(actor: system_actor)
%{member: member, field: field}
end

View file

@ -17,6 +17,8 @@ defmodule MvWeb.MemberLive.IndexCustomFieldsDisplayTest do
alias Mv.Membership.{CustomField, CustomFieldValue, Member}
setup do
system_actor = Mv.Helpers.SystemActor.get_system_actor()
# Create test members
{:ok, member1} =
Member
@ -25,7 +27,7 @@ defmodule MvWeb.MemberLive.IndexCustomFieldsDisplayTest do
last_name: "Anderson",
email: "alice@example.com"
})
|> Ash.create()
|> Ash.create(actor: system_actor)
{:ok, member2} =
Member
@ -34,7 +36,7 @@ defmodule MvWeb.MemberLive.IndexCustomFieldsDisplayTest do
last_name: "Brown",
email: "bob@example.com"
})
|> Ash.create()
|> Ash.create(actor: system_actor)
# Create custom fields
{:ok, field_show_string} =
@ -44,7 +46,7 @@ defmodule MvWeb.MemberLive.IndexCustomFieldsDisplayTest do
value_type: :string,
show_in_overview: true
})
|> Ash.create()
|> Ash.create(actor: system_actor)
{:ok, field_hide} =
CustomField
@ -53,7 +55,7 @@ defmodule MvWeb.MemberLive.IndexCustomFieldsDisplayTest do
value_type: :string,
show_in_overview: false
})
|> Ash.create()
|> Ash.create(actor: system_actor)
{:ok, field_show_integer} =
CustomField
@ -62,7 +64,7 @@ defmodule MvWeb.MemberLive.IndexCustomFieldsDisplayTest do
value_type: :integer,
show_in_overview: true
})
|> Ash.create()
|> Ash.create(actor: system_actor)
{:ok, field_show_boolean} =
CustomField
@ -71,7 +73,7 @@ defmodule MvWeb.MemberLive.IndexCustomFieldsDisplayTest do
value_type: :boolean,
show_in_overview: true
})
|> Ash.create()
|> Ash.create(actor: system_actor)
{:ok, field_show_date} =
CustomField
@ -80,7 +82,7 @@ defmodule MvWeb.MemberLive.IndexCustomFieldsDisplayTest do
value_type: :date,
show_in_overview: true
})
|> Ash.create()
|> Ash.create(actor: system_actor)
{:ok, field_show_email} =
CustomField
@ -89,7 +91,7 @@ defmodule MvWeb.MemberLive.IndexCustomFieldsDisplayTest do
value_type: :email,
show_in_overview: true
})
|> Ash.create()
|> Ash.create(actor: system_actor)
# Create custom field values for member1
{:ok, _cfv1} =
@ -99,7 +101,7 @@ defmodule MvWeb.MemberLive.IndexCustomFieldsDisplayTest do
custom_field_id: field_show_string.id,
value: %{"_union_type" => "string", "_union_value" => "+49123456789"}
})
|> Ash.create()
|> Ash.create(actor: system_actor)
{:ok, _cfv2} =
CustomFieldValue
@ -108,7 +110,7 @@ defmodule MvWeb.MemberLive.IndexCustomFieldsDisplayTest do
custom_field_id: field_show_integer.id,
value: %{"_union_type" => "integer", "_union_value" => 12_345}
})
|> Ash.create()
|> Ash.create(actor: system_actor)
{:ok, _cfv3} =
CustomFieldValue
@ -117,7 +119,7 @@ defmodule MvWeb.MemberLive.IndexCustomFieldsDisplayTest do
custom_field_id: field_show_boolean.id,
value: %{"_union_type" => "boolean", "_union_value" => true}
})
|> Ash.create()
|> Ash.create(actor: system_actor)
{:ok, _cfv4} =
CustomFieldValue
@ -126,7 +128,7 @@ defmodule MvWeb.MemberLive.IndexCustomFieldsDisplayTest do
custom_field_id: field_show_date.id,
value: %{"_union_type" => "date", "_union_value" => ~D[1990-05-15]}
})
|> Ash.create()
|> Ash.create(actor: system_actor)
{:ok, _cfv5} =
CustomFieldValue
@ -135,7 +137,7 @@ defmodule MvWeb.MemberLive.IndexCustomFieldsDisplayTest do
custom_field_id: field_show_email.id,
value: %{"_union_type" => "email", "_union_value" => "alice.private@example.com"}
})
|> Ash.create()
|> Ash.create(actor: system_actor)
# Create hidden custom field value (should not be displayed)
{:ok, _cfv_hidden} =
@ -145,7 +147,7 @@ defmodule MvWeb.MemberLive.IndexCustomFieldsDisplayTest do
custom_field_id: field_hide.id,
value: %{"_union_type" => "string", "_union_value" => "Internal note"}
})
|> Ash.create()
|> Ash.create(actor: system_actor)
%{
member1: member1,

View file

@ -13,6 +13,8 @@ defmodule MvWeb.MemberLive.IndexCustomFieldsEdgeCasesTest do
alias Mv.Membership.{CustomField, Member}
test "displays custom field column even when no members have values", %{conn: conn} do
system_actor = Mv.Helpers.SystemActor.get_system_actor()
# Create test members without custom field values
{:ok, _member1} =
Member
@ -21,7 +23,7 @@ defmodule MvWeb.MemberLive.IndexCustomFieldsEdgeCasesTest do
last_name: "Anderson",
email: "alice@example.com"
})
|> Ash.create()
|> Ash.create(actor: system_actor)
{:ok, _member2} =
Member
@ -30,7 +32,7 @@ defmodule MvWeb.MemberLive.IndexCustomFieldsEdgeCasesTest do
last_name: "Brown",
email: "bob@example.com"
})
|> Ash.create()
|> Ash.create(actor: system_actor)
# Create custom field with show_in_overview: true but no values
{:ok, field} =
@ -40,7 +42,7 @@ defmodule MvWeb.MemberLive.IndexCustomFieldsEdgeCasesTest do
value_type: :string,
show_in_overview: true
})
|> Ash.create()
|> Ash.create(actor: system_actor)
conn = conn_with_oidc_user(conn)
{:ok, _view, html} = live(conn, "/members")
@ -50,6 +52,8 @@ defmodule MvWeb.MemberLive.IndexCustomFieldsEdgeCasesTest do
end
test "displays very long custom field values correctly", %{conn: conn} do
system_actor = Mv.Helpers.SystemActor.get_system_actor()
# Create test member
{:ok, member} =
Member
@ -58,7 +62,7 @@ defmodule MvWeb.MemberLive.IndexCustomFieldsEdgeCasesTest do
last_name: "Anderson",
email: "alice@example.com"
})
|> Ash.create()
|> Ash.create(actor: system_actor)
# Create custom field
{:ok, field} =
@ -68,7 +72,7 @@ defmodule MvWeb.MemberLive.IndexCustomFieldsEdgeCasesTest do
value_type: :string,
show_in_overview: true
})
|> Ash.create()
|> Ash.create(actor: system_actor)
# Create very long value (but within limits)
long_value = String.duplicate("A", 500)
@ -80,7 +84,7 @@ defmodule MvWeb.MemberLive.IndexCustomFieldsEdgeCasesTest do
custom_field_id: field.id,
value: %{"_union_type" => "string", "_union_value" => long_value}
})
|> Ash.create()
|> Ash.create(actor: system_actor)
conn = conn_with_oidc_user(conn)
{:ok, _view, html} = live(conn, "/members")
@ -91,6 +95,8 @@ defmodule MvWeb.MemberLive.IndexCustomFieldsEdgeCasesTest do
end
test "handles multiple custom fields with show_in_overview correctly", %{conn: conn} do
system_actor = Mv.Helpers.SystemActor.get_system_actor()
# Create test member
{:ok, member} =
Member
@ -99,7 +105,7 @@ defmodule MvWeb.MemberLive.IndexCustomFieldsEdgeCasesTest do
last_name: "Anderson",
email: "alice@example.com"
})
|> Ash.create()
|> Ash.create(actor: system_actor)
# Create multiple custom fields with show_in_overview: true
{:ok, field1} =
@ -109,7 +115,7 @@ defmodule MvWeb.MemberLive.IndexCustomFieldsEdgeCasesTest do
value_type: :string,
show_in_overview: true
})
|> Ash.create()
|> Ash.create(actor: system_actor)
{:ok, field2} =
CustomField
@ -118,7 +124,7 @@ defmodule MvWeb.MemberLive.IndexCustomFieldsEdgeCasesTest do
value_type: :string,
show_in_overview: true
})
|> Ash.create()
|> Ash.create(actor: system_actor)
{:ok, field3} =
CustomField
@ -127,7 +133,7 @@ defmodule MvWeb.MemberLive.IndexCustomFieldsEdgeCasesTest do
value_type: :string,
show_in_overview: true
})
|> Ash.create()
|> Ash.create(actor: system_actor)
# Create values for all fields
{:ok, _cfv1} =
@ -137,7 +143,7 @@ defmodule MvWeb.MemberLive.IndexCustomFieldsEdgeCasesTest do
custom_field_id: field1.id,
value: %{"_union_type" => "string", "_union_value" => "Value1"}
})
|> Ash.create()
|> Ash.create(actor: system_actor)
{:ok, _cfv2} =
Mv.Membership.CustomFieldValue
@ -146,7 +152,7 @@ defmodule MvWeb.MemberLive.IndexCustomFieldsEdgeCasesTest do
custom_field_id: field2.id,
value: %{"_union_type" => "string", "_union_value" => "Value2"}
})
|> Ash.create()
|> Ash.create(actor: system_actor)
{:ok, _cfv3} =
Mv.Membership.CustomFieldValue
@ -155,7 +161,7 @@ defmodule MvWeb.MemberLive.IndexCustomFieldsEdgeCasesTest do
custom_field_id: field3.id,
value: %{"_union_type" => "string", "_union_value" => "Value3"}
})
|> Ash.create()
|> Ash.create(actor: system_actor)
conn = conn_with_oidc_user(conn)
{:ok, _view, html} = live(conn, "/members")

View file

@ -16,6 +16,8 @@ defmodule MvWeb.MemberLive.IndexCustomFieldsSortingTest do
alias Mv.Membership.{CustomField, CustomFieldValue, Member}
setup do
system_actor = Mv.Helpers.SystemActor.get_system_actor()
# Create test members
{:ok, member1} =
Member
@ -24,7 +26,7 @@ defmodule MvWeb.MemberLive.IndexCustomFieldsSortingTest do
last_name: "Anderson",
email: "alice@example.com"
})
|> Ash.create()
|> Ash.create(actor: system_actor)
{:ok, member2} =
Member
@ -33,7 +35,7 @@ defmodule MvWeb.MemberLive.IndexCustomFieldsSortingTest do
last_name: "Brown",
email: "bob@example.com"
})
|> Ash.create()
|> Ash.create(actor: system_actor)
{:ok, member3} =
Member
@ -42,7 +44,7 @@ defmodule MvWeb.MemberLive.IndexCustomFieldsSortingTest do
last_name: "Clark",
email: "charlie@example.com"
})
|> Ash.create()
|> Ash.create(actor: system_actor)
# Create custom field with show_in_overview: true
{:ok, field_string} =
@ -52,7 +54,7 @@ defmodule MvWeb.MemberLive.IndexCustomFieldsSortingTest do
value_type: :string,
show_in_overview: true
})
|> Ash.create()
|> Ash.create(actor: system_actor)
{:ok, field_integer} =
CustomField
@ -61,7 +63,7 @@ defmodule MvWeb.MemberLive.IndexCustomFieldsSortingTest do
value_type: :integer,
show_in_overview: true
})
|> Ash.create()
|> Ash.create(actor: system_actor)
# Create custom field values
{:ok, _cfv1} =
@ -71,7 +73,7 @@ defmodule MvWeb.MemberLive.IndexCustomFieldsSortingTest do
custom_field_id: field_string.id,
value: %{"_union_type" => "string", "_union_value" => "A001"}
})
|> Ash.create()
|> Ash.create(actor: system_actor)
{:ok, _cfv2} =
CustomFieldValue
@ -80,7 +82,7 @@ defmodule MvWeb.MemberLive.IndexCustomFieldsSortingTest do
custom_field_id: field_string.id,
value: %{"_union_type" => "string", "_union_value" => "C003"}
})
|> Ash.create()
|> Ash.create(actor: system_actor)
{:ok, _cfv3} =
CustomFieldValue
@ -89,7 +91,7 @@ defmodule MvWeb.MemberLive.IndexCustomFieldsSortingTest do
custom_field_id: field_string.id,
value: %{"_union_type" => "string", "_union_value" => "B002"}
})
|> Ash.create()
|> Ash.create(actor: system_actor)
{:ok, _cfv4} =
CustomFieldValue
@ -98,7 +100,7 @@ defmodule MvWeb.MemberLive.IndexCustomFieldsSortingTest do
custom_field_id: field_integer.id,
value: %{"_union_type" => "integer", "_union_value" => 10}
})
|> Ash.create()
|> Ash.create(actor: system_actor)
{:ok, _cfv5} =
CustomFieldValue
@ -107,7 +109,7 @@ defmodule MvWeb.MemberLive.IndexCustomFieldsSortingTest do
custom_field_id: field_integer.id,
value: %{"_union_type" => "integer", "_union_value" => 30}
})
|> Ash.create()
|> Ash.create(actor: system_actor)
{:ok, _cfv6} =
CustomFieldValue
@ -116,7 +118,7 @@ defmodule MvWeb.MemberLive.IndexCustomFieldsSortingTest do
custom_field_id: field_integer.id,
value: %{"_union_type" => "integer", "_union_value" => 20}
})
|> Ash.create()
|> Ash.create(actor: system_actor)
%{
member1: member1,
@ -236,6 +238,8 @@ defmodule MvWeb.MemberLive.IndexCustomFieldsSortingTest do
end
test "NULL values and empty strings are always sorted last (ASC)", %{conn: conn} do
system_actor = Mv.Helpers.SystemActor.get_system_actor()
# Create additional members with NULL and empty string values
{:ok, member_with_value} =
Member
@ -244,7 +248,7 @@ defmodule MvWeb.MemberLive.IndexCustomFieldsSortingTest do
last_name: "Test",
email: "withvalue@example.com"
})
|> Ash.create()
|> Ash.create(actor: system_actor)
{:ok, member_with_empty} =
Member
@ -253,7 +257,7 @@ defmodule MvWeb.MemberLive.IndexCustomFieldsSortingTest do
last_name: "Test",
email: "withempty@example.com"
})
|> Ash.create()
|> Ash.create(actor: system_actor)
{:ok, member_with_null} =
Member
@ -262,7 +266,7 @@ defmodule MvWeb.MemberLive.IndexCustomFieldsSortingTest do
last_name: "Test",
email: "withnull@example.com"
})
|> Ash.create()
|> Ash.create(actor: system_actor)
{:ok, member_with_another_value} =
Member
@ -271,7 +275,7 @@ defmodule MvWeb.MemberLive.IndexCustomFieldsSortingTest do
last_name: "Test",
email: "another@example.com"
})
|> Ash.create()
|> Ash.create(actor: system_actor)
# Create custom field
{:ok, field} =
@ -281,7 +285,7 @@ defmodule MvWeb.MemberLive.IndexCustomFieldsSortingTest do
value_type: :string,
show_in_overview: true
})
|> Ash.create()
|> Ash.create(actor: system_actor)
# Create values: one with actual value, one with empty string, one with NULL (no value), another with value
{:ok, _cfv1} =
@ -291,7 +295,7 @@ defmodule MvWeb.MemberLive.IndexCustomFieldsSortingTest do
custom_field_id: field.id,
value: %{"_union_type" => "string", "_union_value" => "Zebra"}
})
|> Ash.create()
|> Ash.create(actor: system_actor)
{:ok, _cfv2} =
CustomFieldValue
@ -300,7 +304,7 @@ defmodule MvWeb.MemberLive.IndexCustomFieldsSortingTest do
custom_field_id: field.id,
value: %{"_union_type" => "string", "_union_value" => ""}
})
|> Ash.create()
|> Ash.create(actor: system_actor)
# member_with_null has no custom field value (NULL)
@ -311,7 +315,7 @@ defmodule MvWeb.MemberLive.IndexCustomFieldsSortingTest do
custom_field_id: field.id,
value: %{"_union_type" => "string", "_union_value" => "Apple"}
})
|> Ash.create()
|> Ash.create(actor: system_actor)
conn = conn_with_oidc_user(conn)
@ -347,6 +351,8 @@ defmodule MvWeb.MemberLive.IndexCustomFieldsSortingTest do
end
test "NULL values and empty strings are always sorted last (DESC)", %{conn: conn} do
system_actor = Mv.Helpers.SystemActor.get_system_actor()
# Create additional members with NULL and empty string values
{:ok, member_with_value} =
Member
@ -355,7 +361,7 @@ defmodule MvWeb.MemberLive.IndexCustomFieldsSortingTest do
last_name: "Test",
email: "withvalue@example.com"
})
|> Ash.create()
|> Ash.create(actor: system_actor)
{:ok, member_with_empty} =
Member
@ -364,7 +370,7 @@ defmodule MvWeb.MemberLive.IndexCustomFieldsSortingTest do
last_name: "Test",
email: "withempty@example.com"
})
|> Ash.create()
|> Ash.create(actor: system_actor)
{:ok, member_with_null} =
Member
@ -373,7 +379,7 @@ defmodule MvWeb.MemberLive.IndexCustomFieldsSortingTest do
last_name: "Test",
email: "withnull@example.com"
})
|> Ash.create()
|> Ash.create(actor: system_actor)
{:ok, member_with_another_value} =
Member
@ -382,7 +388,7 @@ defmodule MvWeb.MemberLive.IndexCustomFieldsSortingTest do
last_name: "Test",
email: "another@example.com"
})
|> Ash.create()
|> Ash.create(actor: system_actor)
# Create custom field
{:ok, field} =
@ -392,7 +398,7 @@ defmodule MvWeb.MemberLive.IndexCustomFieldsSortingTest do
value_type: :string,
show_in_overview: true
})
|> Ash.create()
|> Ash.create(actor: system_actor)
# Create values: one with actual value, one with empty string, one with NULL (no value), another with value
{:ok, _cfv1} =
@ -402,7 +408,7 @@ defmodule MvWeb.MemberLive.IndexCustomFieldsSortingTest do
custom_field_id: field.id,
value: %{"_union_type" => "string", "_union_value" => "Apple"}
})
|> Ash.create()
|> Ash.create(actor: system_actor)
{:ok, _cfv2} =
CustomFieldValue
@ -411,7 +417,7 @@ defmodule MvWeb.MemberLive.IndexCustomFieldsSortingTest do
custom_field_id: field.id,
value: %{"_union_type" => "string", "_union_value" => ""}
})
|> Ash.create()
|> Ash.create(actor: system_actor)
# member_with_null has no custom field value (NULL)
@ -422,7 +428,7 @@ defmodule MvWeb.MemberLive.IndexCustomFieldsSortingTest do
custom_field_id: field.id,
value: %{"_union_type" => "string", "_union_value" => "Zebra"}
})
|> Ash.create()
|> Ash.create(actor: system_actor)
conn = conn_with_oidc_user(conn)

View file

@ -19,6 +19,8 @@ defmodule MvWeb.MemberLive.IndexFieldVisibilityTest do
alias Mv.Membership.{CustomField, CustomFieldValue, Member}
setup do
system_actor = Mv.Helpers.SystemActor.get_system_actor()
# Create test members
{:ok, member1} =
Member
@ -29,7 +31,7 @@ defmodule MvWeb.MemberLive.IndexFieldVisibilityTest do
street: "Main St",
city: "Berlin"
})
|> Ash.create()
|> Ash.create(actor: system_actor)
{:ok, member2} =
Member
@ -40,7 +42,7 @@ defmodule MvWeb.MemberLive.IndexFieldVisibilityTest do
street: "Second St",
city: "Hamburg"
})
|> Ash.create()
|> Ash.create(actor: system_actor)
# Create custom field
{:ok, custom_field} =
@ -50,7 +52,7 @@ defmodule MvWeb.MemberLive.IndexFieldVisibilityTest do
value_type: :string,
show_in_overview: true
})
|> Ash.create()
|> Ash.create(actor: system_actor)
# Create custom field values
{:ok, _cfv1} =
@ -60,7 +62,7 @@ defmodule MvWeb.MemberLive.IndexFieldVisibilityTest do
custom_field_id: custom_field.id,
value: "M001"
})
|> Ash.create()
|> Ash.create(actor: system_actor)
{:ok, _cfv2} =
CustomFieldValue
@ -69,7 +71,7 @@ defmodule MvWeb.MemberLive.IndexFieldVisibilityTest do
custom_field_id: custom_field.id,
value: "M002"
})
|> Ash.create()
|> Ash.create(actor: system_actor)
%{
member1: member1,

View file

@ -6,6 +6,8 @@ defmodule MvWeb.MemberLive.IndexMemberFieldsDisplayTest do
alias Mv.Membership.Member
setup do
system_actor = Mv.Helpers.SystemActor.get_system_actor()
{:ok, member1} =
Member
|> Ash.Changeset.for_create(:create_member, %{
@ -18,7 +20,7 @@ defmodule MvWeb.MemberLive.IndexMemberFieldsDisplayTest do
city: "Berlin",
join_date: ~D[2020-01-15]
})
|> Ash.create()
|> Ash.create(actor: system_actor)
{:ok, member2} =
Member
@ -27,7 +29,7 @@ defmodule MvWeb.MemberLive.IndexMemberFieldsDisplayTest do
last_name: "Brown",
email: "bob@example.com"
})
|> Ash.create()
|> Ash.create(actor: system_actor)
%{
member1: member1,

View file

@ -14,6 +14,8 @@ defmodule MvWeb.MemberLive.IndexMembershipFeeStatusTest do
# Helper to create a membership fee type
defp create_fee_type(attrs) do
system_actor = Mv.Helpers.SystemActor.get_system_actor()
default_attrs = %{
name: "Test Fee Type #{System.unique_integer([:positive])}",
amount: Decimal.new("50.00"),
@ -24,11 +26,13 @@ defmodule MvWeb.MemberLive.IndexMembershipFeeStatusTest do
MembershipFeeType
|> Ash.Changeset.for_create(:create, attrs)
|> Ash.create!()
|> Ash.create!(actor: system_actor)
end
# Helper to create a member
defp create_member(attrs) do
system_actor = Mv.Helpers.SystemActor.get_system_actor()
default_attrs = %{
first_name: "Test",
last_name: "Member",
@ -39,18 +43,20 @@ defmodule MvWeb.MemberLive.IndexMembershipFeeStatusTest do
Member
|> Ash.Changeset.for_create(:create_member, attrs)
|> Ash.create!()
|> Ash.create!(actor: system_actor)
end
# Helper to create a cycle
defp create_cycle(member, fee_type, attrs) do
system_actor = Mv.Helpers.SystemActor.get_system_actor()
# Delete any auto-generated cycles first to avoid conflicts
existing_cycles =
MembershipFeeCycle
|> Ash.Query.filter(member_id == ^member.id)
|> Ash.read!()
|> Ash.read!(actor: system_actor)
Enum.each(existing_cycles, fn cycle -> Ash.destroy!(cycle) end)
Enum.each(existing_cycles, fn cycle -> Ash.destroy!(cycle, actor: system_actor) end)
default_attrs = %{
cycle_start: ~D[2023-01-01],
@ -64,7 +70,7 @@ defmodule MvWeb.MemberLive.IndexMembershipFeeStatusTest do
MembershipFeeCycle
|> Ash.Changeset.for_create(:create, attrs)
|> Ash.create!()
|> Ash.create!(actor: system_actor)
end
describe "status column display" do
@ -172,16 +178,18 @@ defmodule MvWeb.MemberLive.IndexMembershipFeeStatusTest do
member2 = create_member(%{first_name: "PaidMember", membership_fee_type_id: fee_type.id})
create_cycle(member2, fee_type, %{cycle_start: ~D[2023-01-01], status: :paid})
system_actor = Mv.Helpers.SystemActor.get_system_actor()
# Verify cycles exist in database
cycles1 =
MembershipFeeCycle
|> Ash.Query.filter(member_id == ^member1.id)
|> Ash.read!()
|> Ash.read!(actor: system_actor)
cycles2 =
MembershipFeeCycle
|> Ash.Query.filter(member_id == ^member2.id)
|> Ash.read!()
|> Ash.read!(actor: system_actor)
refute Enum.empty?(cycles1)
refute Enum.empty?(cycles2)
@ -206,16 +214,18 @@ defmodule MvWeb.MemberLive.IndexMembershipFeeStatusTest do
member2 = create_member(%{first_name: "PaidCurrent", membership_fee_type_id: fee_type.id})
create_cycle(member2, fee_type, %{cycle_start: current_year_start, status: :paid})
system_actor = Mv.Helpers.SystemActor.get_system_actor()
# Verify cycles exist in database
cycles1 =
MembershipFeeCycle
|> Ash.Query.filter(member_id == ^member1.id)
|> Ash.read!()
|> Ash.read!(actor: system_actor)
cycles2 =
MembershipFeeCycle
|> Ash.Query.filter(member_id == ^member2.id)
|> Ash.read!()
|> Ash.read!(actor: system_actor)
refute Enum.empty?(cycles1)
refute Enum.empty?(cycles2)

View file

@ -223,13 +223,18 @@ defmodule MvWeb.MemberLive.IndexTest do
end
test "can delete a member without error", %{conn: conn} do
system_actor = Mv.Helpers.SystemActor.get_system_actor()
# Create a test member first
{:ok, member} =
Mv.Membership.create_member(%{
first_name: "Test",
last_name: "User",
email: "test@example.com"
})
Mv.Membership.create_member(
%{
first_name: "Test",
last_name: "User",
email: "test@example.com"
},
actor: system_actor
)
conn = conn_with_oidc_user(conn)
{:ok, index_view, _html} = live(conn, "/members")
@ -251,27 +256,38 @@ defmodule MvWeb.MemberLive.IndexTest do
describe "copy_emails feature" do
setup do
system_actor = Mv.Helpers.SystemActor.get_system_actor()
# Create test members
{:ok, member1} =
Mv.Membership.create_member(%{
first_name: "Max",
last_name: "Mustermann",
email: "max@example.com"
})
Mv.Membership.create_member(
%{
first_name: "Max",
last_name: "Mustermann",
email: "max@example.com"
},
actor: system_actor
)
{:ok, member2} =
Mv.Membership.create_member(%{
first_name: "Erika",
last_name: "Musterfrau",
email: "erika@example.com"
})
Mv.Membership.create_member(
%{
first_name: "Erika",
last_name: "Musterfrau",
email: "erika@example.com"
},
actor: system_actor
)
{:ok, member3} =
Mv.Membership.create_member(%{
first_name: "Hans",
last_name: "Müller-Lüdenscheidt",
email: "hans@example.com"
})
Mv.Membership.create_member(
%{
first_name: "Hans",
last_name: "Müller-Lüdenscheidt",
email: "hans@example.com"
},
actor: system_actor
)
%{member1: member1, member2: member2, member3: member3}
end
@ -351,7 +367,8 @@ defmodule MvWeb.MemberLive.IndexTest do
render_click(view, "select_member", %{"id" => member1.id})
# Delete the member from the database
Ash.destroy!(member1)
system_actor = Mv.Helpers.SystemActor.get_system_actor()
Ash.destroy!(member1, actor: system_actor)
# Trigger copy_emails event directly - selection still contains the deleted ID
# but the member is no longer in @members list after reload
@ -391,12 +408,17 @@ defmodule MvWeb.MemberLive.IndexTest do
conn = conn_with_oidc_user(conn)
# Create a member with known data
system_actor = Mv.Helpers.SystemActor.get_system_actor()
{:ok, test_member} =
Mv.Membership.create_member(%{
first_name: "Test",
last_name: "Format",
email: "test.format@example.com"
})
Mv.Membership.create_member(
%{
first_name: "Test",
last_name: "Format",
email: "test.format@example.com"
},
actor: system_actor
)
{:ok, view, _html} = live(conn, "/members")
@ -461,7 +483,7 @@ defmodule MvWeb.MemberLive.IndexTest do
alias Mv.MembershipFees.MembershipFeeCycle
# Helper to create a membership fee type
defp create_fee_type(attrs) do
defp create_fee_type(attrs, actor) do
default_attrs = %{
name: "Test Fee Type #{System.unique_integer([:positive])}",
amount: Decimal.new("50.00"),
@ -472,11 +494,11 @@ defmodule MvWeb.MemberLive.IndexTest do
MembershipFeeType
|> Ash.Changeset.for_create(:create, attrs)
|> Ash.create!()
|> Ash.create!(actor: actor)
end
# Helper to create a member
defp create_member(attrs) do
defp create_member(attrs, actor) do
default_attrs = %{
first_name: "Test",
last_name: "Member",
@ -487,18 +509,18 @@ defmodule MvWeb.MemberLive.IndexTest do
Mv.Membership.Member
|> Ash.Changeset.for_create(:create_member, attrs)
|> Ash.create!()
|> Ash.create!(actor: actor)
end
# Helper to create a cycle
defp create_cycle(member, fee_type, attrs) do
defp create_cycle(member, fee_type, attrs, actor) do
# Delete any auto-generated cycles first to avoid conflicts
existing_cycles =
MembershipFeeCycle
|> Ash.Query.filter(member_id == ^member.id)
|> Ash.read!()
|> Ash.read!(actor: actor)
Enum.each(existing_cycles, fn cycle -> Ash.destroy!(cycle) end)
Enum.each(existing_cycles, fn cycle -> Ash.destroy!(cycle, actor: actor) end)
default_attrs = %{
cycle_start: ~D[2023-01-01],
@ -512,32 +534,49 @@ defmodule MvWeb.MemberLive.IndexTest do
MembershipFeeCycle
|> Ash.Changeset.for_create(:create, attrs)
|> Ash.create!()
|> Ash.create!(actor: actor)
end
test "filter shows only members with paid status in last cycle", %{conn: conn} do
system_actor = Mv.Helpers.SystemActor.get_system_actor()
conn = conn_with_oidc_user(conn)
fee_type = create_fee_type(%{interval: :yearly})
fee_type = create_fee_type(%{interval: :yearly}, system_actor)
today = Date.utc_today()
last_year_start = Date.new!(today.year - 1, 1, 1)
# Member with paid last cycle
paid_member =
create_member(%{
first_name: "PaidLast",
membership_fee_type_id: fee_type.id
})
create_member(
%{
first_name: "PaidLast",
membership_fee_type_id: fee_type.id
},
system_actor
)
create_cycle(paid_member, fee_type, %{cycle_start: last_year_start, status: :paid})
create_cycle(
paid_member,
fee_type,
%{cycle_start: last_year_start, status: :paid},
system_actor
)
# Member with unpaid last cycle
unpaid_member =
create_member(%{
first_name: "UnpaidLast",
membership_fee_type_id: fee_type.id
})
create_member(
%{
first_name: "UnpaidLast",
membership_fee_type_id: fee_type.id
},
system_actor
)
create_cycle(unpaid_member, fee_type, %{cycle_start: last_year_start, status: :unpaid})
create_cycle(
unpaid_member,
fee_type,
%{cycle_start: last_year_start, status: :unpaid},
system_actor
)
{:ok, _view, html} = live(conn, "/members?cycle_status_filter=paid")
@ -546,28 +585,45 @@ defmodule MvWeb.MemberLive.IndexTest do
end
test "filter shows only members with unpaid status in last cycle", %{conn: conn} do
system_actor = Mv.Helpers.SystemActor.get_system_actor()
conn = conn_with_oidc_user(conn)
fee_type = create_fee_type(%{interval: :yearly})
fee_type = create_fee_type(%{interval: :yearly}, system_actor)
today = Date.utc_today()
last_year_start = Date.new!(today.year - 1, 1, 1)
# Member with paid last cycle
paid_member =
create_member(%{
first_name: "PaidLast",
membership_fee_type_id: fee_type.id
})
create_member(
%{
first_name: "PaidLast",
membership_fee_type_id: fee_type.id
},
system_actor
)
create_cycle(paid_member, fee_type, %{cycle_start: last_year_start, status: :paid})
create_cycle(
paid_member,
fee_type,
%{cycle_start: last_year_start, status: :paid},
system_actor
)
# Member with unpaid last cycle
unpaid_member =
create_member(%{
first_name: "UnpaidLast",
membership_fee_type_id: fee_type.id
})
create_member(
%{
first_name: "UnpaidLast",
membership_fee_type_id: fee_type.id
},
system_actor
)
create_cycle(unpaid_member, fee_type, %{cycle_start: last_year_start, status: :unpaid})
create_cycle(
unpaid_member,
fee_type,
%{cycle_start: last_year_start, status: :unpaid},
system_actor
)
{:ok, _view, html} = live(conn, "/members?cycle_status_filter=unpaid")
@ -576,28 +632,45 @@ defmodule MvWeb.MemberLive.IndexTest do
end
test "filter shows only members with paid status in current cycle", %{conn: conn} do
system_actor = Mv.Helpers.SystemActor.get_system_actor()
conn = conn_with_oidc_user(conn)
fee_type = create_fee_type(%{interval: :yearly})
fee_type = create_fee_type(%{interval: :yearly}, system_actor)
today = Date.utc_today()
current_year_start = Date.new!(today.year, 1, 1)
# Member with paid current cycle
paid_member =
create_member(%{
first_name: "PaidCurrent",
membership_fee_type_id: fee_type.id
})
create_member(
%{
first_name: "PaidCurrent",
membership_fee_type_id: fee_type.id
},
system_actor
)
create_cycle(paid_member, fee_type, %{cycle_start: current_year_start, status: :paid})
create_cycle(
paid_member,
fee_type,
%{cycle_start: current_year_start, status: :paid},
system_actor
)
# Member with unpaid current cycle
unpaid_member =
create_member(%{
first_name: "UnpaidCurrent",
membership_fee_type_id: fee_type.id
})
create_member(
%{
first_name: "UnpaidCurrent",
membership_fee_type_id: fee_type.id
},
system_actor
)
create_cycle(unpaid_member, fee_type, %{cycle_start: current_year_start, status: :unpaid})
create_cycle(
unpaid_member,
fee_type,
%{cycle_start: current_year_start, status: :unpaid},
system_actor
)
{:ok, _view, html} = live(conn, "/members?cycle_status_filter=paid&show_current_cycle=true")
@ -606,28 +679,45 @@ defmodule MvWeb.MemberLive.IndexTest do
end
test "filter shows only members with unpaid status in current cycle", %{conn: conn} do
system_actor = Mv.Helpers.SystemActor.get_system_actor()
conn = conn_with_oidc_user(conn)
fee_type = create_fee_type(%{interval: :yearly})
fee_type = create_fee_type(%{interval: :yearly}, system_actor)
today = Date.utc_today()
current_year_start = Date.new!(today.year, 1, 1)
# Member with paid current cycle
paid_member =
create_member(%{
first_name: "PaidCurrent",
membership_fee_type_id: fee_type.id
})
create_member(
%{
first_name: "PaidCurrent",
membership_fee_type_id: fee_type.id
},
system_actor
)
create_cycle(paid_member, fee_type, %{cycle_start: current_year_start, status: :paid})
create_cycle(
paid_member,
fee_type,
%{cycle_start: current_year_start, status: :paid},
system_actor
)
# Member with unpaid current cycle
unpaid_member =
create_member(%{
first_name: "UnpaidCurrent",
membership_fee_type_id: fee_type.id
})
create_member(
%{
first_name: "UnpaidCurrent",
membership_fee_type_id: fee_type.id
},
system_actor
)
create_cycle(unpaid_member, fee_type, %{cycle_start: current_year_start, status: :unpaid})
create_cycle(
unpaid_member,
fee_type,
%{cycle_start: current_year_start, status: :unpaid},
system_actor
)
{:ok, _view, html} =
live(conn, "/members?cycle_status_filter=unpaid&show_current_cycle=true")

View file

@ -14,6 +14,8 @@ defmodule MvWeb.MemberLive.MembershipFeeIntegrationTest do
# Helper to create a membership fee type
defp create_fee_type(attrs) do
system_actor = Mv.Helpers.SystemActor.get_system_actor()
default_attrs = %{
name: "Test Fee Type #{System.unique_integer([:positive])}",
amount: Decimal.new("50.00"),
@ -24,11 +26,13 @@ defmodule MvWeb.MemberLive.MembershipFeeIntegrationTest do
MembershipFeeType
|> Ash.Changeset.for_create(:create, attrs)
|> Ash.create!()
|> Ash.create!(actor: system_actor)
end
# Helper to create a member
defp create_member(attrs) do
system_actor = Mv.Helpers.SystemActor.get_system_actor()
default_attrs = %{
first_name: "Test",
last_name: "Member",
@ -39,7 +43,7 @@ defmodule MvWeb.MemberLive.MembershipFeeIntegrationTest do
Member
|> Ash.Changeset.for_create(:create_member, attrs)
|> Ash.create!()
|> Ash.create!(actor: system_actor)
end
describe "end-to-end workflows" do
@ -75,7 +79,13 @@ defmodule MvWeb.MemberLive.MembershipFeeIntegrationTest do
|> render_click()
# Verify status changed
updated_cycle = Ash.read_one!(MembershipFeeCycle |> Ash.Query.filter(id == ^cycle.id))
system_actor = Mv.Helpers.SystemActor.get_system_actor()
updated_cycle =
Ash.read_one!(MembershipFeeCycle |> Ash.Query.filter(id == ^cycle.id),
actor: system_actor
)
assert updated_cycle.status == :paid
end
end
@ -115,13 +125,14 @@ defmodule MvWeb.MemberLive.MembershipFeeIntegrationTest do
fee_type = create_fee_type(%{interval: :yearly})
# Update settings
system_actor = Mv.Helpers.SystemActor.get_system_actor()
{:ok, settings} = Mv.Membership.get_settings()
settings
|> Ash.Changeset.for_update(:update_membership_fee_settings, %{
default_membership_fee_type_id: fee_type.id
})
|> Ash.update!()
|> Ash.update!(actor: system_actor)
# Create new member
{:ok, view, _html} = live(conn, "/members/new")
@ -138,10 +149,12 @@ defmodule MvWeb.MemberLive.MembershipFeeIntegrationTest do
|> render_submit()
# Verify member got default type
system_actor = Mv.Helpers.SystemActor.get_system_actor()
member =
Member
|> Ash.Query.filter(email == ^form_data["member[email]"])
|> Ash.read_one!()
|> Ash.read_one!(actor: system_actor)
assert member.membership_fee_type_id == fee_type.id
end
@ -150,6 +163,8 @@ defmodule MvWeb.MemberLive.MembershipFeeIntegrationTest do
fee_type = create_fee_type(%{interval: :yearly})
member = create_member(%{membership_fee_type_id: fee_type.id})
system_actor = Mv.Helpers.SystemActor.get_system_actor()
cycle =
MembershipFeeCycle
|> Ash.Changeset.for_create(:create, %{
@ -159,7 +174,7 @@ defmodule MvWeb.MemberLive.MembershipFeeIntegrationTest do
membership_fee_type_id: fee_type.id,
status: :unpaid
})
|> Ash.create!()
|> Ash.create!(actor: system_actor)
{:ok, view, _html} = live(conn, "/members/#{member.id}")
@ -187,6 +202,8 @@ defmodule MvWeb.MemberLive.MembershipFeeIntegrationTest do
fee_type = create_fee_type(%{interval: :yearly})
member = create_member(%{membership_fee_type_id: fee_type.id})
system_actor = Mv.Helpers.SystemActor.get_system_actor()
cycle =
MembershipFeeCycle
|> Ash.Changeset.for_create(:create, %{
@ -196,7 +213,7 @@ defmodule MvWeb.MemberLive.MembershipFeeIntegrationTest do
membership_fee_type_id: fee_type.id,
status: :unpaid
})
|> Ash.create!()
|> Ash.create!(actor: system_actor)
{:ok, view, _html} = live(conn, "/members/#{member.id}")
@ -216,7 +233,13 @@ defmodule MvWeb.MemberLive.MembershipFeeIntegrationTest do
|> render_submit()
# Verify amount updated
updated_cycle = Ash.read_one!(MembershipFeeCycle |> Ash.Query.filter(id == ^cycle.id))
system_actor = Mv.Helpers.SystemActor.get_system_actor()
updated_cycle =
Ash.read_one!(MembershipFeeCycle |> Ash.Query.filter(id == ^cycle.id),
actor: system_actor
)
assert updated_cycle.amount == Decimal.new("75.00")
end
end

View file

@ -14,6 +14,8 @@ defmodule MvWeb.MemberLive.ShowMembershipFeesTest do
# Helper to create a membership fee type
defp create_fee_type(attrs) do
system_actor = Mv.Helpers.SystemActor.get_system_actor()
default_attrs = %{
name: "Test Fee Type #{System.unique_integer([:positive])}",
amount: Decimal.new("50.00"),
@ -24,11 +26,13 @@ defmodule MvWeb.MemberLive.ShowMembershipFeesTest do
MembershipFeeType
|> Ash.Changeset.for_create(:create, attrs)
|> Ash.create!()
|> Ash.create!(actor: system_actor)
end
# Helper to create a member
defp create_member(attrs) do
system_actor = Mv.Helpers.SystemActor.get_system_actor()
default_attrs = %{
first_name: "Test",
last_name: "Member",
@ -39,18 +43,20 @@ defmodule MvWeb.MemberLive.ShowMembershipFeesTest do
Member
|> Ash.Changeset.for_create(:create_member, attrs)
|> Ash.create!()
|> Ash.create!(actor: system_actor)
end
# Helper to create a cycle
defp create_cycle(member, fee_type, attrs) do
system_actor = Mv.Helpers.SystemActor.get_system_actor()
# Delete any auto-generated cycles first to avoid conflicts
existing_cycles =
MembershipFeeCycle
|> Ash.Query.filter(member_id == ^member.id)
|> Ash.read!()
|> Ash.read!(actor: system_actor)
Enum.each(existing_cycles, fn cycle -> Ash.destroy!(cycle) end)
Enum.each(existing_cycles, fn cycle -> Ash.destroy!(cycle, actor: system_actor) end)
default_attrs = %{
cycle_start: ~D[2023-01-01],
@ -64,7 +70,7 @@ defmodule MvWeb.MemberLive.ShowMembershipFeesTest do
MembershipFeeCycle
|> Ash.Changeset.for_create(:create, attrs)
|> Ash.create!()
|> Ash.create!(actor: system_actor)
end
describe "cycles table display" do
@ -161,7 +167,13 @@ defmodule MvWeb.MemberLive.ShowMembershipFeesTest do
|> render_click()
# Verify cycle is now paid
updated_cycle = Ash.read_one!(MembershipFeeCycle |> Ash.Query.filter(id == ^cycle.id))
system_actor = Mv.Helpers.SystemActor.get_system_actor()
updated_cycle =
Ash.read_one!(MembershipFeeCycle |> Ash.Query.filter(id == ^cycle.id),
actor: system_actor
)
assert updated_cycle.status == :paid
end
@ -186,7 +198,13 @@ defmodule MvWeb.MemberLive.ShowMembershipFeesTest do
|> render_click()
# Verify cycle is now suspended
updated_cycle = Ash.read_one!(MembershipFeeCycle |> Ash.Query.filter(id == ^cycle.id))
system_actor = Mv.Helpers.SystemActor.get_system_actor()
updated_cycle =
Ash.read_one!(MembershipFeeCycle |> Ash.Query.filter(id == ^cycle.id),
actor: system_actor
)
assert updated_cycle.status == :suspended
end
@ -211,7 +229,13 @@ defmodule MvWeb.MemberLive.ShowMembershipFeesTest do
|> render_click()
# Verify cycle is now unpaid
updated_cycle = Ash.read_one!(MembershipFeeCycle |> Ash.Query.filter(id == ^cycle.id))
system_actor = Mv.Helpers.SystemActor.get_system_actor()
updated_cycle =
Ash.read_one!(MembershipFeeCycle |> Ash.Query.filter(id == ^cycle.id),
actor: system_actor
)
assert updated_cycle.status == :unpaid
end
end

View file

@ -21,6 +21,8 @@ defmodule MvWeb.MemberLive.ShowTest do
alias Mv.Membership.{CustomField, CustomFieldValue, Member}
setup do
system_actor = Mv.Helpers.SystemActor.get_system_actor()
# Create test member
{:ok, member} =
Member
@ -29,15 +31,16 @@ defmodule MvWeb.MemberLive.ShowTest do
last_name: "Anderson",
email: "alice@example.com"
})
|> Ash.create()
|> Ash.create(actor: system_actor)
%{member: member}
%{member: member, actor: system_actor}
end
describe "custom fields section visibility (Issue #282)" do
test "displays Custom Fields section even when member has no custom field values", %{
conn: conn,
member: member
member: member,
actor: actor
} do
# Create a custom field but no value for the member
{:ok, custom_field} =
@ -46,7 +49,7 @@ defmodule MvWeb.MemberLive.ShowTest do
name: "phone_mobile",
value_type: :string
})
|> Ash.create()
|> Ash.create(actor: actor)
conn = conn_with_oidc_user(conn)
{:ok, _view, html} = live(conn, ~p"/members/#{member}")
@ -63,7 +66,8 @@ defmodule MvWeb.MemberLive.ShowTest do
test "displays Custom Fields section with multiple custom fields, some without values", %{
conn: conn,
member: member
member: member,
actor: actor
} do
# Create multiple custom fields
{:ok, field1} =
@ -72,7 +76,7 @@ defmodule MvWeb.MemberLive.ShowTest do
name: "phone_mobile",
value_type: :string
})
|> Ash.create()
|> Ash.create(actor: actor)
{:ok, field2} =
CustomField
@ -80,7 +84,7 @@ defmodule MvWeb.MemberLive.ShowTest do
name: "membership_number",
value_type: :integer
})
|> Ash.create()
|> Ash.create(actor: actor)
# Create value only for first field
{:ok, _cfv} =
@ -90,7 +94,7 @@ defmodule MvWeb.MemberLive.ShowTest do
custom_field_id: field1.id,
value: %{"_union_type" => "string", "_union_value" => "+49123456789"}
})
|> Ash.create()
|> Ash.create(actor: actor)
conn = conn_with_oidc_user(conn)
{:ok, _view, html} = live(conn, ~p"/members/#{member}")
@ -111,18 +115,19 @@ defmodule MvWeb.MemberLive.ShowTest do
test "does not display Custom Fields section when no custom fields exist", %{
conn: conn,
member: member
member: member,
actor: actor
} do
# Ensure no custom fields exist for this test
# This ensures test isolation even if previous tests created custom fields
existing_custom_fields = Ash.read!(CustomField)
existing_custom_fields = Ash.read!(CustomField, actor: actor)
for cf <- existing_custom_fields do
Ash.destroy!(cf)
Ash.destroy!(cf, actor: actor)
end
# Verify no custom fields exist
assert Ash.read!(CustomField) == []
assert Ash.read!(CustomField, actor: actor) == []
conn = conn_with_oidc_user(conn)
{:ok, _view, html} = live(conn, ~p"/members/#{member}")
@ -133,14 +138,14 @@ defmodule MvWeb.MemberLive.ShowTest do
end
describe "custom field value formatting" do
test "formats string custom field values", %{conn: conn, member: member} do
test "formats string custom field values", %{conn: conn, member: member, actor: actor} do
{:ok, custom_field} =
CustomField
|> Ash.Changeset.for_create(:create, %{
name: "phone_mobile",
value_type: :string
})
|> Ash.create()
|> Ash.create(actor: actor)
{:ok, _cfv} =
CustomFieldValue
@ -149,7 +154,7 @@ defmodule MvWeb.MemberLive.ShowTest do
custom_field_id: custom_field.id,
value: %{"_union_type" => "string", "_union_value" => "+49123456789"}
})
|> Ash.create()
|> Ash.create(actor: actor)
conn = conn_with_oidc_user(conn)
{:ok, _view, html} = live(conn, ~p"/members/#{member}")
@ -157,14 +162,18 @@ defmodule MvWeb.MemberLive.ShowTest do
assert html =~ "+49123456789"
end
test "formats email custom field values as mailto links", %{conn: conn, member: member} do
test "formats email custom field values as mailto links", %{
conn: conn,
member: member,
actor: actor
} do
{:ok, custom_field} =
CustomField
|> Ash.Changeset.for_create(:create, %{
name: "private_email",
value_type: :email
})
|> Ash.create()
|> Ash.create(actor: actor)
{:ok, _cfv} =
CustomFieldValue
@ -173,7 +182,7 @@ defmodule MvWeb.MemberLive.ShowTest do
custom_field_id: custom_field.id,
value: %{"_union_type" => "email", "_union_value" => "private@example.com"}
})
|> Ash.create()
|> Ash.create(actor: actor)
conn = conn_with_oidc_user(conn)
{:ok, _view, html} = live(conn, ~p"/members/#{member}")