From c41d24113feb8c653fa165eff687000b38a14d06 Mon Sep 17 00:00:00 2001 From: Moritz Date: Tue, 2 Jun 2026 12:00:38 +0200 Subject: [PATCH] fix(import): return readable string for unreadable upload errors File.read/1 only yields posix atoms, so the File.Error and bare-reason branches were unreachable, and :file.format_error/1 returns a charlist rather than a String. Normalize the error to a binary so it interpolates correctly in flash messages. --- lib/mv/membership/import/import_runner.ex | 8 +---- .../membership/import/import_runner_test.exs | 33 +++++++++++++++++++ 2 files changed, 34 insertions(+), 7 deletions(-) create mode 100644 test/mv/membership/import/import_runner_test.exs diff --git a/lib/mv/membership/import/import_runner.ex b/lib/mv/membership/import/import_runner.ex index eccd75f..5f953d4 100644 --- a/lib/mv/membership/import/import_runner.ex +++ b/lib/mv/membership/import/import_runner.ex @@ -26,14 +26,8 @@ defmodule Mv.Membership.Import.ImportRunner do {:ok, content} -> {:ok, content} - {:error, reason} when is_atom(reason) -> - {:error, :file.format_error(reason)} - - {:error, %File.Error{reason: reason}} -> - {:error, :file.format_error(reason)} - {:error, reason} -> - {:error, Exception.message(reason)} + {:error, to_string(:file.format_error(reason))} end end diff --git a/test/mv/membership/import/import_runner_test.exs b/test/mv/membership/import/import_runner_test.exs new file mode 100644 index 0000000..88d189e --- /dev/null +++ b/test/mv/membership/import/import_runner_test.exs @@ -0,0 +1,33 @@ +defmodule Mv.Membership.Import.ImportRunnerTest do + use ExUnit.Case, async: true + + alias Mv.Membership.Import.ImportRunner + + describe "read_file_entry/2" do + test "returns {:ok, content} for a readable file" do + path = + Path.join( + System.tmp_dir!(), + "import_runner_read_#{System.unique_integer([:positive])}.csv" + ) + + File.write!(path, "email;first_name\njohn@example.com;John") + on_exit(fn -> File.rm_rf(path) end) + + assert {:ok, "email;first_name\njohn@example.com;John"} = + ImportRunner.read_file_entry(%{path: path}, %{}) + end + + test "returns {:error, message} with a binary message when the file cannot be read" do + missing_path = + Path.join( + System.tmp_dir!(), + "import_runner_missing_#{System.unique_integer([:positive])}.csv" + ) + + assert {:error, message} = ImportRunner.read_file_entry(%{path: missing_path}, %{}) + assert is_binary(message) + assert message != "" + end + end +end