110 lines
3.4 KiB
Elixir
110 lines
3.4 KiB
Elixir
defmodule Mv.Membership.Import.ImportRunnerTest do
|
|
use ExUnit.Case, async: true
|
|
|
|
alias Mv.Membership.Import.ImportRunner
|
|
|
|
describe "carry_groups_forward/2" do
|
|
test "replaces import_state groups_found with the chunk's grown snapshot" do
|
|
import_state = %{groups_found: [%{id: "1", name: "A"}]}
|
|
chunk_result = %{groups_found: [%{id: "1", name: "A"}, %{id: "2", name: "B"}]}
|
|
|
|
assert ImportRunner.carry_groups_forward(import_state, chunk_result) == %{
|
|
groups_found: [%{id: "1", name: "A"}, %{id: "2", name: "B"}]
|
|
}
|
|
end
|
|
|
|
test "leaves import_state unchanged when the chunk result omits groups_found" do
|
|
import_state = %{groups_found: [%{id: "1", name: "A"}], other: :kept}
|
|
chunk_result = %{inserted: 1}
|
|
|
|
assert ImportRunner.carry_groups_forward(import_state, chunk_result) == import_state
|
|
end
|
|
end
|
|
|
|
describe "merge_progress/4 warning accumulation" do
|
|
test "deduplicates identical warnings across chunks instead of growing unbounded" do
|
|
progress = %{
|
|
inserted: 0,
|
|
failed: 0,
|
|
errors: [],
|
|
warnings: ["Fee type 'Ghost' not found; using the default fee type."],
|
|
status: :running,
|
|
current_chunk: 0,
|
|
total_chunks: 3
|
|
}
|
|
|
|
chunk_result = %{
|
|
inserted: 2,
|
|
failed: 0,
|
|
errors: [],
|
|
errors_truncated?: false,
|
|
warnings: [
|
|
"Fee type 'Ghost' not found; using the default fee type.",
|
|
"Fee type 'Ghost' not found; using the default fee type."
|
|
]
|
|
}
|
|
|
|
result = ImportRunner.merge_progress(progress, chunk_result, 0)
|
|
|
|
assert result.warnings == ["Fee type 'Ghost' not found; using the default fee type."]
|
|
end
|
|
|
|
test "preserves distinct warnings while collapsing duplicates" do
|
|
progress = %{
|
|
inserted: 0,
|
|
failed: 0,
|
|
errors: [],
|
|
warnings: ["Fee type 'A' not found; using the default fee type."],
|
|
status: :running,
|
|
current_chunk: 0,
|
|
total_chunks: 2
|
|
}
|
|
|
|
chunk_result = %{
|
|
inserted: 1,
|
|
failed: 0,
|
|
errors: [],
|
|
errors_truncated?: false,
|
|
warnings: [
|
|
"Fee type 'A' not found; using the default fee type.",
|
|
"Fee type 'B' not found; using the default fee type."
|
|
]
|
|
}
|
|
|
|
result = ImportRunner.merge_progress(progress, chunk_result, 0)
|
|
|
|
assert result.warnings == [
|
|
"Fee type 'A' not found; using the default fee type.",
|
|
"Fee type 'B' not found; using the default fee type."
|
|
]
|
|
end
|
|
end
|
|
|
|
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
|