Files
scrum-poker-internal/tests/Feature/EmbeddedRoomTest.php
T
Twyco 4dfe79ce5c
CI/CD / test_and_check_app (push) Successful in 2m19s
CI/CD / Publish immutable image (push) Successful in 1m16s
kick forever
2026-09-24 14:38:18 +02:00

247 lines
7.8 KiB
PHP

<?php
use App\Enums\RoomStateChange;
use App\Events\RoomStateChanged;
use App\Models\Room;
use App\Models\User;
use Illuminate\Support\Facades\Event;
use Inertia\Testing\AssertableInertia as Assert;
function createEmbeddedRoom(array $attributes = []): Room
{
return Room::create([
'title' => 'Fillibri Planning',
'deck_config' => [
'name' => 'Fibonacci',
'cards' => [
['key' => '3', 'label' => '3'],
['key' => '5', 'label' => '5'],
],
],
...$attributes,
]);
}
test('a guest automatically joins the embedded room', function () {
$room = createEmbeddedRoom();
$response = $this->get(route('embedded.room', [
'join_code' => strtolower($room->join_code),
'player_name' => ' Nico ',
]))
->assertOk()
->assertInertia(fn (Assert $page) => $page
->component('embedded/Room')
->where('room.id', $room->id)
->where('currentPlayer.name', 'Nico'));
$player = $room->players()->sole();
expect($player->user_id)->toBeNull()
->and($player->is_moderator)->toBeFalse();
$response->assertSessionHas("room_players.{$room->id}", $player->id);
});
test('embedded guest access reuses the session player and applies a changed display name', function () {
$room = createEmbeddedRoom();
$player = $room->players()->create([
'name' => 'Old name',
]);
$this->withSession(["room_players.{$room->id}" => $player->id])
->get(route('embedded.room', [
'join_code' => $room->join_code,
'player_name' => 'New name',
]))
->assertOk();
expect($room->players()->count())->toBe(1)
->and($player->fresh()->name)->toBe('New name');
});
test('an authenticated user automatically joins the embedded room', function () {
$user = User::factory()->create();
$room = createEmbeddedRoom(['allow_participants_to_manage_rounds' => true]);
$this->actingAs($user)
->get(route('embedded.room', [
'join_code' => strtolower($room->join_code),
'player_name' => ' Nico ',
]))
->assertOk()
->assertInertia(fn (Assert $page) => $page
->component('embedded/Room')
->where('room.id', $room->id)
->where('room.allow_participants_to_manage_rounds', true)
->where('currentPlayer.name', 'Nico'))
->assertSessionHas("room_players.{$room->id}");
$this->assertDatabaseHas('players', [
'room_id' => $room->id,
'user_id' => $user->id,
'name' => 'Nico',
'is_moderator' => false,
]);
});
test('embedded access reuses the user player and applies a changed display name', function () {
$user = User::factory()->create();
$room = createEmbeddedRoom();
$player = $room->players()->create([
'user_id' => $user->id,
'name' => 'Old name',
]);
$this->actingAs($user)
->get(route('embedded.room', [
'join_code' => $room->join_code,
'player_name' => 'New name',
]))
->assertOk();
expect($room->players()->count())->toBe(1)
->and($player->fresh()->name)->toBe('New name');
});
test('an embedded guest keeps the same player after logging in separately', function () {
$user = User::factory()->create([
'email' => 'nico@example.com',
]);
$room = createEmbeddedRoom();
$url = route('embedded.room', [
'join_code' => $room->join_code,
'player_name' => 'Nico',
]);
$this->get($url)->assertOk();
$player = $room->players()->sole();
$this->post(route('login.store'), [
'email' => 'nico@example.com',
'password' => 'password',
])->assertRedirect();
$this->get($url)->assertOk();
expect($room->players()->count())->toBe(1)
->and($player->fresh()->user_id)->toBe($user->id);
});
test('embedded guest access shows a dedicated error when the display name is taken', function () {
$user = User::factory()->create([
'email' => 'nico@example.com',
]);
$room = createEmbeddedRoom();
$room->players()->create([
'user_id' => $user->id,
'name' => 'Nico',
]);
$url = route('embedded.room', [
'join_code' => $room->join_code,
'player_name' => 'Nico',
]);
$this->get($url)
->assertUnprocessable()
->assertInertia(fn (Assert $page) => $page
->component('embedded/Error')
->where('message', 'Dieser Anzeigename ist in dem Raum bereits vorhanden.')
->where('showLoginAction', true))
->assertSessionHas('url.intended', $url);
$this->post(route('login.store'), [
'email' => 'nico@example.com',
'password' => 'password',
])->assertRedirect($url);
$this->get($url)
->assertOk()
->assertInertia(fn (Assert $page) => $page
->component('embedded/Room')
->where('currentPlayer.name', 'Nico'));
});
test('a new account instance takes over the embedded player and kicks the previous instance', function () {
Event::fake([RoomStateChanged::class]);
$user = User::factory()->create();
$room = createEmbeddedRoom();
$player = $room->players()->create([
'user_id' => $user->id,
'name' => 'Nico',
'active_instance_id' => '019b8f80-37c4-71a3-b415-5f2697332c16',
]);
$url = route('embedded.room', [
'join_code' => $room->join_code,
'player_name' => 'Nico',
]);
$this->actingAs($user)
->withSession([
'room_player_instance_id' => '019b8f80-37c4-71a3-b415-5f2697332c17',
])
->get($url)
->assertOk()
->assertInertia(fn (Assert $page) => $page
->where('currentPlayer.id', $player->id)
->where('currentPlayer.instance_id', '019b8f80-37c4-71a3-b415-5f2697332c17'));
expect($player->fresh()->active_instance_id)
->toBe('019b8f80-37c4-71a3-b415-5f2697332c17');
Event::assertDispatched(
RoomStateChanged::class,
fn (RoomStateChanged $event): bool => $event->change === RoomStateChange::PlayerInstanceReplaced
&& $event->affectedPlayerId === $player->id
&& $event->affectedInstanceId === '019b8f80-37c4-71a3-b415-5f2697332c16',
);
$this->withSession([
"room_players.{$room->id}" => $player->id,
'room_player_instance_id' => '019b8f80-37c4-71a3-b415-5f2697332c16',
])
->post(route('room.vote.store', $room), ['value' => '5'])
->assertRedirect(route('room.join', ['join_code' => $room->join_code]));
$this->assertDatabaseCount('votes', 0);
});
test('embedded access shows a dedicated error for an unknown room code', function () {
$this->get(route('embedded.room', [
'join_code' => 'ABC234',
'player_name' => 'Nico',
]))
->assertUnprocessable()
->assertInertia(fn (Assert $page) => $page
->component('embedded/Error')
->where('message', 'Dieser Raumcode existiert nicht.')
->where('showLoginAction', false));
});
test('embedded logout returns to the same room as a guest without duplicating the player', function () {
$user = User::factory()->create();
$room = createEmbeddedRoom();
$url = route('embedded.room', [
'join_code' => $room->join_code,
'player_name' => 'Nico',
]);
$this->actingAs($user)->get($url)->assertOk();
$player = $room->players()->sole();
$this
->followingRedirects()
->post(route('embedded.logout', [
'join_code' => $room->join_code,
'player_name' => 'Nico',
]))
->assertOk()
->assertInertia(fn (Assert $page) => $page
->component('embedded/Room')
->where('currentPlayer.id', $player->id));
$this->assertGuest()
->assertDatabaseCount('players', 1);
});