fix: fix tests and remove navbar remainings
Some checks failed
continuous-integration/drone/push Build is failing

This commit is contained in:
Simon 2026-01-12 15:16:31 +01:00
parent 30805b07ca
commit 8a1b14fc79
Signed by: simon
GPG key ID: 40E7A58C4AA1EDB2
9 changed files with 706 additions and 332 deletions

View file

@ -0,0 +1,233 @@
# Analyse der fehlschlagenden Tests
## Übersicht
**Gesamtanzahl fehlschlagender Tests:** 5
- **show_test.exs:** 1 Fehler
- **sidebar_test.exs:** 4 Fehler
---
## Kategorisierung
### Kategorie 1: Test-Assertions passen nicht zur Implementierung (4 Tests)
Diese Tests erwarten bestimmte Werte/Attribute, die in der aktuellen Implementierung anders sind oder fehlen.
### Kategorie 2: Datenbank-Isolation Problem (1 Test)
Ein Test schlägt fehl, weil die Datenbank nicht korrekt isoliert ist.
---
## Detaillierte Analyse
### 1. `show_test.exs` - Custom Fields Sichtbarkeit
**Test:** `does not display Custom Fields section when no custom fields exist` (Zeile 112)
**Problem:**
- Der Test erwartet, dass die "Custom Fields" Sektion NICHT angezeigt wird, wenn keine Custom Fields existieren
- Die Sektion wird aber angezeigt, weil in der Datenbank noch Custom Fields von anderen Tests vorhanden sind
**Ursache:**
- Die LiveView lädt alle Custom Fields aus der Datenbank (Zeile 238-242 in `show.ex`)
- Die Test-Datenbank wird nicht zwischen Tests geleert
- Da `async: false` verwendet wird, sollten die Tests sequenziell laufen, aber Custom Fields bleiben in der Datenbank
**Kategorie:** Datenbank-Isolation Problem
---
### 2. `sidebar_test.exs` - Settings Link
**Test:** `T3.1: renders flat menu items with icons and labels` (Zeile 174)
**Problem:**
- Test erwartet `href="#"` für Settings
- Tatsächlicher Wert: `href="/settings"`
**Ursache:**
- Die Implementierung verwendet einen echten Link `~p"/settings"` (Zeile 100 in `sidebar.ex`)
- Der Test erwartet einen Placeholder-Link `href="#"`
**Kategorie:** Test-Assertion passt nicht zur Implementierung
---
### 3. `sidebar_test.exs` - Drawer Overlay CSS-Klasse
**Test:** `drawer overlay is present` (Zeile 747)
**Problem:**
- Test sucht nach exakt `class="drawer-overlay"`
- Tatsächlicher Wert: `class="drawer-overlay lg:hidden focus:outline-none focus:ring-2 focus:ring-primary"`
**Ursache:**
- Der Test verwendet eine exakte String-Suche (`~s(class="drawer-overlay")`)
- Die Implementierung hat mehrere CSS-Klassen
**Kategorie:** Test-Assertion passt nicht zur Implementierung
---
### 4. `sidebar_test.exs` - Toggle Button ARIA-Attribut
**Test:** `T5.2: toggle button has correct ARIA attributes` (Zeile 324)
**Problem:**
- Test erwartet `aria-controls="main-sidebar"` am Toggle-Button
- Das Attribut fehlt in der Implementierung (Zeile 45-65 in `sidebar.ex`)
**Ursache:**
- Das `aria-controls` Attribut wurde nicht in der Implementierung hinzugefügt
- Der Test erwartet es für bessere Accessibility
**Kategorie:** Test-Assertion passt nicht zur Implementierung (Accessibility-Feature fehlt)
---
### 5. `sidebar_test.exs` - Contribution Settings Link
**Test:** `sidebar structure is complete with all sections` (Zeile 501)
**Problem:**
- Test erwartet Link `/contribution_settings`
- Tatsächlicher Link: `/membership_fee_settings`
**Ursache:**
- Der Test hat eine veraltete/inkorrekte Erwartung
- Die Implementierung verwendet `/membership_fee_settings` (Zeile 96 in `sidebar.ex`)
**Kategorie:** Test-Assertion passt nicht zur Implementierung (veralteter Test)
---
## Lösungsvorschläge
### Lösung 1: `show_test.exs` - Custom Fields Sichtbarkeit
**Option A: Test-Datenbank bereinigen (Empfohlen)**
- Im `setup` Block alle Custom Fields löschen, bevor der Test läuft
- Oder: Explizit prüfen, dass keine Custom Fields existieren
**Option B: Test anpassen**
- Den Test so anpassen, dass er explizit alle Custom Fields löscht
- Oder: Die LiveView-Logik ändern, um nur Custom Fields zu laden, die tatsächlich existieren
**Empfehlung:** Option A - Im Test-Setup alle Custom Fields löschen
```elixir
setup do
# Clean up any existing custom fields
Mv.Membership.CustomField
|> Ash.read!()
|> Enum.each(&Ash.destroy!/1)
# Create test member
{:ok, member} = ...
%{member: member}
end
```
---
### Lösung 2: `sidebar_test.exs` - Settings Link
**Option A: Test anpassen (Empfohlen)**
- Test ändern, um `href="/settings"` zu erwarten statt `href="#"`
**Option B: Implementierung ändern**
- Settings-Link zu `href="#"` ändern (nicht empfohlen, da es ein echter Link sein sollte)
**Empfehlung:** Option A - Test anpassen
```elixir
# Zeile 190 ändern von:
assert html =~ ~s(href="#")
# zu:
assert html =~ ~s(href="/settings")
```
---
### Lösung 3: `sidebar_test.exs` - Drawer Overlay CSS-Klasse
**Option A: Test anpassen (Empfohlen)**
- Test ändern, um nach der Klasse in der Klasse-Liste zu suchen (mit `has_class?` Helper)
**Option B: Regex verwenden**
- Regex verwenden, um die Klasse zu finden
**Empfehlung:** Option A - Test anpassen
```elixir
# Zeile 752 ändern von:
assert html =~ ~s(class="drawer-overlay")
# zu:
assert has_class?(html, "drawer-overlay")
```
---
### Lösung 4: `sidebar_test.exs` - Toggle Button ARIA-Attribut
**Option A: Implementierung anpassen (Empfohlen)**
- `aria-controls="main-sidebar"` zum Toggle-Button hinzufügen
**Option B: Test anpassen**
- Test entfernen oder als optional markieren (nicht empfohlen für Accessibility)
**Empfehlung:** Option A - Implementierung anpassen
```elixir
# In sidebar.ex Zeile 45-52, aria-controls hinzufügen:
<button
type="button"
id="sidebar-toggle"
class="hidden lg:flex ml-auto btn btn-ghost btn-sm btn-square"
aria-label={gettext("Toggle sidebar")}
aria-controls="main-sidebar"
aria-expanded="true"
onclick="toggleSidebar()"
>
```
---
### Lösung 5: `sidebar_test.exs` - Contribution Settings Link
**Option A: Test anpassen (Empfohlen)**
- Test ändern, um `/membership_fee_settings` statt `/contribution_settings` zu erwarten
**Option B: Link hinzufügen**
- Einen neuen Link `/contribution_settings` hinzufügen (nicht empfohlen, da redundant)
**Empfehlung:** Option A - Test anpassen
```elixir
# Zeile 519 ändern von:
"/contribution_settings",
# zu:
# Entfernen oder durch "/membership_fee_settings" ersetzen
# (da "/membership_fee_settings" bereits in Zeile 518 vorhanden ist)
```
---
## Zusammenfassung der empfohlenen Änderungen
1. **show_test.exs:** Custom Fields im Setup löschen
2. **sidebar_test.exs (T3.1):** Settings-Link Assertion anpassen
3. **sidebar_test.exs (drawer overlay):** CSS-Klasse-Suche mit Helper-Funktion
4. **sidebar_test.exs (T5.2):** `aria-controls` Attribut zur Implementierung hinzufügen
5. **sidebar_test.exs (edge cases):** Falschen Link aus erwarteter Liste entfernen
---
## Priorisierung
1. **Hoch:** Lösung 1 (show_test.exs) - Datenbank-Isolation ist wichtig
2. **Mittel:** Lösung 4 (ARIA-Attribut) - Accessibility-Verbesserung
3. **Niedrig:** Lösungen 2, 3, 5 - Einfache Test-Anpassungen

