From 8db24405fa121ad4673c3e104b9969391b5d22a5 Mon Sep 17 00:00:00 2001 From: Moritz Date: Mon, 23 Feb 2026 23:53:54 +0100 Subject: [PATCH] test: fee type column visibility, CSV export, export controller FieldVisibility pseudo fields and visible selection; MembersCSV fee type column; export accepts membership_fee_type and returns Fee Type column. --- test/mv/membership/members_csv_test.exs | 37 +++++++++++++++++++ .../member_export_controller_test.exs | 31 ++++++++++++++++ .../index/field_visibility_test.exs | 22 +++++++++++ 3 files changed, 90 insertions(+) diff --git a/test/mv/membership/members_csv_test.exs b/test/mv/membership/members_csv_test.exs index 6b0a300..7a4dfa3 100644 --- a/test/mv/membership/members_csv_test.exs +++ b/test/mv/membership/members_csv_test.exs @@ -199,6 +199,43 @@ defmodule Mv.Membership.MembersCSVTest do assert csv =~ "M,m@m.com,Paid" end + test "membership_fee_type column exports fee type name" do + columns = [ + %{header: "First Name", kind: :member_field, key: "first_name"}, + %{header: "Email", kind: :member_field, key: "email"}, + %{header: "Fee Type", kind: :membership_fee_type, key: :membership_fee_type} + ] + + member = %{ + first_name: "M", + email: "m@m.com", + membership_fee_type: %{id: "ft-1", name: "Standard"} + } + + iodata = MembersCSV.export([member], columns) + csv = IO.iodata_to_binary(iodata) + + assert csv =~ "Fee Type" + assert csv =~ "Standard" + assert csv =~ "M,m@m.com,Standard" + end + + test "membership_fee_type column exports empty when no fee type" do + columns = [ + %{header: "First Name", kind: :member_field, key: "first_name"}, + %{header: "Fee Type", kind: :membership_fee_type, key: :membership_fee_type} + ] + + member = %{first_name: "M", email: "m@m.com", membership_fee_type: nil} + + iodata = MembersCSV.export([member], columns) + csv = IO.iodata_to_binary(iodata) + + assert csv =~ "Fee Type" + assert csv =~ "M," + refute csv =~ "Standard" + end + test "CSV injection: formula-like and dangerous prefixes are escaped with apostrophe" do member = %{ first_name: "=SUM(A1:A10)", diff --git a/test/mv_web/controllers/member_export_controller_test.exs b/test/mv_web/controllers/member_export_controller_test.exs index b7fff60..de7b417 100644 --- a/test/mv_web/controllers/member_export_controller_test.exs +++ b/test/mv_web/controllers/member_export_controller_test.exs @@ -146,6 +146,37 @@ defmodule MvWeb.MemberExportControllerTest do refute header =~ "unknown_field" end + test "export includes membership_fee_type column when requested", %{ + conn: conn, + member1: m1 + } do + payload = %{ + "selected_ids" => [m1.id], + "member_fields" => ["first_name", "membership_fee_type", "email"], + "custom_field_ids" => [], + "query" => nil, + "sort_field" => nil, + "sort_order" => nil + } + + conn = get(conn, "/members") + csrf_token = csrf_token_from_conn(conn) + + conn = + post(conn, "/members/export.csv", %{ + "payload" => Jason.encode!(payload), + "_csrf_token" => csrf_token + }) + + assert conn.status == 200 + body = response(conn, 200) + header = body |> export_lines() |> hd() + + # Fee Type column is included (label from MemberFields.label(:membership_fee_type)) + assert header =~ "Fee Type" + assert body =~ "Alice" + end + test "export includes membership_fee_status computed field when requested", %{ conn: conn, member1: m1 diff --git a/test/mv_web/live/member_live/index/field_visibility_test.exs b/test/mv_web/live/member_live/index/field_visibility_test.exs index 83ae06d..d86893d 100644 --- a/test/mv_web/live/member_live/index/field_visibility_test.exs +++ b/test/mv_web/live/member_live/index/field_visibility_test.exs @@ -56,6 +56,14 @@ defmodule MvWeb.MemberLive.Index.FieldVisibilityTest do assert field in result end) end + + test "includes pseudo member fields (membership_fee_status, membership_fee_type, groups)" do + result = FieldVisibility.get_all_available_fields([]) + + assert :membership_fee_status in result + assert :membership_fee_type in result + assert :groups in result + end end describe "merge_with_global_settings/3" do @@ -278,6 +286,20 @@ defmodule MvWeb.MemberLive.Index.FieldVisibilityTest do test "handles invalid input" do assert FieldVisibility.get_visible_member_fields(nil) == [] end + + test "returns membership_fee_type when visible in selection" do + selection = %{ + "first_name" => true, + "membership_fee_type" => true, + "groups" => false + } + + result = FieldVisibility.get_visible_member_fields(selection) + + assert :membership_fee_type in result + assert :first_name in result + refute :groups in result + end end describe "get_visible_custom_fields/1" do