Files
einundzwanzig-app/tests/Feature/Api/MeetupEventRsvpApiTest.php
HolgerHatGarKeineNode 0a1d177fc4 Add RSVP functionality for Meetup Events
- 🏷️ Introduce `RsvpStatus` enum for managing attendance states (`attending`, `maybe`, `none`).
- ✏️ Add `MeetupEventController` methods for RSVP actions (`rsvpStatus`, `rsvp`) and payload handling.
-  Implement RSVP helpers in `MeetupEvent` model for user-specific attendance management.
- 🌐 Register RSVP routes for showing and updating attendance in the API.
- 🧪 Add feature tests for RSVP actions, covering validation, idempotency, and correct list handling.
2026-06-15 22:10:10 +02:00

85 lines
3.2 KiB
PHP

<?php
use App\Models\MeetupEvent;
use App\Models\User;
use Laravel\Sanctum\Sanctum;
it('rejects a guest', function () {
$event = MeetupEvent::factory()->create();
$this->postJson("/api/meetup-events/{$event->id}/rsvp", ['status' => 'attending'])
->assertUnauthorized();
});
it('lets an authenticated user attend', function () {
Sanctum::actingAs($user = User::factory()->create(['name' => 'Satoshi']));
$event = MeetupEvent::factory()->create();
$this->postJson("/api/meetup-events/{$event->id}/rsvp", ['status' => 'attending'])
->assertSuccessful()
->assertJson(['status' => 'attending', 'attendees' => 1, 'might_attendees' => 0]);
expect($event->fresh()->attendees)->toBe(["id_{$user->id}|Satoshi"]);
});
it('moves the user between lists without duplicating', function () {
Sanctum::actingAs($user = User::factory()->create(['name' => 'Satoshi']));
$event = MeetupEvent::factory()->create();
$this->postJson("/api/meetup-events/{$event->id}/rsvp", ['status' => 'attending']);
$this->postJson("/api/meetup-events/{$event->id}/rsvp", ['status' => 'maybe'])
->assertJson(['status' => 'maybe', 'attendees' => 0, 'might_attendees' => 1]);
$event->refresh();
expect($event->attendees)->toBe([])
->and($event->might_attendees)->toBe(["id_{$user->id}|Satoshi"]);
});
it('withdraws the user with status none', function () {
Sanctum::actingAs($user = User::factory()->create(['name' => 'Satoshi']));
$event = MeetupEvent::factory()->create();
$this->postJson("/api/meetup-events/{$event->id}/rsvp", ['status' => 'attending']);
$this->postJson("/api/meetup-events/{$event->id}/rsvp", ['status' => 'none'])
->assertJson(['status' => 'none', 'attendees' => 0, 'might_attendees' => 0]);
expect($event->fresh()->attendees)->toBe([]);
});
it('keeps other attendees untouched', function () {
$event = MeetupEvent::factory()->create([
'attendees' => ['id_999|Hal', 'id_50|Nick'],
]);
Sanctum::actingAs($user = User::factory()->create(['name' => 'Satoshi']));
// id_5 darf id_50 nicht versehentlich treffen (Prefix-Abgrenzung per Pipe).
$this->postJson("/api/meetup-events/{$event->id}/rsvp", ['status' => 'attending'])
->assertJson(['attendees' => 3]);
expect($event->fresh()->attendees)
->toContain('id_999|Hal')
->toContain('id_50|Nick')
->toContain("id_{$user->id}|Satoshi");
});
it('reports the current status and counts', function () {
Sanctum::actingAs($user = User::factory()->create(['name' => 'Satoshi']));
$event = MeetupEvent::factory()->create([
'attendees' => ['id_999|Hal'],
'might_attendees' => ["id_{$user->id}|Satoshi"],
]);
$this->getJson("/api/meetup-events/{$event->id}/rsvp")
->assertSuccessful()
->assertJson(['status' => 'maybe', 'attendees' => 1, 'might_attendees' => 1]);
});
it('validates the status value', function () {
Sanctum::actingAs(User::factory()->create());
$event = MeetupEvent::factory()->create();
$this->postJson("/api/meetup-events/{$event->id}/rsvp", ['status' => 'bogus'])
->assertUnprocessable()
->assertJsonValidationErrors(['status']);
});