View file

@ -1,98 +0,0 @@
defmodule MvWeb.Layouts.Navbar do
@moduledoc """
Navbar that is used in the rootlayout shown on every page
"""
use MvWeb, :html
import MvWeb.Authorization
attr :current_user, :map,
required: true,
doc: "The current user - navbar is only shown when user is present"
attr :club_name, :string,
default: nil,
doc: "Optional club name - if not provided, will be loaded from database"
def navbar(assigns) do
club_name = assigns[:club_name] || get_club_name()
assigns = assign(assigns, :club_name, club_name)
~H"""
<header class="shadow-sm navbar bg-base-100">
<div class="flex-1">
<a href="/members" class="btn btn-ghost text-xl">{@club_name}</a>
<ul class="menu menu-horizontal bg-base-200">
<li><.link navigate="/members">{gettext("Members")}</.link></li>
<li>
<details>
<summary>{gettext("Settings")}</summary>
<ul class="bg-base-200 rounded-t-none p-2 z-10 w-48">
<li>
<.link navigate="/settings">{gettext("Global Settings")}</.link>
</li>
<%= if can_access_page?(@current_user, ~p"/admin/roles") do %>
<li>
<.link navigate={~p"/admin/roles"}>{gettext("Roles")}</.link>
</li>
<% end %>
</ul>
</details>
</li>
<li><.link navigate="/users">{gettext("Users")}</.link></li>
<li>
<details>
<summary>{gettext("Contributions")}</summary>
<ul class="bg-base-200 rounded-t-none p-2 z-10">
<li>
<.link navigate="/membership_fee_types">{gettext("Membership Fee Types")}</.link>
</li>
<li>
<.link navigate="/membership_fee_settings">
{gettext("Membership Fee Settings")}
</.link>
</li>
</ul>
</details>
</li>
</ul>
</div>
<div class="flex gap-2">
<form method="post" action="/set_locale" class="mr-4">
<input type="hidden" name="_csrf_token" value={Plug.CSRFProtection.get_csrf_token()} />
<label class="sr-only" for="locale-select">{gettext("Select language")}</label>
<select
id="locale-select"
name="locale"
onchange="this.form.submit()"
class="select select-sm"
aria-label={gettext("Select language")}
>
<option value="de" selected={Gettext.get_locale() == "de"}>Deutsch</option>
<option value="en" selected={Gettext.get_locale() == "en"}>English</option>
</select>
</form>
<!-- Daisy UI Theme Toggle for dark and light mode-->
<label class="flex cursor-pointer gap-2" aria-label={gettext("Toggle dark mode")}>
<input
type="checkbox"
value="dark"
class="toggle toggle-sm theme-controller"
aria-label={gettext("Toggle dark mode")}
/>
<.icon name="hero-sun" class="size-5" aria-hidden="true" />
<.icon name="hero-moon" class="size-5" aria-hidden="true" />
</label>
</div>
</header>
"""
end
# Helper function to get club name from settings
# Falls back to "Mitgliederverwaltung" if settings can't be loaded
defp get_club_name do
case Mv.Membership.get_settings() do
{:ok, settings} -> settings.club_name
_ -> "Mitgliederverwaltung"
end
end
end

View file

