mitgliederverwaltung/test/mv_web/controllers/import_template_controller_test.exs

104 lines
3.5 KiB
Elixir

defmodule MvWeb.ImportTemplateControllerTest do
use MvWeb.ConnCase, async: true
setup %{conn: conn} do
actor = Mv.Helpers.SystemActor.get_system_actor()
{:ok, custom_field} =
Mv.Membership.CustomField
|> Ash.Changeset.for_create(:create, %{name: "Lieblingsfarbe", value_type: :string})
|> Ash.create(actor: actor)
%{conn: conn, custom_field: custom_field}
end
describe "authenticated EN template" do
setup %{conn: conn} do
admin = Mv.Fixtures.user_with_role_fixture("admin")
%{conn: MvWeb.ConnCase.conn_with_password_user(conn, admin)}
end
test "returns CSV with English headers and current custom fields", %{conn: conn} do
conn = get(conn, ~p"/admin/import/template/en")
assert response_content_type(conn, :csv) =~ "text/csv"
body = response(conn, 200)
header = body |> String.split("\n") |> List.first()
assert header =~ "email"
# EN headers use the canonical English variant from HeaderMapper, not the
# underscore form, so the template stays faithful to the documented variant list.
assert header =~ "first name"
assert header =~ "last name"
refute header =~ "first_name"
assert header =~ "house number"
refute header =~ "house_number"
assert header =~ "Lieblingsfarbe"
assert get_resp_header(conn, "content-disposition")
|> Enum.any?(&(&1 =~ "member_import_en.csv"))
end
test "neutralizes formula-injection in a custom field header", %{conn: conn} do
actor = Mv.Helpers.SystemActor.get_system_actor()
{:ok, _} =
Mv.Membership.CustomField
|> Ash.Changeset.for_create(:create, %{
name: "=cmd|'/c calc'!A1",
value_type: :string
})
|> Ash.create(actor: actor)
conn = get(conn, ~p"/admin/import/template/en")
body = response(conn, 200)
header = body |> String.split("\n") |> List.first()
# The dangerous cell must be prefixed with a single quote so spreadsheet
# software does not evaluate it as a formula, matching the export writer.
refute header =~ ~r/(^|;)=cmd/
assert header =~ "'=cmd|'/c calc'!A1"
end
end
describe "authenticated DE template" do
setup %{conn: conn} do
admin = Mv.Fixtures.user_with_role_fixture("admin")
%{conn: MvWeb.ConnCase.conn_with_password_user(conn, admin)}
end
test "returns CSV with German headers and current custom fields", %{conn: conn} do
conn = get(conn, ~p"/admin/import/template/de")
body = response(conn, 200)
header = body |> String.split("\n") |> List.first()
assert header =~ "E-Mail"
assert header =~ "Vorname"
assert header =~ "Lieblingsfarbe"
assert get_resp_header(conn, "content-disposition")
|> Enum.any?(&(&1 =~ "member_import_de.csv"))
end
end
describe "authorization" do
@tag role: :unauthenticated
test "unauthenticated request does not receive a CSV", %{conn: conn} do
conn = get(conn, ~p"/admin/import/template/en")
refute conn.status == 200
refute get_resp_header(conn, "content-type") |> Enum.any?(&(&1 =~ "text/csv"))
refute to_string(conn.resp_body) =~ "email"
end
@tag role: :member
test "user without import permission is forbidden", %{conn: conn} do
conn = get(conn, ~p"/admin/import/template/en")
refute conn.status == 200
refute get_resp_header(conn, "content-type") |> Enum.any?(&(&1 =~ "text/csv"))
refute to_string(conn.resp_body) =~ "email"
end
end
end