diff --git a/lib/mv/membership/import/member_csv.ex b/lib/mv/membership/import/member_csv.ex index 4222fc3..94c634b 100644 --- a/lib/mv/membership/import/member_csv.ex +++ b/lib/mv/membership/import/member_csv.ex @@ -299,7 +299,7 @@ defmodule Mv.Membership.Import.MemberCSV do custom_field_lookup = Keyword.get(opts, :custom_field_lookup, %{}) existing_error_count = Keyword.get(opts, :existing_error_count, 0) max_errors = Keyword.get(opts, :max_errors, @default_max_errors) - actor = Keyword.get(opts, :actor) + actor = Keyword.fetch!(opts, :actor) {inserted, failed, errors, _collected_error_count, truncated?} = Enum.reduce(chunk_rows_with_lines, {0, 0, [], 0, false}, fn {line_number, row_map}, diff --git a/test/mv/membership/import/member_csv_test.exs b/test/mv/membership/import/member_csv_test.exs index 5cb40d6..778e82b 100644 --- a/test/mv/membership/import/member_csv_test.exs +++ b/test/mv/membership/import/member_csv_test.exs @@ -73,25 +73,33 @@ defmodule Mv.Membership.Import.MemberCSVTest do end describe "process_chunk/4" do - test "function exists and accepts chunk_rows_with_lines, column_map, custom_field_map, and opts" do + setup do + system_actor = Mv.Helpers.SystemActor.get_system_actor() + %{actor: system_actor} + end + + test "function exists and accepts chunk_rows_with_lines, column_map, custom_field_map, and opts", + %{ + actor: actor + } do chunk_rows_with_lines = [{2, %{member: %{email: "john@example.com"}, custom: %{}}}] column_map = %{email: 0} custom_field_map = %{} - opts = [] + opts = [actor: actor] # This will fail until the function is implemented result = MemberCSV.process_chunk(chunk_rows_with_lines, column_map, custom_field_map, opts) assert match?({:ok, _}, result) or match?({:error, _}, result) end - test "creates member successfully with valid data" do + test "creates member successfully with valid data", %{actor: actor} do chunk_rows_with_lines = [ {2, %{member: %{email: "john@example.com", first_name: "John"}, custom: %{}}} ] column_map = %{email: 0, first_name: 1} custom_field_map = %{} - opts = [] + opts = [actor: actor] assert {:ok, chunk_result} = MemberCSV.process_chunk(chunk_rows_with_lines, column_map, custom_field_map, opts) @@ -106,14 +114,14 @@ defmodule Mv.Membership.Import.MemberCSVTest do assert Enum.any?(members, &(&1.email == "john@example.com")) end - test "returns error for invalid email" do + test "returns error for invalid email", %{actor: actor} do chunk_rows_with_lines = [ {2, %{member: %{email: "invalid-email"}, custom: %{}}} ] column_map = %{email: 0} custom_field_map = %{} - opts = [] + opts = [actor: actor] assert {:ok, chunk_result} = MemberCSV.process_chunk(chunk_rows_with_lines, column_map, custom_field_map, opts) @@ -130,14 +138,14 @@ defmodule Mv.Membership.Import.MemberCSVTest do assert error.message != "" end - test "returns error for missing email" do + test "returns error for missing email", %{actor: actor} do chunk_rows_with_lines = [ {2, %{member: %{}, custom: %{}}} ] column_map = %{} custom_field_map = %{} - opts = [] + opts = [actor: actor] assert {:ok, chunk_result} = MemberCSV.process_chunk(chunk_rows_with_lines, column_map, custom_field_map, opts) @@ -152,14 +160,14 @@ defmodule Mv.Membership.Import.MemberCSVTest do assert is_binary(error.message) end - test "returns error for whitespace-only email" do + test "returns error for whitespace-only email", %{actor: actor} do chunk_rows_with_lines = [ {3, %{member: %{email: " "}, custom: %{}}} ] column_map = %{email: 0} custom_field_map = %{} - opts = [] + opts = [actor: actor] assert {:ok, chunk_result} = MemberCSV.process_chunk(chunk_rows_with_lines, column_map, custom_field_map, opts) @@ -173,13 +181,11 @@ defmodule Mv.Membership.Import.MemberCSVTest do assert error.field == :email end - test "returns error for duplicate email" do + test "returns error for duplicate email", %{actor: actor} do # Create existing member first - system_actor = Mv.Helpers.SystemActor.get_system_actor() - {:ok, _existing} = Mv.Membership.create_member(%{email: "duplicate@example.com", first_name: "Existing"}, - actor: system_actor + actor: actor ) chunk_rows_with_lines = [ @@ -188,7 +194,7 @@ defmodule Mv.Membership.Import.MemberCSVTest do column_map = %{email: 0, first_name: 1} custom_field_map = %{} - opts = [] + opts = [actor: actor] assert {:ok, chunk_result} = MemberCSV.process_chunk(chunk_rows_with_lines, column_map, custom_field_map, opts) @@ -203,9 +209,7 @@ defmodule Mv.Membership.Import.MemberCSVTest do assert error.message =~ "email" or error.message =~ "duplicate" or error.message =~ "unique" end - test "creates member with custom field values" do - system_actor = Mv.Helpers.SystemActor.get_system_actor() - + test "creates member with custom field values", %{actor: actor} do # Create custom field first {:ok, custom_field} = Mv.Membership.CustomField @@ -213,7 +217,7 @@ defmodule Mv.Membership.Import.MemberCSVTest do name: "Phone", value_type: :string }) - |> Ash.create(actor: system_actor) + |> Ash.create(actor: actor) chunk_rows_with_lines = [ {2, @@ -230,7 +234,7 @@ defmodule Mv.Membership.Import.MemberCSVTest do to_string(custom_field.id) => %{id: custom_field.id, value_type: custom_field.value_type} } - opts = [custom_field_lookup: custom_field_lookup] + opts = [custom_field_lookup: custom_field_lookup, actor: actor] assert {:ok, chunk_result} = MemberCSV.process_chunk(chunk_rows_with_lines, column_map, custom_field_map, opts) @@ -239,8 +243,7 @@ defmodule Mv.Membership.Import.MemberCSVTest do assert chunk_result.failed == 0 # Verify member and custom field value were created - system_actor = Mv.Helpers.SystemActor.get_system_actor() - members = Mv.Membership.list_members!(actor: system_actor) + members = Mv.Membership.list_members!(actor: actor) member = Enum.find(members, &(&1.email == "withcustom@example.com")) assert member != nil @@ -251,7 +254,7 @@ defmodule Mv.Membership.Import.MemberCSVTest do assert cfv.value.value == "123-456-7890" end - test "handles multiple rows with mixed success and failure" do + test "handles multiple rows with mixed success and failure", %{actor: actor} do chunk_rows_with_lines = [ {2, %{member: %{email: "valid1@example.com"}, custom: %{}}}, {3, %{member: %{email: "invalid-email"}, custom: %{}}}, @@ -260,7 +263,7 @@ defmodule Mv.Membership.Import.MemberCSVTest do column_map = %{email: 0} custom_field_map = %{} - opts = [] + opts = [actor: actor] assert {:ok, chunk_result} = MemberCSV.process_chunk(chunk_rows_with_lines, column_map, custom_field_map, opts) @@ -276,7 +279,7 @@ defmodule Mv.Membership.Import.MemberCSVTest do assert is_binary(error.message) end - test "preserves CSV line numbers in errors" do + test "preserves CSV line numbers in errors", %{actor: actor} do chunk_rows_with_lines = [ {5, %{member: %{email: "invalid"}, custom: %{}}}, {10, %{member: %{email: "also-invalid"}, custom: %{}}} @@ -284,7 +287,7 @@ defmodule Mv.Membership.Import.MemberCSVTest do column_map = %{email: 0} custom_field_map = %{} - opts = [] + opts = [actor: actor] assert {:ok, chunk_result} = MemberCSV.process_chunk(chunk_rows_with_lines, column_map, custom_field_map, opts) @@ -297,11 +300,11 @@ defmodule Mv.Membership.Import.MemberCSVTest do assert 10 in line_numbers end - test "returns {:ok, chunk_result} on success" do + test "returns {:ok, chunk_result} on success", %{actor: actor} do chunk_rows_with_lines = [{2, %{member: %{email: "test@example.com"}, custom: %{}}}] column_map = %{email: 0} custom_field_map = %{} - opts = [] + opts = [actor: actor] assert {:ok, chunk_result} = MemberCSV.process_chunk(chunk_rows_with_lines, column_map, custom_field_map, opts) @@ -315,11 +318,11 @@ defmodule Mv.Membership.Import.MemberCSVTest do assert is_list(chunk_result.errors) end - test "returns {:ok, _} with zero counts for empty chunk" do + test "returns {:ok, _} with zero counts for empty chunk", %{actor: actor} do chunk_rows_with_lines = [] column_map = %{} custom_field_map = %{} - opts = [] + opts = [actor: actor] assert {:ok, chunk_result} = MemberCSV.process_chunk(chunk_rows_with_lines, column_map, custom_field_map, opts) @@ -334,7 +337,7 @@ defmodule Mv.Membership.Import.MemberCSVTest do assert function_exported?(MemberCSV, :process_chunk, 4) end - test "error capping collects exactly 50 errors" do + test "error capping collects exactly 50 errors", %{actor: actor} do # Create 50 rows with invalid emails chunk_rows_with_lines = 1..50 @@ -344,7 +347,7 @@ defmodule Mv.Membership.Import.MemberCSVTest do column_map = %{email: 0} custom_field_map = %{} - opts = [existing_error_count: 0, max_errors: 50] + opts = [existing_error_count: 0, max_errors: 50, actor: actor] assert {:ok, chunk_result} = MemberCSV.process_chunk(chunk_rows_with_lines, column_map, custom_field_map, opts) @@ -354,7 +357,9 @@ defmodule Mv.Membership.Import.MemberCSVTest do assert length(chunk_result.errors) == 50 end - test "error capping collects only first 50 errors when more than 50 errors occur" do + test "error capping collects only first 50 errors when more than 50 errors occur", %{ + actor: actor + } do # Create 60 rows with invalid emails chunk_rows_with_lines = 1..60 @@ -364,7 +369,7 @@ defmodule Mv.Membership.Import.MemberCSVTest do column_map = %{email: 0} custom_field_map = %{} - opts = [existing_error_count: 0, max_errors: 50] + opts = [existing_error_count: 0, max_errors: 50, actor: actor] assert {:ok, chunk_result} = MemberCSV.process_chunk(chunk_rows_with_lines, column_map, custom_field_map, opts) @@ -374,7 +379,7 @@ defmodule Mv.Membership.Import.MemberCSVTest do assert length(chunk_result.errors) == 50 end - test "error capping respects existing_error_count" do + test "error capping respects existing_error_count", %{actor: actor} do # Create 30 rows with invalid emails chunk_rows_with_lines = 1..30 @@ -384,7 +389,7 @@ defmodule Mv.Membership.Import.MemberCSVTest do column_map = %{email: 0} custom_field_map = %{} - opts = [existing_error_count: 25, max_errors: 50] + opts = [existing_error_count: 25, max_errors: 50, actor: actor] assert {:ok, chunk_result} = MemberCSV.process_chunk(chunk_rows_with_lines, column_map, custom_field_map, opts) @@ -395,7 +400,7 @@ defmodule Mv.Membership.Import.MemberCSVTest do assert length(chunk_result.errors) == 25 end - test "error capping collects no errors when limit already reached" do + test "error capping collects no errors when limit already reached", %{actor: actor} do # Create 10 rows with invalid emails chunk_rows_with_lines = 1..10 @@ -405,7 +410,7 @@ defmodule Mv.Membership.Import.MemberCSVTest do column_map = %{email: 0} custom_field_map = %{} - opts = [existing_error_count: 50, max_errors: 50] + opts = [existing_error_count: 50, max_errors: 50, actor: actor] assert {:ok, chunk_result} = MemberCSV.process_chunk(chunk_rows_with_lines, column_map, custom_field_map, opts) @@ -415,7 +420,7 @@ defmodule Mv.Membership.Import.MemberCSVTest do assert chunk_result.errors == [] end - test "error capping with mixed success and failure" do + test "error capping with mixed success and failure", %{actor: actor} do # Create 100 rows: 30 valid, 70 invalid valid_rows = 1..30 @@ -433,7 +438,7 @@ defmodule Mv.Membership.Import.MemberCSVTest do column_map = %{email: 0} custom_field_map = %{} - opts = [existing_error_count: 0, max_errors: 50] + opts = [existing_error_count: 0, max_errors: 50, actor: actor] assert {:ok, chunk_result} = MemberCSV.process_chunk(chunk_rows_with_lines, column_map, custom_field_map, opts) @@ -444,7 +449,7 @@ defmodule Mv.Membership.Import.MemberCSVTest do assert length(chunk_result.errors) == 50 end - test "error capping with custom max_errors" do + test "error capping with custom max_errors", %{actor: actor} do # Create 20 rows with invalid emails chunk_rows_with_lines = 1..20 @@ -454,7 +459,7 @@ defmodule Mv.Membership.Import.MemberCSVTest do column_map = %{email: 0} custom_field_map = %{} - opts = [existing_error_count: 0, max_errors: 10] + opts = [existing_error_count: 0, max_errors: 10, actor: actor] assert {:ok, chunk_result} = MemberCSV.process_chunk(chunk_rows_with_lines, column_map, custom_field_map, opts)