@ -34,12 +34,12 @@ defmodule MvWeb.Layouts.Sidebar do
<div class="flex items-center gap-3 p-4 border-b border-base-300">
<!-- Logo -->
<img src={~p"/images/mila.svg"} alt="Mila Logo" class="size-8 shrink-0" />
<!-- Club Name -->
<span class="menu-label text-lg font-bold truncate">
{@club_name}
</span>
<!-- Toggle Button (Desktop only) -->
<%= unless @mobile do %>
<button
@ -47,6 +47,7 @@ defmodule MvWeb.Layouts.Sidebar do
id="sidebar-toggle"
class="hidden lg:flex ml-auto btn btn-ghost btn-sm btn-square"
aria-label={gettext("Toggle sidebar")}
aria-controls="main-sidebar"
aria-expanded="true"
onclick="toggleSidebar()"
>
@ -86,18 +87,18 @@ defmodule MvWeb.Layouts.Sidebar do
icon="hero-rectangle-group"
label={gettext("Custom Fields")}
/>
<!-- Nested Menu: Contributions -->
<.menu_group
icon="hero-currency-dollar"
label={gettext("Contributions")}
>
<.menu_subitem href="/contribution_types" label={gettext("Contribution Types")} />
<.menu_subitem href="/contribution_settings" label={gettext("Settings")} />
<.menu_subitem href="/membership_fee_settings" label={gettext("Settings")} />
</.menu_group>
<.menu_item
href="#"
href={~p"/settings"}
icon="hero-cog-6-tooth"
label={gettext("Settings")}
/>
@ -146,7 +147,7 @@ defmodule MvWeb.Layouts.Sidebar do
{render_slot(@inner_block)}
</ul>
</details>
<!-- Collapsed Mode: Dropdown -->
<div class="collapsed-menu-group dropdown dropdown-right">
<button
@ -207,10 +208,10 @@ defmodule MvWeb.Layouts.Sidebar do
<option value="en" selected={Gettext.get_locale() == "en"}>English</option>
</select>
</form>
<!-- Theme Toggle (immer sichtbar) -->
<.theme_toggle />
<!-- User Menu (nur wenn current_user existiert) -->
<%= if @current_user do %>
<.user_menu current_user={@current_user} />

View file

