mitgliederverwaltung/test/mv_web/member_live/index_payment_wiring_test.exs
Simon c547ca19af feat(overview): replace filter panel with add-filter builder and aging column
Swaps the unbounded vertical filter panel for a Polaris-style add-filter
builder (searchable grouped field picker, type-aware value control, applied
chips) and colour-codes the fees column with each member's period-scoped
unpaid-cycle count.
2026-07-10 16:27:15 +02:00

72 lines
2.7 KiB
Elixir

defmodule MvWeb.MemberLive.IndexPaymentWiringTest do
@moduledoc """
§1.16 / §1.17 — the member overview LiveView honours the period-scoped
payment-count filter and payment-period URL contract (`pay_filter`,
`pay_from`, `pay_to`), driving the same DB result set the OverviewQuery unit
tests pin, but through `handle_params` and the query wiring.
"""
use MvWeb.ConnCase, async: false
import Phoenix.LiveViewTest
import Mv.Fixtures, only: [create_fee_type: 2, member_fixture_with_actor: 2, create_cycle: 4]
setup %{conn: conn} do
actor = Mv.Helpers.SystemActor.get_system_actor()
ft = create_fee_type(%{interval: :monthly}, actor)
# Deterministic id set: drop the seeded members.
Mv.Membership.Member
|> Ash.read!(actor: actor)
|> Enum.each(&Ash.destroy!(&1, actor: actor))
%{conn: conn_with_oidc_user(conn), actor: actor, ft: ft}
end
defp member_with_unpaid(n, actor, ft) do
member = member_fixture_with_actor(%{}, actor)
Enum.each(1..max(n, 0)//1, fn i ->
create_cycle(member, ft, %{cycle_start: Date.new!(2024, i, 1), status: :unpaid}, actor)
end)
member
end
test "has-unpaid >= 2 shows only members with at least two in-period unpaid cycles", ctx do
one = member_with_unpaid(1, ctx.actor, ctx.ft)
two = member_with_unpaid(2, ctx.actor, ctx.ft)
{:ok, view, _html} =
live(ctx.conn, "/members?pay_filter=unpaid_2&pay_from=2024-01-01&pay_to=2024-12-31")
assert has_element?(view, "#row-#{two.id}")
refute has_element?(view, "#row-#{one.id}")
end
test "fully_paid shows only members with zero in-period unpaid cycles", ctx do
paid = member_with_unpaid(0, ctx.actor, ctx.ft)
create_cycle(paid, ctx.ft, %{cycle_start: ~D[2024-05-01], status: :paid}, ctx.actor)
unpaid = member_with_unpaid(1, ctx.actor, ctx.ft)
{:ok, view, _html} =
live(ctx.conn, "/members?pay_filter=fully_paid&pay_from=2024-01-01&pay_to=2024-12-31")
assert has_element?(view, "#row-#{paid.id}")
refute has_element?(view, "#row-#{unpaid.id}")
end
test "the active period scopes the filter: a cycle outside the period does not count", ctx do
# One unpaid cycle in 2023, none in 2024. With a 2024 period, has-unpaid>=1
# must not select this member; with the all-outstanding default it must.
member = member_fixture_with_actor(%{}, ctx.actor)
create_cycle(member, ctx.ft, %{cycle_start: ~D[2023-03-01], status: :unpaid}, ctx.actor)
{:ok, scoped, _} =
live(ctx.conn, "/members?pay_filter=unpaid_1&pay_from=2024-01-01&pay_to=2024-12-31")
refute has_element?(scoped, "#row-#{member.id}")
{:ok, all_time, _} = live(ctx.conn, "/members?pay_filter=unpaid_1")
assert has_element?(all_time, "#row-#{member.id}")
end
end