mirror of
https://github.com/ericasch6/scrum-poker-internal.git
synced 2026-10-13 14:52:09 +00:00
do not need login
This commit is contained in:
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
namespace App\Http\Controllers;
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
|
use App\Models\Room;
|
||||||
use Illuminate\Http\RedirectResponse;
|
use Illuminate\Http\RedirectResponse;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Support\Facades\Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
@@ -15,11 +16,27 @@ class EmbeddedLogoutController extends Controller
|
|||||||
{
|
{
|
||||||
$joinCode = $request->string('join_code')->trim()->upper()->toString();
|
$joinCode = $request->string('join_code')->trim()->upper()->toString();
|
||||||
$playerName = $request->string('player_name')->trim()->toString();
|
$playerName = $request->string('player_name')->trim()->toString();
|
||||||
|
$room = Room::query()->where('join_code', $joinCode)->first();
|
||||||
|
$playerId = null;
|
||||||
|
|
||||||
|
if ($room !== null) {
|
||||||
|
$sessionPlayerId = $request->session()->get("room_players.{$room->id}");
|
||||||
|
|
||||||
|
if (is_numeric($sessionPlayerId)) {
|
||||||
|
$playerId = $room->players()
|
||||||
|
->whereKey((int) $sessionPlayerId)
|
||||||
|
->value('id');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Auth::guard('web')->logout();
|
Auth::guard('web')->logout();
|
||||||
$request->session()->invalidate();
|
$request->session()->invalidate();
|
||||||
$request->session()->regenerateToken();
|
$request->session()->regenerateToken();
|
||||||
|
|
||||||
|
if ($room !== null && is_numeric($playerId)) {
|
||||||
|
$request->session()->put("room_players.{$room->id}", (int) $playerId);
|
||||||
|
}
|
||||||
|
|
||||||
return to_route('embedded.room', [
|
return to_route('embedded.room', [
|
||||||
'join_code' => $joinCode,
|
'join_code' => $joinCode,
|
||||||
'player_name' => $playerName,
|
'player_name' => $playerName,
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ use App\Http\Requests\ShowEmbeddedRoomRequest;
|
|||||||
use App\Http\Resources\CurrentPlayerResource;
|
use App\Http\Resources\CurrentPlayerResource;
|
||||||
use App\Http\Resources\RoomResource;
|
use App\Http\Resources\RoomResource;
|
||||||
use App\Models\Room;
|
use App\Models\Room;
|
||||||
use App\Models\User;
|
|
||||||
use App\Services\Rooms\RoomPageService;
|
use App\Services\Rooms\RoomPageService;
|
||||||
use App\Services\Rooms\RoomParticipationService;
|
use App\Services\Rooms\RoomParticipationService;
|
||||||
use Inertia\Inertia;
|
use Inertia\Inertia;
|
||||||
@@ -25,8 +24,6 @@ class EmbeddedRoomController extends Controller
|
|||||||
$validated = $request->validated();
|
$validated = $request->validated();
|
||||||
$user = $request->user();
|
$user = $request->user();
|
||||||
|
|
||||||
abort_unless($user instanceof User, 403);
|
|
||||||
|
|
||||||
$room = Room::query()
|
$room = Room::query()
|
||||||
->where('join_code', $validated['join_code'])
|
->where('join_code', $validated['join_code'])
|
||||||
->firstOrFail();
|
->firstOrFail();
|
||||||
@@ -34,10 +31,10 @@ class EmbeddedRoomController extends Controller
|
|||||||
$room,
|
$room,
|
||||||
$user,
|
$user,
|
||||||
$validated['player_name'],
|
$validated['player_name'],
|
||||||
|
$request->session()->get("room_players.{$room->id}"),
|
||||||
);
|
);
|
||||||
|
|
||||||
$request->session()->put("room_players.{$room->id}", $player->id);
|
$request->session()->put("room_players.{$room->id}", $player->id);
|
||||||
$request->session()->forget('embedded_login');
|
|
||||||
|
|
||||||
$pageData = $this->roomPage->prepare($room, $player, $user);
|
$pageData = $this->roomPage->prepare($room, $player, $user);
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ class ShowEmbeddedRoomRequest extends FormRequest
|
|||||||
*/
|
*/
|
||||||
public function authorize(): bool
|
public function authorize(): bool
|
||||||
{
|
{
|
||||||
return $this->user() !== null;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function prepareForValidation(): void
|
protected function prepareForValidation(): void
|
||||||
@@ -67,17 +67,28 @@ class ShowEmbeddedRoomRequest extends FormRequest
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($room === null || $this->user() === null) {
|
if ($room === null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$sessionPlayerId = $this->session()->get("room_players.{$room->id}");
|
||||||
|
$existingPlayer = is_numeric($sessionPlayerId)
|
||||||
|
? $room->players()->find((int) $sessionPlayerId)
|
||||||
|
: null;
|
||||||
|
|
||||||
|
if ($existingPlayer === null && $this->user() !== null) {
|
||||||
|
$existingPlayer = $room->players()
|
||||||
|
->where('user_id', $this->user()->id)
|
||||||
|
->first();
|
||||||
|
}
|
||||||
|
|
||||||
$nameIsTaken = Player::query()
|
$nameIsTaken = Player::query()
|
||||||
->where('room_id', $room->id)
|
->where('room_id', $room->id)
|
||||||
->where('name', $this->input('player_name'))
|
->where('name', $this->input('player_name'))
|
||||||
->where(function ($query): void {
|
->when(
|
||||||
$query->whereNull('user_id')
|
$existingPlayer !== null,
|
||||||
->orWhere('user_id', '!=', $this->user()->id);
|
fn ($query) => $query->whereKeyNot($existingPlayer->id),
|
||||||
})
|
)
|
||||||
->exists();
|
->exists();
|
||||||
|
|
||||||
if ($nameIsTaken) {
|
if ($nameIsTaken) {
|
||||||
|
|||||||
@@ -51,7 +51,6 @@ class FortifyServiceProvider extends ServiceProvider
|
|||||||
Fortify::loginView(fn (Request $request) => Inertia::render('auth/Login', [
|
Fortify::loginView(fn (Request $request) => Inertia::render('auth/Login', [
|
||||||
'canResetPassword' => Features::enabled(Features::resetPasswords()),
|
'canResetPassword' => Features::enabled(Features::resetPasswords()),
|
||||||
'status' => $request->session()->get('status'),
|
'status' => $request->session()->get('status'),
|
||||||
'rememberByDefault' => $request->session()->get('embedded_login', false),
|
|
||||||
]));
|
]));
|
||||||
|
|
||||||
Fortify::resetPasswordView(fn (Request $request) => Inertia::render('auth/ResetPassword', [
|
Fortify::resetPasswordView(fn (Request $request) => Inertia::render('auth/ResetPassword', [
|
||||||
|
|||||||
@@ -102,9 +102,13 @@ class RoomParticipationService
|
|||||||
return [$room, $player];
|
return [$room, $player];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function joinEmbedded(Room $room, User $user, string $playerName): Player
|
public function joinEmbedded(
|
||||||
{
|
Room $room,
|
||||||
[$player, $change, $stateVersion] = DB::transaction(function () use ($room, $user, $playerName): array {
|
?User $user,
|
||||||
|
string $playerName,
|
||||||
|
mixed $sessionPlayerId,
|
||||||
|
): Player {
|
||||||
|
[$player, $change, $stateVersion] = DB::transaction(function () use ($room, $user, $playerName, $sessionPlayerId): array {
|
||||||
$lockedRoom = Room::query()
|
$lockedRoom = Room::query()
|
||||||
->lockForUpdate()
|
->lockForUpdate()
|
||||||
->findOrFail($room->id);
|
->findOrFail($room->id);
|
||||||
@@ -115,12 +119,18 @@ class RoomParticipationService
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$player = $this->findExistingEmbeddedPlayer(
|
||||||
|
$lockedRoom,
|
||||||
|
$user,
|
||||||
|
$sessionPlayerId,
|
||||||
|
);
|
||||||
|
|
||||||
$nameIsTaken = $lockedRoom->players()
|
$nameIsTaken = $lockedRoom->players()
|
||||||
->where('name', $playerName)
|
->where('name', $playerName)
|
||||||
->where(function ($query) use ($user): void {
|
->when(
|
||||||
$query->whereNull('user_id')
|
$player !== null,
|
||||||
->orWhere('user_id', '!=', $user->id);
|
fn ($query) => $query->whereKeyNot($player->id),
|
||||||
})
|
)
|
||||||
->exists();
|
->exists();
|
||||||
|
|
||||||
if ($nameIsTaken) {
|
if ($nameIsTaken) {
|
||||||
@@ -129,14 +139,11 @@ class RoomParticipationService
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
$player = $lockedRoom->players()
|
|
||||||
->where('user_id', $user->id)
|
|
||||||
->first();
|
|
||||||
$change = null;
|
$change = null;
|
||||||
|
|
||||||
if ($player === null) {
|
if ($player === null) {
|
||||||
$player = $lockedRoom->players()->create([
|
$player = $lockedRoom->players()->create([
|
||||||
'user_id' => $user->id,
|
'user_id' => $user?->id,
|
||||||
'name' => $playerName,
|
'name' => $playerName,
|
||||||
'is_moderator' => false,
|
'is_moderator' => false,
|
||||||
'last_seen_at' => now(),
|
'last_seen_at' => now(),
|
||||||
@@ -149,11 +156,24 @@ class RoomParticipationService
|
|||||||
$change = RoomStateChange::PlayerUpdated;
|
$change = RoomStateChange::PlayerUpdated;
|
||||||
}
|
}
|
||||||
|
|
||||||
$player->update([
|
$updates = [
|
||||||
'name' => $playerName,
|
'name' => $playerName,
|
||||||
'last_seen_at' => now(),
|
'last_seen_at' => now(),
|
||||||
'inactive_at' => null,
|
'inactive_at' => null,
|
||||||
]);
|
];
|
||||||
|
|
||||||
|
if (
|
||||||
|
$user !== null
|
||||||
|
&& $player->user_id === null
|
||||||
|
&& ! $lockedRoom->players()
|
||||||
|
->where('user_id', $user->id)
|
||||||
|
->whereKeyNot($player->id)
|
||||||
|
->exists()
|
||||||
|
) {
|
||||||
|
$updates['user_id'] = $user->id;
|
||||||
|
}
|
||||||
|
|
||||||
|
$player->update($updates);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($change === null) {
|
if ($change === null) {
|
||||||
@@ -180,6 +200,32 @@ class RoomParticipationService
|
|||||||
return $player;
|
return $player;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function findExistingEmbeddedPlayer(
|
||||||
|
Room $room,
|
||||||
|
?User $user,
|
||||||
|
mixed $sessionPlayerId,
|
||||||
|
): ?Player {
|
||||||
|
if (is_numeric($sessionPlayerId)) {
|
||||||
|
$sessionPlayer = $room->players()
|
||||||
|
->whereKey((int) $sessionPlayerId)
|
||||||
|
->lockForUpdate()
|
||||||
|
->first();
|
||||||
|
|
||||||
|
if ($sessionPlayer !== null) {
|
||||||
|
return $sessionPlayer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($user === null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $room->players()
|
||||||
|
->where('user_id', $user->id)
|
||||||
|
->lockForUpdate()
|
||||||
|
->first();
|
||||||
|
}
|
||||||
|
|
||||||
public function kick(
|
public function kick(
|
||||||
Room $room,
|
Room $room,
|
||||||
Player $player,
|
Player $player,
|
||||||
|
|||||||
@@ -18,13 +18,6 @@ return Application::configure(basePath: dirname(__DIR__))
|
|||||||
)
|
)
|
||||||
->withMiddleware(function (Middleware $middleware): void {
|
->withMiddleware(function (Middleware $middleware): void {
|
||||||
$middleware->trustProxies(at: '*');
|
$middleware->trustProxies(at: '*');
|
||||||
$middleware->redirectGuestsTo(function (Request $request): string {
|
|
||||||
if ($request->isMethod('GET') && $request->is('embedded/scrum-poker')) {
|
|
||||||
$request->session()->put('embedded_login', true);
|
|
||||||
}
|
|
||||||
|
|
||||||
return route('login');
|
|
||||||
});
|
|
||||||
$middleware->encryptCookies(except: ['appearance', 'sidebar_state']);
|
$middleware->encryptCookies(except: ['appearance', 'sidebar_state']);
|
||||||
$middleware->alias([
|
$middleware->alias([
|
||||||
'room.player' => EnsureRoomParticipant::class,
|
'room.player' => EnsureRoomParticipant::class,
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ const props = withDefaults(defineProps<RoomExperienceProps>(), {
|
|||||||
const page = usePage();
|
const page = usePage();
|
||||||
const presenterMode = ref(false);
|
const presenterMode = ref(false);
|
||||||
const roomNotice = computed(() => page.props.roomNotice);
|
const roomNotice = computed(() => page.props.roomNotice);
|
||||||
|
const isAuthenticated = computed(() => page.props.auth.user !== null);
|
||||||
const embeddedBackgroundColor = computed(() => {
|
const embeddedBackgroundColor = computed(() => {
|
||||||
if (!props.embedded) {
|
if (!props.embedded) {
|
||||||
return undefined;
|
return undefined;
|
||||||
@@ -74,7 +75,7 @@ const {
|
|||||||
realtimeRoom.allow_participants_to_manage_rounds
|
realtimeRoom.allow_participants_to_manage_rounds
|
||||||
"
|
"
|
||||||
:current-player-id="realtimeCurrentPlayer.id"
|
:current-player-id="realtimeCurrentPlayer.id"
|
||||||
:embedded="embedded"
|
:can-logout="embedded && isAuthenticated"
|
||||||
:player-name="realtimeCurrentPlayer.name"
|
:player-name="realtimeCurrentPlayer.name"
|
||||||
v-model:presenter-mode="presenterMode"
|
v-model:presenter-mode="presenterMode"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -99,7 +99,7 @@ async function copyInviteLink(): Promise<void> {
|
|||||||
|
|
||||||
<div class="flex flex-col items-end gap-2">
|
<div class="flex flex-col items-end gap-2">
|
||||||
<Link
|
<Link
|
||||||
v-if="embedded"
|
v-if="canLogout"
|
||||||
:href="
|
:href="
|
||||||
embeddedLogout({
|
embeddedLogout({
|
||||||
query: {
|
query: {
|
||||||
|
|||||||
@@ -23,7 +23,6 @@ defineOptions({
|
|||||||
defineProps<{
|
defineProps<{
|
||||||
status?: string;
|
status?: string;
|
||||||
canResetPassword: boolean;
|
canResetPassword: boolean;
|
||||||
rememberByDefault: boolean;
|
|
||||||
}>();
|
}>();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -89,7 +88,6 @@ defineProps<{
|
|||||||
<Checkbox
|
<Checkbox
|
||||||
id="remember"
|
id="remember"
|
||||||
name="remember"
|
name="remember"
|
||||||
:default-value="rememberByDefault"
|
|
||||||
:tabindex="3"
|
:tabindex="3"
|
||||||
/>
|
/>
|
||||||
<span>Remember me</span>
|
<span>Remember me</span>
|
||||||
|
|||||||
@@ -116,7 +116,7 @@ export type RoomHeaderProps = Pick<
|
|||||||
canManageParticipants: boolean;
|
canManageParticipants: boolean;
|
||||||
currentPlayerId: number;
|
currentPlayerId: number;
|
||||||
presenterMode: boolean;
|
presenterMode: boolean;
|
||||||
embedded: boolean;
|
canLogout: boolean;
|
||||||
playerName: string;
|
playerName: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
+1
-3
@@ -25,10 +25,8 @@ Route::get('/room/join', RoomJoinController::class)->name('room.join');
|
|||||||
Route::post('room/join', [RoomPlayerController::class, 'join'])->name('room.code');
|
Route::post('room/join', [RoomPlayerController::class, 'join'])->name('room.code');
|
||||||
Route::post('/room', [RoomController::class, 'store'])->name('room.store');
|
Route::post('/room', [RoomController::class, 'store'])->name('room.store');
|
||||||
|
|
||||||
Route::middleware(['auth', 'verified'])->group(function () {
|
Route::get('/embedded/scrum-poker', EmbeddedRoomController::class)
|
||||||
Route::get('/embedded/scrum-poker', EmbeddedRoomController::class)
|
|
||||||
->name('embedded.room');
|
->name('embedded.room');
|
||||||
});
|
|
||||||
|
|
||||||
Route::post('/embedded/scrum-poker/logout', EmbeddedLogoutController::class)
|
Route::post('/embedded/scrum-poker/logout', EmbeddedLogoutController::class)
|
||||||
->middleware('auth')
|
->middleware('auth')
|
||||||
|
|||||||
@@ -19,22 +19,43 @@ function createEmbeddedRoom(array $attributes = []): Room
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
test('embedded room access sends guests through login and remembers the intended room', function () {
|
test('a guest automatically joins the embedded room', function () {
|
||||||
$room = createEmbeddedRoom();
|
$room = createEmbeddedRoom();
|
||||||
$url = route('embedded.room', [
|
$response = $this->get(route('embedded.room', [
|
||||||
'join_code' => $room->join_code,
|
'join_code' => strtolower($room->join_code),
|
||||||
'player_name' => 'Nico',
|
'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',
|
||||||
|
'inactive_at' => now(),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$this->get($url)
|
$this->withSession(["room_players.{$room->id}" => $player->id])
|
||||||
->assertRedirect(route('login'))
|
->get(route('embedded.room', [
|
||||||
->assertSessionHas('embedded_login', true)
|
'join_code' => $room->join_code,
|
||||||
->assertSessionHas('url.intended', $url);
|
'player_name' => 'New name',
|
||||||
|
]))
|
||||||
|
->assertOk();
|
||||||
|
|
||||||
$this->get(route('login'))
|
expect($room->players()->count())->toBe(1)
|
||||||
->assertInertia(fn (Assert $page) => $page
|
->and($player->fresh()->name)->toBe('New name')
|
||||||
->component('auth/Login')
|
->and($player->fresh()->inactive_at)->toBeNull();
|
||||||
->where('rememberByDefault', true));
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test('an authenticated user automatically joins the embedded room', function () {
|
test('an authenticated user automatically joins the embedded room', function () {
|
||||||
@@ -83,13 +104,36 @@ test('embedded access reuses the user player and applies a changed display name'
|
|||||||
->and($player->fresh()->inactive_at)->toBeNull();
|
->and($player->fresh()->inactive_at)->toBeNull();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('embedded access shows a dedicated error when the display name is taken', function () {
|
test('an embedded guest keeps the same player after logging in separately', function () {
|
||||||
$user = User::factory()->create();
|
$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 () {
|
||||||
$room = createEmbeddedRoom();
|
$room = createEmbeddedRoom();
|
||||||
$room->players()->create(['name' => 'Nico']);
|
$room->players()->create(['name' => 'Nico']);
|
||||||
|
|
||||||
$this->actingAs($user)
|
$this->get(route('embedded.room', [
|
||||||
->get(route('embedded.room', [
|
|
||||||
'join_code' => $room->join_code,
|
'join_code' => $room->join_code,
|
||||||
'player_name' => 'Nico',
|
'player_name' => 'Nico',
|
||||||
]))
|
]))
|
||||||
@@ -100,8 +144,7 @@ test('embedded access shows a dedicated error when the display name is taken', f
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('embedded access shows a dedicated error for an unknown room code', function () {
|
test('embedded access shows a dedicated error for an unknown room code', function () {
|
||||||
$this->actingAs(User::factory()->create())
|
$this->get(route('embedded.room', [
|
||||||
->get(route('embedded.room', [
|
|
||||||
'join_code' => 'ABC234',
|
'join_code' => 'ABC234',
|
||||||
'player_name' => 'Nico',
|
'player_name' => 'Nico',
|
||||||
]))
|
]))
|
||||||
@@ -111,19 +154,29 @@ test('embedded access shows a dedicated error for an unknown room code', functio
|
|||||||
->where('message', 'Dieser Raumcode existiert nicht.'));
|
->where('message', 'Dieser Raumcode existiert nicht.'));
|
||||||
});
|
});
|
||||||
|
|
||||||
test('embedded logout returns to the same configured room and signs the user out', function () {
|
test('embedded logout returns to the same room as a guest without duplicating the player', function () {
|
||||||
$user = User::factory()->create();
|
$user = User::factory()->create();
|
||||||
$room = createEmbeddedRoom();
|
$room = createEmbeddedRoom();
|
||||||
|
$url = route('embedded.room', [
|
||||||
|
'join_code' => $room->join_code,
|
||||||
|
'player_name' => 'Nico',
|
||||||
|
]);
|
||||||
|
|
||||||
$this->actingAs($user)
|
$this->actingAs($user)->get($url)->assertOk();
|
||||||
|
|
||||||
|
$player = $room->players()->sole();
|
||||||
|
|
||||||
|
$this
|
||||||
|
->followingRedirects()
|
||||||
->post(route('embedded.logout', [
|
->post(route('embedded.logout', [
|
||||||
'join_code' => $room->join_code,
|
'join_code' => $room->join_code,
|
||||||
'player_name' => 'Nico',
|
'player_name' => 'Nico',
|
||||||
]))
|
]))
|
||||||
->assertRedirect(route('embedded.room', [
|
->assertOk()
|
||||||
'join_code' => $room->join_code,
|
->assertInertia(fn (Assert $page) => $page
|
||||||
'player_name' => 'Nico',
|
->component('embedded/Room')
|
||||||
]));
|
->where('currentPlayer.id', $player->id));
|
||||||
|
|
||||||
$this->assertGuest();
|
$this->assertGuest()
|
||||||
|
->assertDatabaseCount('players', 1);
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user