@ -302,7 +302,7 @@ msgstr "Benutzer*in bearbeiten"
msgid "Enabled"
msgstr "Aktiviert"
#: lib/mv_web/components/layouts/navbar.ex
#: lib/mv_web/components/layouts/sidebar.ex
#, elixir-autogen, elixir-format
msgid "Logout"
msgstr "Abmelden"
@ -319,6 +319,7 @@ msgid "Member"
msgstr "Mitglied"
#: lib/mv_web/components/layouts/navbar.ex
#: lib/mv_web/components/layouts/sidebar.ex
#: lib/mv_web/live/contribution_type_live/index.ex
#: lib/mv_web/live/member_live/index.ex
#: lib/mv_web/live/member_live/index.html.heex
@ -362,11 +363,6 @@ msgstr "Hinweis"
msgid "Password Authentication"
msgstr "Passwort-Authentifizierung"
#: lib/mv_web/components/layouts/navbar.ex
#, elixir-autogen, elixir-format
msgid "Profil"
msgstr "Profil"
#: lib/mv_web/live/custom_field_live/form_component.ex
#: lib/mv_web/live/custom_field_live/index_component.ex
#: lib/mv_web/live/member_field_live/form_component.ex
@ -386,6 +382,7 @@ msgid "Select member"
msgstr "Mitglied auswählen"
#: lib/mv_web/components/layouts/navbar.ex
#: lib/mv_web/components/layouts/sidebar.ex
#: lib/mv_web/live/global_settings_live.ex
#, elixir-autogen, elixir-format
msgid "Settings"
@ -555,11 +552,13 @@ msgid "Back to users list"
msgstr "Zurück zur Benutzer*innen-Liste"
#: lib/mv_web/components/layouts/navbar.ex
#: lib/mv_web/components/layouts/sidebar.ex
#, elixir-autogen, elixir-format
msgid "Select language"
msgstr "Sprache auswählen"
#: lib/mv_web/components/layouts/navbar.ex
#: lib/mv_web/components/layouts/sidebar.ex
#, elixir-autogen, elixir-format
msgid "Toggle dark mode"
msgstr "Dunklen Modus umschalten"
@ -571,6 +570,7 @@ msgid "Search..."
msgstr "Suchen..."
#: lib/mv_web/components/layouts/navbar.ex
#: lib/mv_web/components/layouts/sidebar.ex
#: lib/mv_web/live/role_live/index.html.heex
#, elixir-autogen, elixir-format
msgid "Users"
@ -636,6 +636,7 @@ msgstr "Benutzerdefinierter Feldwert erfolgreich %{action}"
msgid "Please select a custom field first"
msgstr "Bitte wähle zuerst ein Benutzerdefiniertes Feld"
#: lib/mv_web/components/layouts/sidebar.ex
#: lib/mv_web/live/member_live/form.ex
#: lib/mv_web/live/member_live/show.ex
#, elixir-autogen, elixir-format
@ -919,6 +920,7 @@ msgstr "Beitragsart ändern"
msgid "Contribution Start"
msgstr "Beitragsbeginn"
#: lib/mv_web/components/layouts/sidebar.ex
#: lib/mv_web/live/contribution_type_live/index.ex
#, elixir-autogen, elixir-format, fuzzy
msgid "Contribution Types"
@ -930,6 +932,7 @@ msgid "Contribution type"
msgstr "Beitragsart"
#: lib/mv_web/components/layouts/navbar.ex
#: lib/mv_web/components/layouts/sidebar.ex
#, elixir-autogen, elixir-format, fuzzy
msgid "Contributions"
msgstr "Beiträge"
@ -1735,7 +1738,12 @@ msgstr "Wählen Sie eine Mitgliedsbeitragsart für dieses Mitglied. Mitglieder k
msgid "Select interval"
msgstr "Intervall auswählen"
#: lib/mv_web/live/member_live/show.ex
#: lib/mv_web/live/membership_fee_settings_live.ex
#, elixir-autogen, elixir-format, fuzzy
msgid "Settings saved successfully."
msgstr "Einstellungen erfolgreich gespeichert"
#: lib/mv_web/live/member_live/show/membership_fees_component.ex
#, elixir-autogen, elixir-format
msgid "This action cannot be undone."
msgstr "Diese Aktion kann nicht rückgängig gemacht werden."
@ -1756,6 +1764,7 @@ msgid "This membership fee type is automatically assigned to all new members. Ca
msgstr "Diese Mitgliedsbeitragsart wird automatisch allen neuen Mitgliedern zugewiesen. Kann individuell pro Mitglied geändert werden."
#: lib/mv_web/live/member_live/show.ex
#: lib/mv_web/live/role_live/index.html.heex
#, elixir-autogen, elixir-format
msgid "Type"
msgstr "Art"
@ -1872,31 +1881,198 @@ msgstr "Neues Datenfeld"
msgid "Save Data Field"
msgstr "Datenfeld speichern"
#~ #: lib/mv_web/live/member_live/index.html.heex
#~ #, elixir-autogen, elixir-format
#~ msgid "Show current cycle"
#~ msgstr "Aktuellen Zyklus anzeigen"
#~ #: lib/mv_web/live/member_live/index.html.heex
#~ #, elixir-autogen, elixir-format
#~ msgid "Unpaid in last cycle"
#~ msgstr "Unbezahlt im letzten Zyklus"
#~ #: lib/mv_web/live/custom_field_live/index_component.ex
#~ #, elixir-autogen, elixir-format, fuzzy
#~ msgid "New Custom field"
#~ msgstr "Benutzerdefiniertes Feld speichern"
#~ #: lib/mv_web/live/member_live/index.html.heex
#~ #, elixir-autogen, elixir-format
#~ msgid "Show Last/Current Cycle Payment Status"
#~ msgstr ""
#: lib/mv_web/live/role_live/show.ex
#, elixir-autogen, elixir-format, fuzzy
msgid "Back to roles list"
msgstr "Zurück zur Rollen-Liste"
#: lib/mv_web/live/role_live/index.html.heex
#, elixir-autogen, elixir-format
msgid "Cannot delete system role"
msgstr ""
#: lib/mv_web/live/role_live/index.html.heex
#, elixir-autogen, elixir-format, fuzzy
msgid "Custom"
msgstr "Benutzerdefinierte Felder"
#: lib/mv_web/live/role_live/show.ex
#, elixir-autogen, elixir-format, fuzzy
msgid "Edit Role"
msgstr "Bearbeiten"
#: lib/mv_web/live/role_live/index.ex
#: lib/mv_web/live/role_live/show.ex
#, elixir-autogen, elixir-format, fuzzy
msgid "Failed to delete role: %{error}"
msgstr "Konnte Feld nicht löschen: %{error}"
#: lib/mv_web/live/role_live/index.ex
#: lib/mv_web/live/role_live/index.html.heex
#, elixir-autogen, elixir-format, fuzzy
msgid "Listing Roles"
msgstr "Benutzer*innen auflisten"
#: lib/mv_web/live/role_live/index.html.heex
#, elixir-autogen, elixir-format
msgid "Manage user roles and their permission sets."
msgstr ""
#: lib/mv_web/live/role_live/index.ex
#: lib/mv_web/live/role_live/show.ex
#, elixir-autogen, elixir-format
msgid "Cannot delete role. %{count} user(s) are still assigned to this role. Please assign them to another role first."
msgstr ""
#: lib/mv_web/components/layouts/sidebar.ex
#, elixir-autogen, elixir-format
msgid "Close sidebar"
msgstr ""
#: lib/mv_web/live/role_live/show.ex
#, elixir-autogen, elixir-format, fuzzy
msgid "Delete Role"
msgstr "Zyklus löschen"
#: lib/mv_web/components/layouts/sidebar.ex
#, elixir-autogen, elixir-format
msgid "Main navigation"
msgstr ""
#: lib/mv_web/live/role_live/index.html.heex
#, elixir-autogen, elixir-format
msgid "New Role"
msgstr ""
#: lib/mv_web/live/role_live/index.html.heex
#: lib/mv_web/live/role_live/show.ex
#, elixir-autogen, elixir-format, fuzzy
msgid "No description"
msgstr "Beschreibung"
#: lib/mv_web/components/layouts.ex
#, elixir-autogen, elixir-format
msgid "Open navigation menu"
msgstr ""
#: lib/mv_web/live/role_live/form.ex
#: lib/mv_web/live/role_live/index.html.heex
#: lib/mv_web/live/role_live/show.ex
#, elixir-autogen, elixir-format
msgid "Permission Set"
msgstr ""
#: lib/mv_web/components/layouts/sidebar.ex
#, elixir-autogen, elixir-format, fuzzy
msgid "Profile"
msgstr "Profil"
#: lib/mv_web/live/role_live/form.ex
#: lib/mv_web/live/role_live/show.ex
#, elixir-autogen, elixir-format
msgid "Role"
msgstr ""
#: lib/mv_web/live/role_live/index.ex
#: lib/mv_web/live/role_live/show.ex
#, elixir-autogen, elixir-format, fuzzy
msgid "Role deleted successfully."
msgstr "Zyklen erfolgreich regeneriert"
#: lib/mv_web/live/role_live/show.ex
#, elixir-autogen, elixir-format
msgid "Role details and permissions."
msgstr ""
#: lib/mv_web/live/role_live/form.ex
#: lib/mv_web/live/role_live/index.ex
#: lib/mv_web/live/role_live/show.ex
#, elixir-autogen, elixir-format
msgid "Role not found."
msgstr ""
#: lib/mv_web/live/role_live/form.ex
#, elixir-autogen, elixir-format
msgid "Role saved successfully."
msgstr ""
#: lib/mv_web/components/layouts/navbar.ex
#, elixir-autogen, elixir-format
msgid "Roles"
msgstr ""
#: lib/mv_web/live/role_live/form.ex
#, elixir-autogen, elixir-format, fuzzy
msgid "Save Role"
msgstr "Speichern"
#: lib/mv_web/live/role_live/form.ex
#, elixir-autogen, elixir-format
msgid "Select permission set"
msgstr ""
#: lib/mv_web/live/role_live/show.ex
#, elixir-autogen, elixir-format, fuzzy
msgid "Show Role"
msgstr "Anzeigen"
#: lib/mv_web/live/role_live/index.html.heex
#, elixir-autogen, elixir-format
msgid "System"
msgstr ""
#: lib/mv_web/live/role_live/index.html.heex
#: lib/mv_web/live/role_live/show.ex
#, elixir-autogen, elixir-format
msgid "System Role"
msgstr ""
#: lib/mv_web/live/role_live/index.html.heex
#, elixir-autogen, elixir-format
msgid "System roles cannot be deleted"
msgstr ""
#: lib/mv_web/live/role_live/index.ex
#: lib/mv_web/live/role_live/show.ex
#, elixir-autogen, elixir-format
msgid "System roles cannot be deleted."
msgstr ""
#: lib/mv_web/components/layouts/sidebar.ex
#, elixir-autogen, elixir-format
msgid "Toggle sidebar"
msgstr ""
#: lib/mv_web/live/role_live/form.ex
#, elixir-autogen, elixir-format, fuzzy
msgid "Use this form to manage roles in your database."
msgstr "Verwenden Sie dieses Formular, um Benutzer*innen-Datensätze zu verwalten."
#: lib/mv_web/components/layouts/sidebar.ex
#, elixir-autogen, elixir-format, fuzzy
msgid "User menu"
msgstr "Benutzer*in"
#: lib/mv_web/live/role_live/form.ex
#, elixir-autogen, elixir-format
msgid "admin - Unrestricted access"
msgstr ""
#: lib/mv_web/live/role_live/form.ex
#, elixir-autogen, elixir-format
msgid "normal_user - Create/Read/Update access"
msgstr ""
#: lib/mv_web/live/role_live/form.ex
#, elixir-autogen, elixir-format
msgid "own_data - Access only to own data"
msgstr ""
#: lib/mv_web/live/role_live/form.ex
#, elixir-autogen, elixir-format
msgid "read_only - Read access to all data"
msgstr ""
#~ #: lib/mv_web/live/custom_field_live/show.ex
#~ #, elixir-autogen, elixir-format
#~ msgid "Auto-generated identifier (immutable)"
@ -1929,17 +2105,6 @@ msgstr "Zurück zur Rollen-Liste"
#~ msgid "Default Contribution Type"
#~ msgstr "Standard-Beitragsart"
#: lib/mv_web/live/role_live/index.html.heex
#: lib/mv_web/live/role_live/show.ex
#, elixir-autogen, elixir-format, fuzzy
msgid "No description"
msgstr "Beschreibung"
#~ #: lib/mv_web/live/member_live/show/membership_fees_component.ex
#~ #, elixir-autogen, elixir-format, fuzzy
#~ msgid "Failed to delete some cycles: %{errors}"
#~ msgstr "Konnte Feld nicht löschen: %{error}"
#~ #: lib/mv_web/live/custom_field_live/form_component.ex
#~ #, elixir-autogen, elixir-format
#~ msgid "Immutable"

