diff --git a/.gitignore b/.gitignore index 46c29ee..cc251e1 100644 --- a/.gitignore +++ b/.gitignore @@ -23,3 +23,5 @@ yarn-error.log /.sisyphus /.opencode .switch-omo-config* +/.playwright-mcp +/*.png diff --git a/.playwright-mcp/console-2026-02-12T21-59-30-399Z.log b/.playwright-mcp/console-2026-02-12T21-59-30-399Z.log new file mode 100644 index 0000000..c2763a2 --- /dev/null +++ b/.playwright-mcp/console-2026-02-12T21-59-30-399Z.log @@ -0,0 +1,3 @@ +[ 3014ms] [ERROR] Access to font at 'http://localhost/storage/fonts/440f07d668/sinconsolatav37qlddnthlqrwh-oj1uhjlkenvzkwgvkl3gzqmawlyya15idhuna.woff2' from origin 'http://127.0.0.1:8321' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. @ http://127.0.0.1:8321/association/news:654 +[ 3015ms] [ERROR] Failed to load resource: net::ERR_FAILED @ http://localhost/storage/fonts/440f07d668/sinconsolatav37qlddnthlqrwh-oj1uhjlkenvzkwgvkl3gzqmawlyya15idhuna.woff2:0 +[ 3126ms] [ERROR] Failed to load resource: net::ERR_CONNECTION_CLOSED @ https://127.0.0.1:8321/favicon.ico:0 diff --git a/resources/views/livewire/association/news.blade.php b/resources/views/livewire/association/news.blade.php index fd880da..25ed66e 100644 --- a/resources/views/livewire/association/news.blade.php +++ b/resources/views/livewire/association/news.blade.php @@ -142,291 +142,233 @@ class extends Component {
@if($isAllowed) -
+
- -
+ +
+ +
+ News +
- -
-
-
+ +
+ + Alle + + @foreach(\App\Enums\NewsCategory::selectOptions() as $category) + + + {{ $category['label'] }} + + @endforeach +
-
- - -
-

- News -

-
- -
- - -
- -
-
- Kategorien -
-
    -
  • - -
  • - @foreach(\App\Enums\NewsCategory::selectOptions() as $category) -
  • - -
  • - @endforeach -
+ +
+ @forelse($this->filteredNews as $post) + + +
+ +
+
+ + {{ $post->einundzwanzigPleb?->profile?->name ?? str($post->einundzwanzigPleb?->npub)->limit(32) }} + + + {{ $post->created_at->format('d.m.Y') }} +
+ + + {{ $post->category->label() }} +
-
-
- -
-
- -
- @forelse($this->filteredNews as $post) - - -
- {{ $post->einundzwanzigPleb->profile?->name }} -
- -
- -
- -
- -

- {{ $post->name }} -

-

- {{ $post->description }} -

- -
-
-
-
- - - - {{ $post->einundzwanzigPleb?->profile?->name ?? str($post->einundzwanzigPleb?->npub)->limit(32) }} -
-
-
-
- {{ $post->created_at->format('d.m.Y') }} -
-
-
-
- @if($post->getFirstMedia('pdf')) - - Öffnen - - @endif - @if($canEdit) - - - Löschen - - - - -
-
- News löschen? - - Du bist dabei, diese News zu löschen.
- Diese Aktion kann nicht rückgängig gemacht werden. -
-
-
- - - Abbrechen - - Löschen -
-
-
- @endif -
-
- @empty - - @if($selectedCategory !== null) -

Keine News in dieser Kategorie vorhanden.

- - Alle anzeigen - - @else -

Keine News vorhanden.

- @endif -
- @endforelse -
- -
-
- -
- - -
-
-
- - -
- - @if($canEdit) - -
- News anlegen -
-
- - - - @error('file') - {{ $message }} - @enderror -
- @if ($file) - - - - - - @endif -
-
- - Kategorie - - @foreach(\App\Enums\NewsCategory::selectOptions() as $category) - - @endforeach - - - -
-
- - Titel - - - -
-
- - Beschreibung - optional - - - -
- - Hinzufügen - -
-
+ +
+ {{ $post->name }} + @if($post->description) + {{ $post->description }} @endif -
-
+ + +
+ @if($post->getFirstMedia('pdf')) + + PDF öffnen + + @endif + @if($canEdit) + + + + Löschen + + + + +
+
+ News löschen? + + Du bist dabei, diese News zu löschen.
+ Diese Aktion kann nicht rückgängig gemacht werden. +
+
+
+ + + Abbrechen + + Löschen +
+
+
+ @endif +
+ + @empty + +
+ @if($selectedCategory !== null) + + Keine News in dieser Kategorie + Versuche eine andere Kategorie oder zeige alle an. + + Alle anzeigen + + @else + + Noch keine News vorhanden + Hier werden zukünftige Neuigkeiten angezeigt. + @endif +
+
+ @endforelse +
+
+ + + @if($canEdit) +
+
+ + News anlegen + + + + + + + + @if ($file) + + + + + + @endif + + + Kategorie + + @foreach(\App\Enums\NewsCategory::selectOptions() as $category) + + @endforeach + + + + + + Titel + + + + + + Beschreibung + optional + + + + + + Hinzufügen + +
+ @endif -
+
@else -
+
- Zugriff auf News nicht möglich -

Um die News einzusehen, benötigst du:

-
    -
  • Einen Vereinsstatus von "Aktives Mitglied"
  • -
  • Eine bezahlte Mitgliedschaft für das aktuelle Jahr ({{ date('Y') }})
  • -
-

- @if(!NostrAuth::check()) - Bitte melde dich zunächst mit Nostr an. - @else - Bitte kontaktiere den Vorstand, wenn du denkst, dass du berechtigt sein solltest. - @endif -

+ Zugriff auf News nicht möglich + +

Um die News einzusehen, benötigst du:

+
    +
  • Einen Vereinsstatus von "Aktives Mitglied"
  • +
  • Eine bezahlte Mitgliedschaft für das aktuelle Jahr ({{ date('Y') }})
  • +
+

+ @if(!NostrAuth::check()) + Bitte melde dich zunächst mit Nostr an. + @else + Bitte kontaktiere den Vorstand, wenn du denkst, dass du berechtigt sein solltest. + @endif +

+
@endif diff --git a/tests/Feature/Livewire/Association/NewsTest.php b/tests/Feature/Livewire/Association/NewsTest.php index dea4f76..517a803 100644 --- a/tests/Feature/Livewire/Association/NewsTest.php +++ b/tests/Feature/Livewire/Association/NewsTest.php @@ -112,3 +112,103 @@ it('displays news list', function () { ->assertSee($news1->name) ->assertSee($news2->name); }); + +it('shows warning callout when access is denied', function () { + $pleb = EinundzwanzigPleb::factory()->create([ + 'association_status' => AssociationStatus::PASSIVE, + ]); + + NostrAuth::login($pleb->pubkey); + + Livewire::test('association.news') + ->assertSet('isAllowed', false) + ->assertSee('Zugriff auf News nicht möglich') + ->assertSee('Aktives Mitglied'); +}); + +it('shows nostr login hint when not authenticated', function () { + Livewire::test('association.news') + ->assertSet('isAllowed', false) + ->assertSee('Bitte melde dich zunächst mit Nostr an'); +}); + +it('displays category badges as filters', function () { + $pleb = EinundzwanzigPleb::factory()->active()->withPaidCurrentYear()->create(); + + NostrAuth::login($pleb->pubkey); + + Livewire::test('association.news') + ->assertSee('Alle') + ->assertSee('Einundzwanzig') + ->assertSee('Allgemeines') + ->assertSee('Organisation'); +}); + +it('filters news by category', function () { + $pleb = EinundzwanzigPleb::factory()->active()->withPaidCurrentYear()->create(); + $newsOrg = Notification::factory()->create(['category' => NewsCategory::Organisation]); + $newsBtc = Notification::factory()->create(['category' => NewsCategory::Bitcoin]); + + NostrAuth::login($pleb->pubkey); + + Livewire::test('association.news') + ->assertSee($newsOrg->name) + ->assertSee($newsBtc->name) + ->call('filterByCategory', NewsCategory::Organisation->value) + ->assertSee($newsOrg->name) + ->assertDontSee($newsBtc->name); +}); + +it('shows empty state when no news exist', function () { + $pleb = EinundzwanzigPleb::factory()->active()->withPaidCurrentYear()->create(); + + NostrAuth::login($pleb->pubkey); + + Livewire::test('association.news') + ->assertSee('Noch keine News vorhanden'); +}); + +it('shows filtered empty state with clear button', function () { + $pleb = EinundzwanzigPleb::factory()->active()->withPaidCurrentYear()->create(); + + NostrAuth::login($pleb->pubkey); + + Livewire::test('association.news') + ->call('filterByCategory', NewsCategory::Bildung->value) + ->assertSee('Keine News in dieser Kategorie') + ->assertSee('Alle anzeigen'); +}); + +it('displays news card with author name and date', function () { + $pleb = EinundzwanzigPleb::factory()->active()->withPaidCurrentYear()->create(); + $news = Notification::factory()->create([ + 'name' => 'Wichtige Neuigkeiten', + 'description' => 'Hier steht die Beschreibung', + ]); + + NostrAuth::login($pleb->pubkey); + + Livewire::test('association.news') + ->assertSee('Wichtige Neuigkeiten') + ->assertSee('Hier steht die Beschreibung') + ->assertSee($news->created_at->format('d.m.Y')); +}); + +it('shows create form only for board members', function () { + $pleb = EinundzwanzigPleb::factory()->active()->withPaidCurrentYear()->create(); + + NostrAuth::login($pleb->pubkey); + + Livewire::test('association.news') + ->assertDontSee('News anlegen'); +}); + +it('displays create form for board members', function () { + $pleb = EinundzwanzigPleb::factory()->boardMember()->withPaidCurrentYear()->create(); + + NostrAuth::login($pleb->pubkey); + + Livewire::test('association.news') + ->assertSee('News anlegen') + ->assertSee('Hinzufügen'); +});