set('rcon.access_command', 'whitelist add {username}'); $rconClient = new FakeMinecraftRconClient; $this->app->instance(MinecraftRconClient::class, $rconClient); $reviewer = User::factory()->create(); $accessRequest = $this->pendingAccessRequest('LeonPlayer'); $output = app(AccessRequestApprover::class)->approve($accessRequest, $reviewer); $this->assertSame('Added LeonPlayer to the whitelist', $output); $this->assertSame(['whitelist add LeonPlayer'], $rconClient->commands); $this->assertDatabaseHas('access_requests', [ 'id' => $accessRequest->id, 'status' => AccessRequestStatus::ACCEPTED->value, 'reviewed_by' => $reviewer->id, ]); $this->assertNotNull($accessRequest->fresh()->reviewed_at); } public function test_it_does_not_accept_when_rcon_fails(): void { $this->app->instance(MinecraftRconClient::class, new FakeMinecraftRconClient(shouldFail: true)); $accessRequest = $this->pendingAccessRequest('LeonPlayer'); $this->expectException(RuntimeException::class); try { app(AccessRequestApprover::class)->approve($accessRequest); } finally { $this->assertDatabaseHas('access_requests', [ 'id' => $accessRequest->id, 'status' => AccessRequestStatus::PENDING->value, 'reviewed_by' => null, 'reviewed_at' => null, ]); } } private function pendingAccessRequest(string $gameUsername): AccessRequests { $server = GameServers::create([ 'name' => 'Survival', 'slug' => 'survival', ]); return AccessRequests::create([ 'status' => AccessRequestStatus::PENDING, 'game_username' => $gameUsername, 'message' => '', 'server_id' => $server->id, ]); } } class FakeMinecraftRconClient extends MinecraftRconClient { /** * @var array */ public array $commands = []; public function __construct( private readonly bool $shouldFail = false, ) {} public function command(string $command): string { $this->commands[] = $command; if ($this->shouldFail) { throw new RuntimeException('rcon failed'); } return 'Added LeonPlayer to the whitelist'; } }