View file

@ -571,8 +571,8 @@ msgid "Search..."
msgstr ""
#: lib/mv_web/components/layouts/navbar.ex
#: lib/mv_web/live/role_live/index.html.heex
#: lib/mv_web/components/layouts/sidebar.ex
#: lib/mv_web/live/role_live/index.html.heex
#, elixir-autogen, elixir-format
msgid "Users"
msgstr ""
@ -637,7 +637,7 @@ msgstr ""
msgid "Please select a custom field first"
msgstr ""
#: lib/mv_web/live/custom_field_live/index_component.ex
#: lib/mv_web/components/layouts/sidebar.ex
#: lib/mv_web/live/member_live/form.ex
#: lib/mv_web/live/member_live/show.ex
#, elixir-autogen, elixir-format
@ -1919,7 +1919,157 @@ msgstr ""
msgid "Manage user roles and their permission sets."
msgstr ""
#: lib/mv_web/live/role_live/index.ex
#: lib/mv_web/live/role_live/show.ex
#, elixir-autogen, elixir-format
msgid "Cannot delete role. %{count} user(s) are still assigned to this role. Please assign them to another role first."
msgstr ""
#: lib/mv_web/components/layouts/sidebar.ex
#, elixir-autogen, elixir-format
msgid "Close sidebar"
msgstr ""
#: lib/mv_web/live/role_live/show.ex
#, elixir-autogen, elixir-format
msgid "Delete Role"
msgstr ""
#: lib/mv_web/components/layouts/sidebar.ex
#, elixir-autogen, elixir-format
msgid "Main navigation"
msgstr ""
#: lib/mv_web/live/role_live/index.html.heex
#, elixir-autogen, elixir-format
msgid "Not set"
msgid "New Role"
msgstr ""
#: lib/mv_web/live/role_live/index.html.heex
#: lib/mv_web/live/role_live/show.ex
#, elixir-autogen, elixir-format
msgid "No description"
msgstr ""
#: lib/mv_web/components/layouts.ex
#, elixir-autogen, elixir-format
msgid "Open navigation menu"
msgstr ""
#: lib/mv_web/live/role_live/form.ex
#: lib/mv_web/live/role_live/index.html.heex
#: lib/mv_web/live/role_live/show.ex
#, elixir-autogen, elixir-format
msgid "Permission Set"
msgstr ""
#: lib/mv_web/components/layouts/sidebar.ex
#, elixir-autogen, elixir-format
msgid "Profile"
msgstr ""
#: lib/mv_web/live/role_live/form.ex
#: lib/mv_web/live/role_live/show.ex
#, elixir-autogen, elixir-format
msgid "Role"
msgstr ""
#: lib/mv_web/live/role_live/index.ex
#: lib/mv_web/live/role_live/show.ex
#, elixir-autogen, elixir-format
msgid "Role deleted successfully."
msgstr ""
#: lib/mv_web/live/role_live/show.ex
#, elixir-autogen, elixir-format
msgid "Role details and permissions."
msgstr ""
#: lib/mv_web/live/role_live/form.ex
#: lib/mv_web/live/role_live/index.ex
#: lib/mv_web/live/role_live/show.ex
#, elixir-autogen, elixir-format
msgid "Role not found."
msgstr ""
#: lib/mv_web/live/role_live/form.ex
#, elixir-autogen, elixir-format
msgid "Role saved successfully."
msgstr ""
#: lib/mv_web/components/layouts/navbar.ex
#, elixir-autogen, elixir-format
msgid "Roles"
msgstr ""
#: lib/mv_web/live/role_live/form.ex
#, elixir-autogen, elixir-format
msgid "Save Role"
msgstr ""
#: lib/mv_web/live/role_live/form.ex
#, elixir-autogen, elixir-format
msgid "Select permission set"
msgstr ""
#: lib/mv_web/live/role_live/show.ex
#, elixir-autogen, elixir-format
msgid "Show Role"
msgstr ""
#: lib/mv_web/live/role_live/index.html.heex
#, elixir-autogen, elixir-format
msgid "System"
msgstr ""
#: lib/mv_web/live/role_live/index.html.heex
#: lib/mv_web/live/role_live/show.ex
#, elixir-autogen, elixir-format
msgid "System Role"
msgstr ""
#: lib/mv_web/live/role_live/index.html.heex
#, elixir-autogen, elixir-format
msgid "System roles cannot be deleted"
msgstr ""
#: lib/mv_web/live/role_live/index.ex
#: lib/mv_web/live/role_live/show.ex
#, elixir-autogen, elixir-format
msgid "System roles cannot be deleted."
msgstr ""
#: lib/mv_web/components/layouts/sidebar.ex
#, elixir-autogen, elixir-format
msgid "Toggle sidebar"
msgstr ""
#: lib/mv_web/live/role_live/form.ex
#, elixir-autogen, elixir-format
msgid "Use this form to manage roles in your database."
msgstr ""
#: lib/mv_web/components/layouts/sidebar.ex
#, elixir-autogen, elixir-format
msgid "User menu"
msgstr ""
#: lib/mv_web/live/role_live/form.ex
#, elixir-autogen, elixir-format
msgid "admin - Unrestricted access"
msgstr ""
#: lib/mv_web/live/role_live/form.ex
#, elixir-autogen, elixir-format
msgid "normal_user - Create/Read/Update access"
msgstr ""
#: lib/mv_web/live/role_live/form.ex
#, elixir-autogen, elixir-format
msgid "own_data - Access only to own data"
msgstr ""
#: lib/mv_web/live/role_live/form.ex
#, elixir-autogen, elixir-format
msgid "read_only - Read access to all data"
msgstr ""

