mirror of
https://github.com/ericasch6/scrum-poker-internal.git
synced 2026-10-13 17:32:09 +00:00
211 lines
6.1 KiB
PHP
211 lines
6.1 KiB
PHP
<?php
|
|
|
|
use App\Models\Room;
|
|
use App\Models\Vote;
|
|
use Inertia\Testing\AssertableInertia as Assert;
|
|
|
|
function createVotingRoom(): array
|
|
{
|
|
$room = Room::create([
|
|
'title' => 'Sprint Planning',
|
|
'deck_config' => [
|
|
'name' => 'Fibonacci',
|
|
'cards' => [
|
|
['key' => '3', 'label' => '3'],
|
|
['key' => '5', 'label' => '5'],
|
|
['key' => '8', 'label' => '8'],
|
|
],
|
|
],
|
|
]);
|
|
|
|
$moderator = $room->players()->create([
|
|
'name' => 'Eric',
|
|
'is_moderator' => true,
|
|
]);
|
|
|
|
$player = $room->players()->create([
|
|
'name' => 'Anna',
|
|
'is_moderator' => false,
|
|
]);
|
|
|
|
return [$room, $moderator, $player];
|
|
}
|
|
|
|
test('a participant can vote and change their vote in the current round', function () {
|
|
[$room, $moderator] = createVotingRoom();
|
|
$room->update(['last_activity_at' => now()->subDay()]);
|
|
$previousActivity = $room->last_activity_at;
|
|
|
|
$session = ["room_players.{$room->id}" => $moderator->id];
|
|
|
|
$this->withSession($session)
|
|
->post(route('room.vote.store', $room), ['value' => '5'])
|
|
->assertRedirect();
|
|
|
|
$this->assertDatabaseHas('votes', [
|
|
'room_id' => $room->id,
|
|
'player_id' => $moderator->id,
|
|
'round' => 1,
|
|
'value' => '5',
|
|
]);
|
|
|
|
$this->withSession($session)
|
|
->post(route('room.vote.store', $room), ['value' => '8'])
|
|
->assertRedirect();
|
|
|
|
expect(Vote::query()->count())->toBe(1);
|
|
expect(Vote::query()->value('value'))->toBe('8')
|
|
->and($room->fresh()->last_activity_at->greaterThan($previousActivity))->toBeTrue();
|
|
});
|
|
|
|
test('a participant cannot vote with a card outside the room deck', function () {
|
|
[$room, $moderator] = createVotingRoom();
|
|
|
|
$this->withSession(["room_players.{$room->id}" => $moderator->id])
|
|
->post(route('room.vote.store', $room), ['value' => '100'])
|
|
->assertSessionHasErrors('value');
|
|
|
|
$this->assertDatabaseCount('votes', 0);
|
|
});
|
|
|
|
test('other votes stay hidden until the moderator reveals the round', function () {
|
|
[$room, $moderator, $player] = createVotingRoom();
|
|
$room->update(['last_activity_at' => now()->subDay()]);
|
|
$previousActivity = $room->last_activity_at;
|
|
|
|
$player->votes()->create([
|
|
'room_id' => $room->id,
|
|
'round' => 1,
|
|
'value' => '8',
|
|
]);
|
|
|
|
$session = ["room_players.{$room->id}" => $moderator->id];
|
|
|
|
$this->withSession($session)
|
|
->get(route('room.show', $room))
|
|
->assertInertia(fn (Assert $page) => $page
|
|
->component('rooms/Show')
|
|
->where('room.revealed', false)
|
|
->where('room.players.1.has_voted', true)
|
|
->where('room.players.1.vote', null));
|
|
|
|
$this->withSession($session)
|
|
->post(route('room.reveal', $room))
|
|
->assertRedirect();
|
|
|
|
expect($room->fresh()->last_activity_at->greaterThan($previousActivity))->toBeTrue();
|
|
|
|
$this->withSession($session)
|
|
->get(route('room.show', $room))
|
|
->assertInertia(fn (Assert $page) => $page
|
|
->where('room.revealed', true)
|
|
->where('room.players.1.vote', '8'));
|
|
});
|
|
|
|
test('only the moderator may reveal cards', function () {
|
|
[$room, , $player] = createVotingRoom();
|
|
|
|
$this->withSession(["room_players.{$room->id}" => $player->id])
|
|
->post(route('room.reveal', $room))
|
|
->assertForbidden();
|
|
|
|
expect($room->fresh()->revealed_at)->toBeNull();
|
|
});
|
|
|
|
test('starting the next round clears the revealed state', function () {
|
|
[$room, $moderator] = createVotingRoom();
|
|
|
|
$room->update([
|
|
'revealed_at' => now(),
|
|
'last_activity_at' => now()->subDay(),
|
|
]);
|
|
$previousActivity = $room->last_activity_at;
|
|
|
|
$this->withSession(["room_players.{$room->id}" => $moderator->id])
|
|
->post(route('room.next-round', $room))
|
|
->assertRedirect();
|
|
|
|
$room->refresh();
|
|
|
|
expect($room->current_round)->toBe(2)
|
|
->and($room->revealed_at)->toBeNull()
|
|
->and($room->last_activity_at->greaterThan($previousActivity))->toBeTrue();
|
|
});
|
|
|
|
test('the moderator can reset only the votes from the current round', function () {
|
|
[$room, $moderator, $player] = createVotingRoom();
|
|
|
|
$room->update([
|
|
'current_round' => 2,
|
|
'revealed_at' => now(),
|
|
'last_activity_at' => now()->subDay(),
|
|
]);
|
|
$previousActivity = $room->last_activity_at;
|
|
|
|
$player->votes()->create([
|
|
'room_id' => $room->id,
|
|
'round' => 1,
|
|
'value' => '3',
|
|
]);
|
|
|
|
$player->votes()->create([
|
|
'room_id' => $room->id,
|
|
'round' => 2,
|
|
'value' => '8',
|
|
]);
|
|
|
|
$this->withSession(["room_players.{$room->id}" => $moderator->id])
|
|
->post(route('room.reset', $room))
|
|
->assertRedirect();
|
|
|
|
$this->assertDatabaseHas('votes', [
|
|
'room_id' => $room->id,
|
|
'player_id' => $player->id,
|
|
'round' => 1,
|
|
'value' => '3',
|
|
]);
|
|
|
|
$this->assertDatabaseMissing('votes', [
|
|
'room_id' => $room->id,
|
|
'round' => 2,
|
|
]);
|
|
|
|
$room->refresh();
|
|
|
|
expect($room->revealed_at)->toBeNull()
|
|
->and($room->last_activity_at->greaterThan($previousActivity))->toBeTrue();
|
|
});
|
|
|
|
test('revealed rounds show the average and median of numeric votes', function () {
|
|
[$room, $moderator, $player] = createVotingRoom();
|
|
$thirdPlayer = $room->players()->create([
|
|
'name' => 'Nina',
|
|
'is_moderator' => false,
|
|
]);
|
|
$nonNumericPlayer = $room->players()->create([
|
|
'name' => 'Coffee',
|
|
'is_moderator' => false,
|
|
]);
|
|
|
|
foreach ([
|
|
[$moderator, '3'],
|
|
[$player, '5'],
|
|
[$thirdPlayer, '8'],
|
|
[$nonNumericPlayer, 'coffee'],
|
|
] as [$votingPlayer, $value]) {
|
|
$votingPlayer->votes()->create([
|
|
'room_id' => $room->id,
|
|
'round' => 1,
|
|
'value' => $value,
|
|
]);
|
|
}
|
|
|
|
$room->update(['revealed_at' => now()]);
|
|
|
|
$this->withSession(["room_players.{$room->id}" => $moderator->id])
|
|
->get(route('room.show', $room))
|
|
->assertInertia(fn (Assert $page) => $page
|
|
->where('room.statistics.average', '5,33')
|
|
->where('room.statistics.median', '5,00'));
|
|
});
|