'array', 'cache.limiter' => 'array']); $this->app->forgetInstance(\Illuminate\Cache\RateLimiter::class); RateLimiter::clearResolvedInstances(); $this->app->getProvider(\App\Providers\RouteServiceProvider::class)->configureRateLimiting(); } private function update(): \Illuminate\Testing\TestResponse { // A valid CSRF token, as the bot had: CSRF is checked before the // limiter, and a request without one is refused (419) uncounted. // An empty payload: the limit counts requests, not successes. return $this->withSession(['_token' => 'test-token']) ->withHeader('X-CSRF-TOKEN', 'test-token') ->postJson(route('default.livewire.update'), ['components' => []]); } public function test_the_update_route_is_throttled(): void { $route = app('router')->getRoutes()->getByName('default.livewire.update'); $this->assertContains('throttle:livewire', $route->gatherMiddleware()); } public function test_a_guest_is_refused_after_120_a_minute(): void { for ($i = 1; $i <= 120; $i++) { $this->assertNotSame(429, $this->update()->status(), "Request $i is within the limit."); } $refused = $this->update(); $refused->assertStatus(429); $this->assertSame('120', (string) $refused->headers->get('X-RateLimit-Limit')); } public function test_a_logged_in_user_gets_500_a_minute_of_their_own(): void { $user = User::factory()->create(); // A guest on the same IP has used up the guest allowance... for ($i = 0; $i < 121; $i++) { $this->update(); } $this->update()->assertStatus(429); // ...which does not touch the user's. $response = $this->actingAs($user)->update(); $this->assertNotSame(429, $response->status()); $this->assertSame('500', (string) $response->headers->get('X-RateLimit-Limit')); } }