View file

@ -303,7 +303,7 @@ msgstr ""
msgid "Enabled"
msgstr ""
#: lib/mv_web/components/layouts/navbar.ex
#: lib/mv_web/components/layouts/sidebar.ex
#, elixir-autogen, elixir-format
msgid "Logout"
msgstr ""
@ -320,6 +320,7 @@ msgid "Member"
msgstr ""
#: lib/mv_web/components/layouts/navbar.ex
#: lib/mv_web/components/layouts/sidebar.ex
#: lib/mv_web/live/contribution_type_live/index.ex
#: lib/mv_web/live/member_live/index.ex
#: lib/mv_web/live/member_live/index.html.heex
@ -363,11 +364,6 @@ msgstr ""
msgid "Password Authentication"
msgstr ""
#: lib/mv_web/components/layouts/navbar.ex
#, elixir-autogen, elixir-format
msgid "Profil"
msgstr ""
#: lib/mv_web/live/custom_field_live/form_component.ex
#: lib/mv_web/live/custom_field_live/index_component.ex
#: lib/mv_web/live/member_field_live/form_component.ex
@ -387,6 +383,7 @@ msgid "Select member"
msgstr ""
#: lib/mv_web/components/layouts/navbar.ex
#: lib/mv_web/components/layouts/sidebar.ex
#: lib/mv_web/live/global_settings_live.ex
#, elixir-autogen, elixir-format
msgid "Settings"
@ -556,11 +553,13 @@ msgid "Back to users list"
msgstr ""
#: lib/mv_web/components/layouts/navbar.ex
#: lib/mv_web/components/layouts/sidebar.ex
#, elixir-autogen, elixir-format, fuzzy
msgid "Select language"
msgstr ""
#: lib/mv_web/components/layouts/navbar.ex
#: lib/mv_web/components/layouts/sidebar.ex
#, elixir-autogen, elixir-format
msgid "Toggle dark mode"
msgstr ""
@ -572,6 +571,7 @@ msgid "Search..."
msgstr ""
#: lib/mv_web/components/layouts/navbar.ex
#: lib/mv_web/components/layouts/sidebar.ex
#: lib/mv_web/live/role_live/index.html.heex
#, elixir-autogen, elixir-format, fuzzy
msgid "Users"
@ -637,6 +637,7 @@ msgstr ""
msgid "Please select a custom field first"
msgstr ""
#: lib/mv_web/components/layouts/sidebar.ex
#: lib/mv_web/live/member_live/form.ex
#: lib/mv_web/live/member_live/show.ex
#, elixir-autogen, elixir-format, fuzzy
@ -920,6 +921,7 @@ msgstr ""
msgid "Contribution Start"
msgstr ""
#: lib/mv_web/components/layouts/sidebar.ex
#: lib/mv_web/live/contribution_type_live/index.ex
#, elixir-autogen, elixir-format
msgid "Contribution Types"
@ -931,6 +933,7 @@ msgid "Contribution type"
msgstr ""
#: lib/mv_web/components/layouts/navbar.ex
#: lib/mv_web/components/layouts/sidebar.ex
#, elixir-autogen, elixir-format
msgid "Contributions"
msgstr ""
@ -1916,6 +1919,27 @@ msgstr ""
msgid "Manage user roles and their permission sets."
msgstr ""
#: lib/mv_web/live/role_live/index.ex
#: lib/mv_web/live/role_live/show.ex
#, elixir-autogen, elixir-format
msgid "Cannot delete role. %{count} user(s) are still assigned to this role. Please assign them to another role first."
msgstr ""
#: lib/mv_web/components/layouts/sidebar.ex
#, elixir-autogen, elixir-format
msgid "Close sidebar"
msgstr ""
#: lib/mv_web/live/role_live/show.ex
#, elixir-autogen, elixir-format, fuzzy
msgid "Delete Role"
msgstr ""
#: lib/mv_web/components/layouts/sidebar.ex
#, elixir-autogen, elixir-format
msgid "Main navigation"
msgstr ""
#: lib/mv_web/live/role_live/index.html.heex
#, elixir-autogen, elixir-format
msgid "New Role"
@ -1927,6 +1951,11 @@ msgstr ""
msgid "No description"
msgstr ""
#: lib/mv_web/components/layouts.ex
#, elixir-autogen, elixir-format
msgid "Open navigation menu"
msgstr ""
#: lib/mv_web/live/role_live/form.ex
#: lib/mv_web/live/role_live/index.html.heex
#: lib/mv_web/live/role_live/show.ex
@ -1934,17 +1963,45 @@ msgstr ""
msgid "Permission Set"
msgstr ""
#: lib/mv_web/components/layouts/sidebar.ex
#, elixir-autogen, elixir-format, fuzzy
msgid "Profile"
msgstr ""
#: lib/mv_web/live/role_live/form.ex
#: lib/mv_web/live/role_live/show.ex
#, elixir-autogen, elixir-format
msgid "Role"
msgstr ""
#: lib/mv_web/live/role_live/index.ex
#: lib/mv_web/live/role_live/show.ex
#, elixir-autogen, elixir-format, fuzzy
msgid "Role deleted successfully."
msgstr ""
#: lib/mv_web/live/role_live/show.ex
#, elixir-autogen, elixir-format
msgid "Role details and permissions."
msgstr ""
#: lib/mv_web/live/role_live/form.ex
#: lib/mv_web/live/role_live/index.ex
#: lib/mv_web/live/role_live/show.ex
#, elixir-autogen, elixir-format
msgid "Role not found."
msgstr ""
#: lib/mv_web/live/role_live/form.ex
#, elixir-autogen, elixir-format, fuzzy
msgid "Role saved successfully."
msgstr ""
#: lib/mv_web/components/layouts/navbar.ex
#, elixir-autogen, elixir-format, fuzzy
msgid "Roles"
msgstr ""
#: lib/mv_web/live/role_live/form.ex
#, elixir-autogen, elixir-format, fuzzy
msgid "Save Role"
@ -1976,11 +2033,27 @@ msgstr ""
msgid "System roles cannot be deleted"
msgstr ""
#: lib/mv_web/live/role_live/index.ex
#: lib/mv_web/live/role_live/show.ex
#, elixir-autogen, elixir-format, fuzzy
msgid "System roles cannot be deleted."
msgstr ""
#: lib/mv_web/components/layouts/sidebar.ex
#, elixir-autogen, elixir-format
msgid "Toggle sidebar"
msgstr ""
#: lib/mv_web/live/role_live/form.ex
#, elixir-autogen, elixir-format, fuzzy
msgid "Use this form to manage roles in your database."
msgstr ""
#: lib/mv_web/components/layouts/sidebar.ex
#, elixir-autogen, elixir-format, fuzzy
msgid "User menu"
msgstr ""
#: lib/mv_web/live/role_live/form.ex
#, elixir-autogen, elixir-format
msgid "admin - Unrestricted access"
@ -2001,71 +2074,16 @@ msgstr ""
msgid "read_only - Read access to all data"
msgstr ""
#: lib/mv_web/live/role_live/show.ex
#, elixir-autogen, elixir-format, fuzzy
msgid "Delete Role"
msgstr ""
#: lib/mv_web/live/role_live/index.ex
#: lib/mv_web/live/role_live/show.ex
#, elixir-autogen, elixir-format, fuzzy
msgid "Role deleted successfully."
msgstr ""
#: lib/mv_web/components/layouts/navbar.ex
#, elixir-autogen, elixir-format, fuzzy
msgid "Roles"
msgstr ""
#: lib/mv_web/live/role_live/index.ex
#: lib/mv_web/live/role_live/show.ex
#, elixir-autogen, elixir-format
msgid "Cannot delete role. %{count} user(s) are still assigned to this role. Please assign them to another role first."
msgstr ""
#: lib/mv_web/live/role_live/form.ex
#: lib/mv_web/live/role_live/index.ex
#: lib/mv_web/live/role_live/show.ex
#, elixir-autogen, elixir-format
msgid "Role not found."
msgstr ""
#: lib/mv_web/live/role_live/form.ex
#, elixir-autogen, elixir-format, fuzzy
msgid "Role saved successfully."
msgstr ""
#: lib/mv_web/live/role_live/index.ex
#: lib/mv_web/live/role_live/show.ex
#, elixir-autogen, elixir-format, fuzzy
msgid "System roles cannot be deleted."
msgstr ""
#~ #: lib/mv_web/live/components/payment_filter_component.ex
#~ #, elixir-autogen, elixir-format
#~ msgid "All payment statuses"
#~ msgstr ""
#~ #: lib/mv_web/live/custom_field_live/show.ex
#~ #, elixir-autogen, elixir-format
#~ msgstr ""
#~ #: lib/mv_web/live/member_field_live/form_component.ex
#~ #: lib/mv_web/live/member_field_live/index_component.ex
#~ #, elixir-autogen, elixir-format, fuzzy
#~ msgid "String"
#~ msgstr ""
#~ #: lib/mv_web/live/contribution_settings_live.ex
#~ #, elixir-autogen, elixir-format
#~ msgid "Configure global settings for membership contributions."
#~ msgstr ""
#~ #: lib/mv_web/live/global_settings_live.ex
#~ #, elixir-autogen, elixir-format
#~ msgid "Failed to update member field visibility: %{error}"
#~ msgstr ""
#~ #: lib/mv_web/live/member_live/form.ex
#~ #: lib/mv_web/live/member_live/show.ex
#~ #, elixir-autogen, elixir-format
@ -2087,6 +2105,11 @@ msgstr ""
#~ msgid "Failed to save settings. Please check the errors below."
#~ msgstr ""
#~ #: lib/mv_web/live/global_settings_live.ex
#~ #, elixir-autogen, elixir-format
#~ msgid "Failed to update member field visibility: %{error}"
#~ msgstr ""
#~ #: lib/mv_web/live/user_live/index.html.heex
#~ #: lib/mv_web/live/user_live/show.ex
#~ #, elixir-autogen, elixir-format
@ -2112,11 +2135,6 @@ msgstr ""
#~ msgid "Pending"
#~ msgstr ""
#~ #: lib/mv_web/live/custom_field_live/form_component.ex
#~ #, elixir-autogen, elixir-format, fuzzy
#~ msgid "Save Custom Field"
#~ msgstr ""
#~ #: lib/mv_web/live/member_live/form.ex
#~ #: lib/mv_web/live/member_live/show.ex
#~ #: lib/mv_web/translations/member_fields.ex
@ -2134,6 +2152,11 @@ msgstr ""
#~ msgid "Quarterly Interval - Joining Period Excluded"
#~ msgstr ""
#~ #: lib/mv_web/live/custom_field_live/form_component.ex
#~ #, elixir-autogen, elixir-format, fuzzy
#~ msgid "Save Custom Field"
#~ msgstr ""
#~ #: lib/mv_web/live/member_live/index.html.heex
#~ #, elixir-autogen, elixir-format
#~ msgid "Show Last/Current Cycle Payment Status"
@ -2149,6 +2172,12 @@ msgstr ""
#~ msgid "Show last completed cycle"
#~ msgstr ""
#~ #: lib/mv_web/live/member_field_live/form_component.ex
#~ #: lib/mv_web/live/member_field_live/index_component.ex
#~ #, elixir-autogen, elixir-format, fuzzy
#~ msgid "String"
#~ msgstr ""
#~ #: lib/mv_web/live/member_live/index.html.heex
#~ #, elixir-autogen, elixir-format
#~ msgid "Switch to current cycle"

