Add tests to verify that copy and open-email buttons are disabled when no members are selected and enabled after selection. Also verify that the counter shows the correct count.
676 lines
22 KiB
Elixir
676 lines
22 KiB
Elixir
defmodule MvWeb.MemberLive.IndexTest do
|
||
use MvWeb.ConnCase, async: true
|
||
import Phoenix.LiveViewTest
|
||
require Ash.Query
|
||
|
||
test "shows translated title in German", %{conn: conn} do
|
||
conn = conn_with_oidc_user(conn)
|
||
conn = Plug.Test.init_test_session(conn, locale: "de")
|
||
{:ok, _view, html} = live(conn, "/members")
|
||
# Expected German title
|
||
assert html =~ "Mitglieder"
|
||
end
|
||
|
||
test "shows translated title in English", %{conn: conn} do
|
||
conn = conn_with_oidc_user(conn)
|
||
Gettext.put_locale(MvWeb.Gettext, "en")
|
||
{:ok, _view, html} = live(conn, "/members")
|
||
# Expected English title
|
||
assert html =~ "Members"
|
||
end
|
||
|
||
test "shows translated button text in German", %{conn: conn} do
|
||
conn = conn_with_oidc_user(conn)
|
||
conn = Plug.Test.init_test_session(conn, locale: "de")
|
||
{:ok, _view, html} = live(conn, "/members/new")
|
||
assert html =~ "Speichern"
|
||
end
|
||
|
||
test "shows translated button text in English", %{conn: conn} do
|
||
conn = conn_with_oidc_user(conn)
|
||
Gettext.put_locale(MvWeb.Gettext, "en")
|
||
{:ok, _view, html} = live(conn, "/members/new")
|
||
assert html =~ "Save"
|
||
end
|
||
|
||
test "shows translated flash message after creating a member in German", %{conn: conn} do
|
||
conn = conn_with_oidc_user(conn)
|
||
conn = Plug.Test.init_test_session(conn, locale: "de")
|
||
{:ok, form_view, _html} = live(conn, "/members/new")
|
||
|
||
form_data = %{
|
||
"member[first_name]" => "Max",
|
||
"member[last_name]" => "Mustermann",
|
||
"member[email]" => "max@example.com"
|
||
}
|
||
|
||
# Submit form and follow the redirect to get the flash message
|
||
{:ok, index_view, _html} =
|
||
form_view
|
||
|> form("#member-form", form_data)
|
||
|> render_submit()
|
||
|> follow_redirect(conn, "/members")
|
||
|
||
assert has_element?(index_view, "#flash-group", "Mitglied wurde erfolgreich erstellt")
|
||
end
|
||
|
||
test "shows translated flash message after creating a member in English", %{conn: conn} do
|
||
conn = conn_with_oidc_user(conn)
|
||
{:ok, form_view, _html} = live(conn, "/members/new")
|
||
|
||
form_data = %{
|
||
"member[first_name]" => "Max",
|
||
"member[last_name]" => "Mustermann",
|
||
"member[email]" => "max@example.com"
|
||
}
|
||
|
||
# Submit form and follow the redirect to get the flash message
|
||
{:ok, index_view, _html} =
|
||
form_view
|
||
|> form("#member-form", form_data)
|
||
|> render_submit()
|
||
|> follow_redirect(conn, "/members")
|
||
|
||
assert has_element?(index_view, "#flash-group", "Member created successfully")
|
||
end
|
||
|
||
describe "sorting integration" do
|
||
test "clicking a column header toggles sort order and updates the URL", %{conn: conn} do
|
||
conn = conn_with_oidc_user(conn)
|
||
{:ok, view, _html} = live(conn, "/members")
|
||
|
||
# The component data test ids are built with the name of the field
|
||
# First click – should sort ASC
|
||
view
|
||
|> element("[data-testid='email']")
|
||
|> render_click()
|
||
|
||
# The LiveView pushes a patch with the new query params
|
||
assert_patch(view, "/members?query=&sort_field=email&sort_order=asc")
|
||
|
||
# Second click – toggles to DESC
|
||
view
|
||
|> element("[data-testid='email']")
|
||
|> render_click()
|
||
|
||
assert_patch(view, "/members?query=&sort_field=email&sort_order=desc")
|
||
end
|
||
|
||
test "clicking different column header resets order to ascending", %{conn: conn} do
|
||
conn = conn_with_oidc_user(conn)
|
||
{:ok, view, _html} = live(conn, "/members?sort_field=email&sort_order=desc")
|
||
|
||
# Click on a different column
|
||
view
|
||
|> element("[data-testid='first_name']")
|
||
|> render_click()
|
||
|
||
assert_patch(view, "/members?query=&sort_field=first_name&sort_order=asc")
|
||
end
|
||
|
||
test "all sortable columns work correctly", %{conn: conn} do
|
||
conn = conn_with_oidc_user(conn)
|
||
{:ok, view, _html} = live(conn, "/members")
|
||
|
||
# default ascending sorting with first name
|
||
assert has_element?(view, "[data-testid='first_name'][aria-label='ascending']")
|
||
|
||
sortable_fields = [
|
||
:email,
|
||
:street,
|
||
:house_number,
|
||
:postal_code,
|
||
:city,
|
||
:phone_number,
|
||
:join_date
|
||
]
|
||
|
||
for field <- sortable_fields do
|
||
view
|
||
|> element("[data-testid='#{field}']")
|
||
|> render_click()
|
||
|
||
assert_patch(view, "/members?query=&sort_field=#{field}&sort_order=asc")
|
||
end
|
||
end
|
||
|
||
test "sorting works with search query", %{conn: conn} do
|
||
conn = conn_with_oidc_user(conn)
|
||
{:ok, view, _html} = live(conn, "/members?query=test")
|
||
|
||
view
|
||
|> element("[data-testid='email']")
|
||
|> render_click()
|
||
|
||
assert_patch(view, "/members?query=test&sort_field=email&sort_order=asc")
|
||
end
|
||
|
||
test "sorting maintains search query when toggling order", %{conn: conn} do
|
||
conn = conn_with_oidc_user(conn)
|
||
{:ok, view, _html} = live(conn, "/members?query=test&sort_field=email&sort_order=asc")
|
||
|
||
view
|
||
|> element("[data-testid='email']")
|
||
|> render_click()
|
||
|
||
assert_patch(view, "/members?query=test&sort_field=email&sort_order=desc")
|
||
end
|
||
end
|
||
|
||
describe "URL param handling" do
|
||
test "handle_params reads sort query and applies it", %{conn: conn} do
|
||
conn = conn_with_oidc_user(conn)
|
||
{:ok, view, _html} = live(conn, "/members?query=&sort_field=email&sort_order=desc")
|
||
|
||
# Check that the sort state is correctly applied
|
||
assert has_element?(view, "[data-testid='email'][aria-label='descending']")
|
||
end
|
||
|
||
test "handle_params handles invalid sort field gracefully", %{conn: conn} do
|
||
conn = conn_with_oidc_user(conn)
|
||
{:ok, view, _html} = live(conn, "/members?query=&sort_field=invalid_field&sort_order=asc")
|
||
|
||
# Should not crash and should show default first name order
|
||
assert has_element?(view, "[data-testid='first_name'][aria-label='ascending']")
|
||
end
|
||
|
||
test "handle_params preserves search query with sort params", %{conn: conn} do
|
||
conn = conn_with_oidc_user(conn)
|
||
{:ok, view, _html} = live(conn, "/members?query=test&sort_field=email&sort_order=desc")
|
||
|
||
# Both search and sort should be preserved
|
||
assert has_element?(view, "[data-testid='email'][aria-label='descending']")
|
||
end
|
||
end
|
||
|
||
describe "search and sort integration" do
|
||
test "search maintains sort state", %{conn: conn} do
|
||
conn = conn_with_oidc_user(conn)
|
||
{:ok, view, _html} = live(conn, "/members?query=&sort_field=email&sort_order=desc")
|
||
|
||
# Perform search
|
||
view
|
||
|> element("[data-testid='search-input']")
|
||
|> render_change(%{value: "test"})
|
||
|
||
# Sort state should be maintained
|
||
assert has_element?(view, "[data-testid='email'][aria-label='descending']")
|
||
end
|
||
|
||
test "sort maintains search state", %{conn: conn} do
|
||
conn = conn_with_oidc_user(conn)
|
||
{:ok, view, _html} = live(conn, "/members?query=test&sort_field=email&sort_order=asc")
|
||
|
||
# Perform sort
|
||
view
|
||
|> element("[data-testid='email']")
|
||
|> render_click()
|
||
|
||
# Search state should be maintained
|
||
assert_patch(view, "/members?query=test&sort_field=email&sort_order=desc")
|
||
end
|
||
end
|
||
|
||
test "handle_info(:search_changed) updates assigns with search results", %{conn: conn} do
|
||
conn = conn_with_oidc_user(conn)
|
||
{:ok, view, _html} = live(conn, "/members")
|
||
|
||
send(view.pid, {:search_changed, "Friedrich"})
|
||
|
||
state = :sys.get_state(view.pid)
|
||
|
||
assert state.socket.assigns.query == "Friedrich"
|
||
assert is_list(state.socket.assigns.members)
|
||
end
|
||
|
||
test "can delete a member without error", %{conn: conn} do
|
||
# Create a test member first
|
||
{:ok, member} =
|
||
Mv.Membership.create_member(%{
|
||
first_name: "Test",
|
||
last_name: "User",
|
||
email: "test@example.com"
|
||
})
|
||
|
||
conn = conn_with_oidc_user(conn)
|
||
{:ok, index_view, _html} = live(conn, "/members")
|
||
|
||
# Verify the member is displayed
|
||
assert has_element?(index_view, "#members", "Test User")
|
||
|
||
# Click the delete link for this member
|
||
index_view
|
||
|> element("a", "Delete")
|
||
|> render_click()
|
||
|
||
# Verify the member is no longer displayed
|
||
refute has_element?(index_view, "#members", "Test User")
|
||
|
||
# Verify the member was actually deleted from the database
|
||
assert not (Mv.Membership.Member |> Ash.Query.filter(id == ^member.id) |> Ash.exists?())
|
||
end
|
||
|
||
describe "copy_emails feature" do
|
||
setup do
|
||
# Create test members
|
||
{:ok, member1} =
|
||
Mv.Membership.create_member(%{
|
||
first_name: "Max",
|
||
last_name: "Mustermann",
|
||
email: "max@example.com"
|
||
})
|
||
|
||
{:ok, member2} =
|
||
Mv.Membership.create_member(%{
|
||
first_name: "Erika",
|
||
last_name: "Musterfrau",
|
||
email: "erika@example.com"
|
||
})
|
||
|
||
{:ok, member3} =
|
||
Mv.Membership.create_member(%{
|
||
first_name: "Hans",
|
||
last_name: "Müller-Lüdenscheidt",
|
||
email: "hans@example.com"
|
||
})
|
||
|
||
%{member1: member1, member2: member2, member3: member3}
|
||
end
|
||
|
||
test "copy_emails event formats selected members correctly", %{
|
||
conn: conn,
|
||
member1: member1,
|
||
member2: member2
|
||
} do
|
||
conn = conn_with_oidc_user(conn)
|
||
{:ok, view, _html} = live(conn, "/members")
|
||
|
||
# Select two members by sending the select_member event directly
|
||
render_click(view, "select_member", %{"id" => member1.id})
|
||
render_click(view, "select_member", %{"id" => member2.id})
|
||
|
||
# Trigger copy_emails event
|
||
view |> element("#copy-emails-btn") |> render_click()
|
||
|
||
# Verify flash message shows correct count
|
||
assert render(view) =~ "2"
|
||
end
|
||
|
||
test "copy_emails event with no selection shows error flash", %{conn: conn} do
|
||
conn = conn_with_oidc_user(conn)
|
||
{:ok, view, _html} = live(conn, "/members")
|
||
|
||
# Trigger copy_emails event directly (button not visible when no selection)
|
||
# This tests the edge case where event is triggered without selection
|
||
result = render_hook(view, "copy_emails", %{})
|
||
|
||
# Should show error flash
|
||
assert result =~ "No members selected" or result =~ "Keine Mitglieder"
|
||
end
|
||
|
||
test "copy_emails event with all members selected formats all emails", %{
|
||
conn: conn
|
||
} do
|
||
conn = conn_with_oidc_user(conn)
|
||
{:ok, view, _html} = live(conn, "/members")
|
||
|
||
# Select all members via select_all
|
||
view |> element("[phx-click='select_all']") |> render_click()
|
||
|
||
# Trigger copy_emails event
|
||
view |> element("#copy-emails-btn") |> render_click()
|
||
|
||
# Verify flash message shows correct count (3 members)
|
||
assert render(view) =~ "3"
|
||
end
|
||
|
||
test "copy_emails handles members with special characters in names", %{
|
||
conn: conn,
|
||
member3: member3
|
||
} do
|
||
conn = conn_with_oidc_user(conn)
|
||
{:ok, view, _html} = live(conn, "/members")
|
||
|
||
# Select member with umlauts by sending the select_member event directly
|
||
render_click(view, "select_member", %{"id" => member3.id})
|
||
|
||
# Trigger copy_emails event - should not crash
|
||
view |> element("#copy-emails-btn") |> render_click()
|
||
|
||
# Verify flash message shows success
|
||
assert render(view) =~ "1"
|
||
end
|
||
|
||
test "copy_emails handles case where selected member is deleted before copy", %{
|
||
conn: conn,
|
||
member1: member1
|
||
} do
|
||
conn = conn_with_oidc_user(conn)
|
||
{:ok, view, _html} = live(conn, "/members")
|
||
|
||
# Select a member by sending the select_member event directly
|
||
render_click(view, "select_member", %{"id" => member1.id})
|
||
|
||
# Delete the member from the database
|
||
Ash.destroy!(member1)
|
||
|
||
# Trigger copy_emails event directly - selection still contains the deleted ID
|
||
# but the member is no longer in @members list after reload
|
||
result = render_hook(view, "copy_emails", %{})
|
||
|
||
# Should show error since no visible members match selection
|
||
assert result =~ "No email" or result =~ "Keine E-Mail" or result =~ "0"
|
||
end
|
||
|
||
test "copy_emails formats emails as RFC 5322 compliant comma-separated list", %{
|
||
conn: conn,
|
||
member1: member1,
|
||
member2: member2
|
||
} do
|
||
conn = conn_with_oidc_user(conn)
|
||
{:ok, view, _html} = live(conn, "/members")
|
||
|
||
# Select two members by sending the select_member event directly
|
||
render_click(view, "select_member", %{"id" => member1.id})
|
||
render_click(view, "select_member", %{"id" => member2.id})
|
||
|
||
# Get the socket state to verify the formatted email string
|
||
state = :sys.get_state(view.pid)
|
||
selected_members = state.socket.assigns.selected_members
|
||
|
||
# Verify MapSet is used
|
||
assert %MapSet{} = selected_members
|
||
assert MapSet.size(selected_members) == 2
|
||
end
|
||
|
||
test "email format is 'First Last <email>' with comma separator", %{
|
||
conn: conn,
|
||
member1: _member1
|
||
} do
|
||
# Test the format_member_email function indirectly
|
||
# by checking the push_event payload structure
|
||
conn = conn_with_oidc_user(conn)
|
||
|
||
# Create a member with known data
|
||
{:ok, test_member} =
|
||
Mv.Membership.create_member(%{
|
||
first_name: "Test",
|
||
last_name: "Format",
|
||
email: "test.format@example.com"
|
||
})
|
||
|
||
{:ok, view, _html} = live(conn, "/members")
|
||
|
||
# Select the test member by sending the select_member event directly
|
||
render_click(view, "select_member", %{"id" => test_member.id})
|
||
|
||
# The format should be "Test Format <test.format@example.com>"
|
||
# We verify this by checking the flash shows 1 email was copied
|
||
view |> element("#copy-emails-btn") |> render_click()
|
||
assert render(view) =~ "1"
|
||
end
|
||
|
||
test "copy button is disabled when no members selected", %{conn: conn} do
|
||
conn = conn_with_oidc_user(conn)
|
||
{:ok, view, _html} = live(conn, "/members")
|
||
|
||
# Copy button should be disabled (button element)
|
||
assert has_element?(view, "#copy-emails-btn[disabled]")
|
||
# Open email button should be disabled (link with tabindex and aria-disabled)
|
||
assert has_element?(view, "#open-email-btn[tabindex='-1'][aria-disabled='true']")
|
||
end
|
||
|
||
test "copy button is enabled after selection", %{
|
||
conn: conn,
|
||
member1: member1
|
||
} do
|
||
conn = conn_with_oidc_user(conn)
|
||
{:ok, view, _html} = live(conn, "/members")
|
||
|
||
# Select a member by sending the select_member event directly
|
||
render_click(view, "select_member", %{"id" => member1.id})
|
||
|
||
# Copy button should now be enabled (no disabled attribute)
|
||
refute has_element?(view, "#copy-emails-btn[disabled]")
|
||
# Open email button should now be enabled (no tabindex=-1 or aria-disabled)
|
||
refute has_element?(view, "#open-email-btn[tabindex='-1']")
|
||
refute has_element?(view, "#open-email-btn[aria-disabled='true']")
|
||
# Counter should show correct count
|
||
assert render(view) =~ "1"
|
||
end
|
||
|
||
test "copy button click triggers event and shows flash", %{
|
||
conn: conn,
|
||
member1: member1
|
||
} do
|
||
conn = conn_with_oidc_user(conn)
|
||
{:ok, view, _html} = live(conn, "/members")
|
||
|
||
# Select a member by sending the select_member event directly
|
||
render_click(view, "select_member", %{"id" => member1.id})
|
||
|
||
# Click copy button
|
||
view |> element("#copy-emails-btn") |> render_click()
|
||
|
||
# Flash message should appear
|
||
assert has_element?(view, "#flash-group")
|
||
end
|
||
end
|
||
|
||
describe "payment filter integration" do
|
||
setup do
|
||
# Create members with different payment status
|
||
# Use unique names that won't appear elsewhere in the HTML
|
||
{:ok, paid_member} =
|
||
Mv.Membership.create_member(%{
|
||
first_name: "Zahler",
|
||
last_name: "Mitglied",
|
||
email: "zahler@example.com",
|
||
paid: true
|
||
})
|
||
|
||
{:ok, unpaid_member} =
|
||
Mv.Membership.create_member(%{
|
||
first_name: "Nichtzahler",
|
||
last_name: "Mitglied",
|
||
email: "nichtzahler@example.com",
|
||
paid: false
|
||
})
|
||
|
||
{:ok, nil_paid_member} =
|
||
Mv.Membership.create_member(%{
|
||
first_name: "Unbestimmt",
|
||
last_name: "Mitglied",
|
||
email: "unbestimmt@example.com"
|
||
# paid is nil by default
|
||
})
|
||
|
||
%{paid_member: paid_member, unpaid_member: unpaid_member, nil_paid_member: nil_paid_member}
|
||
end
|
||
|
||
test "filter shows all members when no filter is active", %{
|
||
conn: conn,
|
||
paid_member: paid_member,
|
||
unpaid_member: unpaid_member,
|
||
nil_paid_member: nil_paid_member
|
||
} do
|
||
conn = conn_with_oidc_user(conn)
|
||
{:ok, _view, html} = live(conn, "/members")
|
||
|
||
assert html =~ paid_member.first_name
|
||
assert html =~ unpaid_member.first_name
|
||
assert html =~ nil_paid_member.first_name
|
||
end
|
||
|
||
test "filter shows only paid members when paid filter is active", %{
|
||
conn: conn,
|
||
paid_member: paid_member,
|
||
unpaid_member: unpaid_member,
|
||
nil_paid_member: nil_paid_member
|
||
} do
|
||
conn = conn_with_oidc_user(conn)
|
||
{:ok, _view, html} = live(conn, "/members?paid_filter=paid")
|
||
|
||
assert html =~ paid_member.first_name
|
||
refute html =~ unpaid_member.first_name
|
||
refute html =~ nil_paid_member.first_name
|
||
end
|
||
|
||
test "filter shows only unpaid members (including nil) when not_paid filter is active", %{
|
||
conn: conn,
|
||
paid_member: paid_member,
|
||
unpaid_member: unpaid_member,
|
||
nil_paid_member: nil_paid_member
|
||
} do
|
||
conn = conn_with_oidc_user(conn)
|
||
{:ok, _view, html} = live(conn, "/members?paid_filter=not_paid")
|
||
|
||
refute html =~ paid_member.first_name
|
||
assert html =~ unpaid_member.first_name
|
||
assert html =~ nil_paid_member.first_name
|
||
end
|
||
|
||
test "filter combines with search query (AND)", %{
|
||
conn: conn,
|
||
paid_member: paid_member
|
||
} do
|
||
conn = conn_with_oidc_user(conn)
|
||
{:ok, _view, html} = live(conn, "/members?query=Zahler&paid_filter=paid")
|
||
|
||
assert html =~ paid_member.first_name
|
||
end
|
||
|
||
test "filter combines with sorting", %{conn: conn} do
|
||
conn = conn_with_oidc_user(conn)
|
||
|
||
{:ok, view, _html} =
|
||
live(conn, "/members?paid_filter=paid&sort_field=first_name&sort_order=asc")
|
||
|
||
# Click on email sort header
|
||
view
|
||
|> element("[data-testid='email']")
|
||
|> render_click()
|
||
|
||
# Filter should be preserved in URL
|
||
path = assert_patch(view)
|
||
assert path =~ "paid_filter=paid"
|
||
assert path =~ "sort_field=email"
|
||
end
|
||
|
||
test "URL parameter paid_filter is set when selecting filter", %{conn: conn} do
|
||
conn = conn_with_oidc_user(conn)
|
||
{:ok, view, _html} = live(conn, "/members")
|
||
|
||
# Open filter dropdown
|
||
view
|
||
|> element("#payment-filter button[aria-haspopup='true']")
|
||
|> render_click()
|
||
|
||
# Select "Paid" option
|
||
view
|
||
|> element("#payment-filter button[phx-value-filter='paid']")
|
||
|> render_click()
|
||
|
||
path = assert_patch(view)
|
||
assert path =~ "paid_filter=paid"
|
||
end
|
||
|
||
test "URL parameter is correctly read on page load", %{
|
||
conn: conn,
|
||
paid_member: paid_member
|
||
} do
|
||
conn = conn_with_oidc_user(conn)
|
||
{:ok, _view, html} = live(conn, "/members?paid_filter=paid")
|
||
|
||
# Only paid member should be visible
|
||
assert html =~ paid_member.first_name
|
||
# Filter badge should be visible
|
||
assert html =~ "badge"
|
||
end
|
||
|
||
test "invalid URL parameter is ignored", %{
|
||
conn: conn,
|
||
paid_member: paid_member,
|
||
unpaid_member: unpaid_member
|
||
} do
|
||
conn = conn_with_oidc_user(conn)
|
||
{:ok, _view, html} = live(conn, "/members?paid_filter=invalid_value")
|
||
|
||
# All members should be visible (filter not applied)
|
||
assert html =~ paid_member.first_name
|
||
assert html =~ unpaid_member.first_name
|
||
end
|
||
|
||
test "search maintains filter state", %{conn: conn} do
|
||
conn = conn_with_oidc_user(conn)
|
||
{:ok, view, _html} = live(conn, "/members?paid_filter=paid")
|
||
|
||
# Perform search
|
||
view
|
||
|> element("[data-testid='search-input']")
|
||
|> render_change(%{"query" => "test"})
|
||
|
||
# Filter state should be maintained in URL
|
||
path = assert_patch(view)
|
||
assert path =~ "paid_filter=paid"
|
||
end
|
||
end
|
||
|
||
describe "paid column in table" do
|
||
setup do
|
||
{:ok, paid_member} =
|
||
Mv.Membership.create_member(%{
|
||
first_name: "Paid",
|
||
last_name: "Member",
|
||
email: "paid.column@example.com",
|
||
paid: true
|
||
})
|
||
|
||
{:ok, unpaid_member} =
|
||
Mv.Membership.create_member(%{
|
||
first_name: "Unpaid",
|
||
last_name: "Member",
|
||
email: "unpaid.column@example.com",
|
||
paid: false
|
||
})
|
||
|
||
%{paid_member: paid_member, unpaid_member: unpaid_member}
|
||
end
|
||
|
||
test "paid column shows green badge for paid members", %{conn: conn} do
|
||
conn = conn_with_oidc_user(conn)
|
||
{:ok, _view, html} = live(conn, "/members")
|
||
|
||
# Check for success badge (green)
|
||
assert html =~ "badge-success"
|
||
end
|
||
|
||
test "paid column shows red badge for unpaid members", %{conn: conn} do
|
||
conn = conn_with_oidc_user(conn)
|
||
{:ok, _view, html} = live(conn, "/members")
|
||
|
||
# Check for error badge (red)
|
||
assert html =~ "badge-error"
|
||
end
|
||
|
||
test "paid column shows 'Yes' for paid members", %{conn: conn} do
|
||
conn = conn_with_oidc_user(conn)
|
||
Gettext.put_locale(MvWeb.Gettext, "en")
|
||
{:ok, _view, html} = live(conn, "/members")
|
||
|
||
# The table should contain "Yes" text inside badge
|
||
assert html =~ "badge-success"
|
||
assert html =~ "Yes"
|
||
end
|
||
|
||
test "paid column shows 'No' for unpaid members", %{conn: conn} do
|
||
conn = conn_with_oidc_user(conn)
|
||
Gettext.put_locale(MvWeb.Gettext, "en")
|
||
{:ok, _view, html} = live(conn, "/members")
|
||
|
||
# The table should contain "No" text inside badge
|
||
assert html =~ "badge-error"
|
||
assert html =~ "No"
|
||
end
|
||
end
|
||
end
|