mirror of
https://github.com/ericasch6/scrum-poker-internal.git
synced 2026-10-13 21:12:10 +00:00
Added inern app integration
This commit is contained in:
@@ -0,0 +1,129 @@
|
||||
<?php
|
||||
|
||||
use App\Models\Room;
|
||||
use App\Models\User;
|
||||
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('embedded room access sends guests through login and remembers the intended room', function () {
|
||||
$room = createEmbeddedRoom();
|
||||
$url = route('embedded.room', [
|
||||
'join_code' => $room->join_code,
|
||||
'player_name' => 'Nico',
|
||||
]);
|
||||
|
||||
$this->get($url)
|
||||
->assertRedirect(route('login'))
|
||||
->assertSessionHas('embedded_login', true)
|
||||
->assertSessionHas('url.intended', $url);
|
||||
|
||||
$this->get(route('login'))
|
||||
->assertInertia(fn (Assert $page) => $page
|
||||
->component('auth/Login')
|
||||
->where('rememberByDefault', true));
|
||||
});
|
||||
|
||||
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',
|
||||
'inactive_at' => now(),
|
||||
]);
|
||||
|
||||
$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')
|
||||
->and($player->fresh()->inactive_at)->toBeNull();
|
||||
});
|
||||
|
||||
test('embedded access shows a dedicated error when the display name is taken', function () {
|
||||
$user = User::factory()->create();
|
||||
$room = createEmbeddedRoom();
|
||||
$room->players()->create(['name' => 'Nico']);
|
||||
|
||||
$this->actingAs($user)
|
||||
->get(route('embedded.room', [
|
||||
'join_code' => $room->join_code,
|
||||
'player_name' => 'Nico',
|
||||
]))
|
||||
->assertUnprocessable()
|
||||
->assertInertia(fn (Assert $page) => $page
|
||||
->component('embedded/Error')
|
||||
->where('message', 'Dieser Anzeigename ist in dem Raum bereits vorhanden.'));
|
||||
});
|
||||
|
||||
test('embedded access shows a dedicated error for an unknown room code', function () {
|
||||
$this->actingAs(User::factory()->create())
|
||||
->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.'));
|
||||
});
|
||||
|
||||
test('embedded logout returns to the same configured room and signs the user out', function () {
|
||||
$user = User::factory()->create();
|
||||
$room = createEmbeddedRoom();
|
||||
|
||||
$this->actingAs($user)
|
||||
->post(route('embedded.logout', [
|
||||
'join_code' => $room->join_code,
|
||||
'player_name' => 'Nico',
|
||||
]))
|
||||
->assertRedirect(route('embedded.room', [
|
||||
'join_code' => $room->join_code,
|
||||
'player_name' => 'Nico',
|
||||
]));
|
||||
|
||||
$this->assertGuest();
|
||||
});
|
||||
@@ -0,0 +1,158 @@
|
||||
<?php
|
||||
|
||||
use App\Enums\RoomStateChange;
|
||||
use App\Events\RoomStateChanged;
|
||||
use App\Jobs\CloseInactiveRooms;
|
||||
use App\Models\Room;
|
||||
use App\Models\User;
|
||||
use Illuminate\Support\Facades\Event;
|
||||
use Inertia\Testing\AssertableInertia as Assert;
|
||||
|
||||
function createSettingsRoom(array $attributes = []): Room
|
||||
{
|
||||
return Room::create([
|
||||
'title' => 'Teamraum',
|
||||
'deck_config' => [
|
||||
'name' => 'Fibonacci',
|
||||
'cards' => [
|
||||
['key' => '3', 'label' => '3'],
|
||||
['key' => '5', 'label' => '5'],
|
||||
],
|
||||
],
|
||||
...$attributes,
|
||||
]);
|
||||
}
|
||||
|
||||
test('room settings default to moderator control and normal retention', function () {
|
||||
$room = createSettingsRoom();
|
||||
|
||||
expect($room->allow_participants_to_manage_rounds)->toBeFalse()
|
||||
->and($room->is_persistent)->toBeFalse();
|
||||
});
|
||||
|
||||
test('the owner can view and update room settings', function () {
|
||||
$owner = User::factory()->create();
|
||||
$room = createSettingsRoom(['owner_id' => $owner->id]);
|
||||
|
||||
$this->actingAs($owner)
|
||||
->get(route('room.settings.edit', $room))
|
||||
->assertInertia(fn (Assert $page) => $page
|
||||
->component('rooms/Settings')
|
||||
->where('room.id', $room->id)
|
||||
->where('room.allow_participants_to_manage_rounds', false)
|
||||
->where('room.is_persistent', false));
|
||||
|
||||
Event::fake();
|
||||
|
||||
$this->actingAs($owner)
|
||||
->patch(route('room.settings.update', $room), [
|
||||
'allow_participants_to_manage_rounds' => true,
|
||||
'is_persistent' => true,
|
||||
])
|
||||
->assertRedirect();
|
||||
|
||||
$room->refresh();
|
||||
|
||||
expect($room->allow_participants_to_manage_rounds)->toBeTrue()
|
||||
->and($room->is_persistent)->toBeTrue()
|
||||
->and($room->state_version)->toBe(2);
|
||||
|
||||
Event::assertDispatched(
|
||||
RoomStateChanged::class,
|
||||
fn (RoomStateChanged $event): bool => $event->change === RoomStateChange::RoomSettingsUpdated
|
||||
&& $event->state['allow_participants_to_manage_rounds'] === true,
|
||||
);
|
||||
});
|
||||
|
||||
test('a user who does not own a room cannot manage its settings', function () {
|
||||
$owner = User::factory()->create();
|
||||
$otherUser = User::factory()->create();
|
||||
$room = createSettingsRoom(['owner_id' => $owner->id]);
|
||||
|
||||
$this->actingAs($otherUser)
|
||||
->get(route('room.settings.edit', $room))
|
||||
->assertForbidden();
|
||||
|
||||
$this->actingAs($otherUser)
|
||||
->patch(route('room.settings.update', $room), [
|
||||
'allow_participants_to_manage_rounds' => true,
|
||||
'is_persistent' => true,
|
||||
])
|
||||
->assertForbidden();
|
||||
|
||||
expect($room->fresh()->allow_participants_to_manage_rounds)->toBeFalse();
|
||||
});
|
||||
|
||||
test('all active participants can manage rounds when the room setting is enabled', function () {
|
||||
$room = createSettingsRoom(['allow_participants_to_manage_rounds' => true]);
|
||||
$player = $room->players()->create([
|
||||
'name' => 'Anna',
|
||||
'is_moderator' => false,
|
||||
]);
|
||||
|
||||
$this->withSession(["room_players.{$room->id}" => $player->id])
|
||||
->post(route('room.reveal', $room))
|
||||
->assertNoContent();
|
||||
|
||||
expect($room->fresh()->revealed_at)->not->toBeNull();
|
||||
});
|
||||
|
||||
test('normal participants remain unable to manage rounds when the setting is disabled', function () {
|
||||
$room = createSettingsRoom();
|
||||
$player = $room->players()->create([
|
||||
'name' => 'Anna',
|
||||
'is_moderator' => false,
|
||||
]);
|
||||
|
||||
$this->withSession(["room_players.{$room->id}" => $player->id])
|
||||
->post(route('room.reveal', $room))
|
||||
->assertForbidden();
|
||||
});
|
||||
|
||||
test('persistent rooms are excluded from automatic closing', function () {
|
||||
$persistentRoom = createSettingsRoom([
|
||||
'owner_id' => User::factory()->create()->id,
|
||||
'is_persistent' => true,
|
||||
'last_activity_at' => now()->subDays(60),
|
||||
]);
|
||||
$expiringRoom = createSettingsRoom([
|
||||
'owner_id' => User::factory()->create()->id,
|
||||
'last_activity_at' => now()->subDays(60),
|
||||
]);
|
||||
|
||||
(new CloseInactiveRooms)->handle();
|
||||
|
||||
expect($persistentRoom->fresh()->closed_at)->toBeNull()
|
||||
->and($expiringRoom->fresh()->closed_at)->not->toBeNull();
|
||||
});
|
||||
|
||||
test('room settings broadcasts never expose hidden vote values', function () {
|
||||
$owner = User::factory()->create();
|
||||
$room = createSettingsRoom(['owner_id' => $owner->id]);
|
||||
$player = $room->players()->create([
|
||||
'name' => 'Anna',
|
||||
'is_moderator' => false,
|
||||
]);
|
||||
$player->votes()->create([
|
||||
'room_id' => $room->id,
|
||||
'round' => 1,
|
||||
'value' => '5',
|
||||
]);
|
||||
|
||||
Event::fake();
|
||||
|
||||
$this->actingAs($owner)->patch(route('room.settings.update', $room), [
|
||||
'allow_participants_to_manage_rounds' => true,
|
||||
'is_persistent' => false,
|
||||
]);
|
||||
|
||||
Event::assertDispatched(
|
||||
RoomStateChanged::class,
|
||||
function (RoomStateChanged $event) use ($player): bool {
|
||||
$broadcastPlayer = collect($event->state['players'])->firstWhere('id', $player->id);
|
||||
|
||||
return $broadcastPlayer['has_voted'] === true
|
||||
&& $broadcastPlayer['vote'] === null;
|
||||
},
|
||||
);
|
||||
});
|
||||
Reference in New Issue
Block a user