View file

@ -1,106 +0,0 @@
defmodule MvWeb.Layouts.NavbarTest do
use MvWeb.ConnCase, async: true
import Phoenix.LiveViewTest
describe "navbar profile section" do
test "renders profile button with correct attributes", %{conn: _conn} do
# Setup: Create a user
user = create_test_user(%{email: "test@example.com"})
html =
render_component(&MvWeb.Layouts.Navbar.navbar/1, %{
current_user: user
})
# Test dropdown structure
assert html =~ "dropdown-content"
assert html =~ "dropdown-end"
assert html =~ ~s(role="button")
# Test profile link
assert html =~ ~s(href="/users/#{user.id}")
assert html =~ "Profil"
end
@tag :skip
# TODO: Implement user initials in navbar avatar - see issue #170
test "shows user initials in avatar", %{conn: _conn} do
# Setup: Create a user with specific email for testing initials
user = create_test_user(%{email: "test.user@example.com"})
html =
render_component(&MvWeb.Layouts.Navbar.navbar/1, %{
current_user: user
})
# Initials from test.user@example.com
assert html =~ "<span>TU</span>"
end
@tag :skip
# TODO: Implement user initials in navbar avatar - see issue #170
test "shows different initials for OIDC user", %{conn: _conn} do
# Setup: Create OIDC user
user_info = %{
"sub" => "oidc_123",
"preferred_username" => "oidc.user@example.com"
}
oauth_tokens = %{
"access_token" => "test_token",
"id_token" => "test_id_token"
}
user =
Mv.Accounts.User
|> Ash.Changeset.for_create(:register_with_rauthy, %{
user_info: user_info,
oauth_tokens: oauth_tokens
})
|> Ash.create!(domain: Mv.Accounts)
html =
render_component(&MvWeb.Layouts.Navbar.navbar/1, %{
current_user: user
})
# Initials from oidc.user@example.com
assert html =~ "<span>OU</span>"
end
test "includes all required navigation items", %{conn: _conn} do
user = create_test_user(%{email: "test@example.com"})
html =
render_component(&MvWeb.Layouts.Navbar.navbar/1, %{
current_user: user
})
# Check for all required menu items
assert html =~ "Profil"
assert html =~ "Settings"
assert html =~ "Logout"
# Check for correct logout path
assert html =~ ~s(href="/sign-out")
end
test "Settings link navigates to global settings page", %{conn: conn} do
user = create_test_user(%{email: "test@example.com"})
conn = conn_with_oidc_user(conn, user)
html =
render_component(&MvWeb.Layouts.Navbar.navbar/1, %{
current_user: user
})
# Check that Settings link exists and points to /settings
assert html =~ "Settings"
assert html =~ ~s(href="/settings") || html =~ ~s(navigate="/settings")
# Verify the link actually works by navigating to it
{:ok, _view, settings_html} = live(conn, ~p"/settings")
assert settings_html =~ "Club Settings"
end
end
end

