defmodule MicrowavepropWeb.ImportLiveTest do use MicrowavepropWeb.ConnCase, async: true import Phoenix.LiveViewTest alias Microwaveprop.Radio.ImportRun alias Microwaveprop.Repo defp insert_run(attrs) do defaults = %{ submitter_email: "importer@example.com", rows: %{"rows" => [], "refinement_ids" => []}, total_rows: 10, processed_rows: 0, imported_count: 0, refined_count: 0, error_count: 0, errors: %{}, status: "pending" } {:ok, run} = %ImportRun{} |> ImportRun.changeset(Map.merge(defaults, attrs)) |> Repo.insert() run end describe "mount" do test "renders the initial state of a pending import", %{conn: conn} do run = insert_run(%{total_rows: 25, submitter_email: "alice@example.com"}) {:ok, _lv, html} = live(conn, ~p"/imports/#{run.id}") assert html =~ "Contact Import" assert html =~ "alice@example.com" assert html =~ "25" assert html =~ ~r/id="import-status-badge"[^>]*>\s*Pending/ assert html =~ ~s(id="import-progress-bar") assert html =~ ~s(id="import-imported-count") assert html =~ ~s(id="import-refined-count") assert html =~ ~s(id="import-error-count") end test "redirects to /submit with a flash when the import is not found", %{conn: conn} do missing_id = Ecto.UUID.generate() assert {:error, {:live_redirect, %{to: "/submit", flash: flash}}} = live(conn, ~p"/imports/#{missing_id}") assert flash["error"] =~ "Import not found" end test "redirects to /submit for an obviously bad id", %{conn: conn} do assert {:error, {:live_redirect, %{to: "/submit"}}} = live(conn, ~p"/imports/not-a-uuid") end end describe "live updates" do test "updates counters when an import_progress message is broadcast", %{conn: conn} do run = insert_run(%{total_rows: 100}) {:ok, lv, _html} = live(conn, ~p"/imports/#{run.id}") updated = %{ run | processed_rows: 50, imported_count: 48, refined_count: 1, error_count: 1, status: "running", errors: %{"7" => ["band is invalid"]} } Phoenix.PubSub.broadcast( Microwaveprop.PubSub, "csv_import:#{run.id}", {:import_progress, run.id, updated} ) html = render(lv) assert html =~ ~r/id="import-imported-count"[^>]*>\s*48/ assert html =~ ~r/id="import-refined-count"[^>]*>\s*1/ assert html =~ ~r/id="import-error-count"[^>]*>\s*1/ assert html =~ ~r/id="import-status-badge"[^>]*>\s*Running/ assert html =~ "band is invalid" end test "shows the complete UI once status flips to complete", %{conn: conn} do run = insert_run(%{total_rows: 3}) {:ok, lv, _html} = live(conn, ~p"/imports/#{run.id}") done = %{ run | processed_rows: 3, imported_count: 3, status: "complete", completed_at: DateTime.utc_now() } Phoenix.PubSub.broadcast( Microwaveprop.PubSub, "csv_import:#{run.id}", {:import_progress, run.id, done} ) html = render(lv) assert html =~ "Import complete" assert html =~ ~s(id="import-complete-panel") assert html =~ "View contacts" assert html =~ ~r/id="import-status-badge"[^>]*>\s*Complete/ end test "shows the errors section when error_count > 0", %{conn: conn} do run = insert_run(%{ total_rows: 2, processed_rows: 2, imported_count: 1, error_count: 1, status: "complete", errors: %{"2" => ["band is invalid"]} }) {:ok, _lv, html} = live(conn, ~p"/imports/#{run.id}") assert html =~ ~s(id="import-errors-section") assert html =~ "Row 2" assert html =~ "band is invalid" end end end