View file

@ -143,14 +143,14 @@ defmodule MvWeb.Layouts.SidebarTest do
assert html =~ ~s(href="/users")
# Check for Custom Fields link
assert html =~ ~s(href="/custom_fields")
assert html =~ ~s(href="/custom_field_values")
# Check for Contributions section
assert html =~ ~s(href="/contribution_types")
assert html =~ ~s(href="/contribution_settings")
assert html =~ ~s(href="/membership_fee_settings")
# Check for Settings link (placeholder)
assert html =~ ~s(href="#")
assert html =~ ~s(href="/settings")
end
test "T2.4: renders sidebar with main-sidebar ID" do
@ -183,11 +183,11 @@ defmodule MvWeb.Layouts.SidebarTest do
assert html =~ "hero-user-circle"
# Check for Custom Fields link with icon
assert html =~ ~s(href="/custom_fields")
assert html =~ ~s(href="/custom_field_values")
assert html =~ "hero-rectangle-group"
# Check for Settings link with icon
assert html =~ ~s(href="#")
assert html =~ ~s(href="/settings")
assert html =~ "hero-cog-6-tooth"
# Check for tooltips (data-tip attribute)
@ -203,7 +203,7 @@ defmodule MvWeb.Layouts.SidebarTest do
# Check for contribution links
assert html =~ ~s(href="/contribution_types")
assert html =~ ~s(href="/contribution_settings")
assert html =~ ~s(href="/membership_fee_settings")
end
test "T3.3: renders nested menu with dropdown for collapsed state" do
@ -514,9 +514,9 @@ defmodule MvWeb.Layouts.SidebarTest do
expected_links = [
"/members",
"/users",
"/custom_fields",
"/custom_field_values",
"/contribution_types",
"/contribution_settings",
"/membership_fee_settings",
"/sign-out"
]
@ -641,7 +641,7 @@ defmodule MvWeb.Layouts.SidebarTest do
# Inner_block items rendered
assert html =~ ~s(href="/contribution_types")
assert html =~ ~s(href="/contribution_settings")
assert html =~ ~s(href="/membership_fee_settings")
assert html =~ ~s(role="menu")
end
end
@ -749,7 +749,7 @@ defmodule MvWeb.Layouts.SidebarTest do
# Drawer overlay label for mobile
assert html =~ ~s(for="mobile-drawer")
assert html =~ ~s(class="drawer-overlay")
assert has_class?(html, "drawer-overlay")
assert html =~ ~s(lg:hidden)
end
end

View file

@ -33,7 +33,7 @@ defmodule MvWeb.ProfileNavigationTest do
end
end
describe "navbar" do
describe "sidebar" do
test "renders profile button with correct attributes", %{conn: conn} do
# Setup: Create and login a user
user = create_test_user(%{email: "test@example.com"})
@ -167,8 +167,8 @@ defmodule MvWeb.ProfileNavigationTest do
test "layout shows user data on user profile page", %{conn: conn, user: user} do
{:ok, _view, html} = live(conn, ~p"/users/#{user.id}")
# The navbar (which requires current_user) should be visible
assert html =~ "navbar"
# The sidebar (which requires current_user) should be visible
assert html =~ "sidebar"
# Profile button should be visible
assert html =~ "Profil"
# User ID should be in profile link