Passed
Push — master ( 2cc434...23a4c1 )
by Alexander
03:31
created

RateLimiterMiddlewareTest   A

Complexity

Total Complexity 4

Size/Duplication

Total Lines 99
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 39
c 1
b 0
f 0
dl 0
loc 99
rs 10
wmc 4

11 Methods

Rating   Name   Duplication   Size   Complexity  
A hp$0 ➔ createRequestHandler() 0 6 1
A hp$0 ➔ createRequest() 0 3 1
A counterIdCouldBeSet() 0 6 1
A hp$0 ➔ createRateLimiter() 0 3 1
A counterIdCouldBeSetWithCallback() 0 11 1
createRateLimiter() 0 3 ?
createRequest() 0 3 ?
A singleRequestWorksAsExpected() 0 13 1
A hp$0 ➔ handle() 0 3 1
createRequestHandler() 0 6 ?
A limitingIsStartedWhenExpected() 0 27 1
1
<?php
2
3
namespace Yiisoft\Yii\Web\Tests\RateLimiter;
4
5
use Nyholm\Psr7\Factory\Psr17Factory;
6
use Nyholm\Psr7\Response;
7
use Nyholm\Psr7\ServerRequest;
8
use PHPUnit\Framework\TestCase;
9
use Psr\Http\Message\ResponseInterface;
10
use Psr\Http\Message\ServerRequestInterface;
11
use Psr\Http\Server\RequestHandlerInterface;
12
use Yiisoft\Http\Method;
13
use Yiisoft\Yii\Web\RateLimiter\CounterInterface;
14
use Yiisoft\Yii\Web\RateLimiter\RateLimiterMiddleware;
15
16
final class RateLimiterMiddlewareTest extends TestCase
17
{
18
    /**
19
     * @test
20
     */
21
    public function singleRequestWorksAsExpected(): void
22
    {
23
        $counter = new FakeCounter(100, 100);
24
        $response = $this->createRateLimiter($counter)->process($this->createRequest(), $this->createRequestHandler());
25
        $this->assertEquals(200, $response->getStatusCode());
26
27
        $this->assertEquals(
28
            [
29
                'X-Rate-Limit-Limit' => ['100'],
30
                'X-Rate-Limit-Remaining' => ['99'],
31
                'X-Rate-Limit-Reset' => ['100'],
32
            ],
33
            $response->getHeaders()
34
        );
35
    }
36
37
    /**
38
     * @test
39
     */
40
    public function limitingIsStartedWhenExpected(): void
41
    {
42
        $counter = new FakeCounter(2, 100);
43
        $middleware = $this->createRateLimiter($counter);
44
45
        // last allowed request
46
        $response = $middleware->process($this->createRequest(), $this->createRequestHandler());
47
        $this->assertEquals(200, $response->getStatusCode());
48
        $this->assertEquals(
49
            [
50
                'X-Rate-Limit-Limit' => ['2'],
51
                'X-Rate-Limit-Remaining' => ['1'],
52
                'X-Rate-Limit-Reset' => ['100'],
53
            ],
54
            $response->getHeaders()
55
        );
56
57
        // first denied request
58
        $response = $middleware->process($this->createRequest(), $this->createRequestHandler());
59
        $this->assertEquals(429, $response->getStatusCode());
60
        $this->assertEquals(
61
            [
62
                'X-Rate-Limit-Limit' => ['2'],
63
                'X-Rate-Limit-Remaining' => ['0'],
64
                'X-Rate-Limit-Reset' => ['100'],
65
            ],
66
            $response->getHeaders()
67
        );
68
    }
69
70
    /**
71
     * @test
72
     */
73
    public function counterIdCouldBeSet(): void
74
    {
75
        $counter = new FakeCounter(100, 100);
76
        $middleware = $this->createRateLimiter($counter)->withCounterId('custom-id');
77
        $middleware->process($this->createRequest(), $this->createRequestHandler());
78
        $this->assertEquals('custom-id', $counter->getId());
79
    }
80
81
    /**
82
     * @test
83
     */
84
    public function counterIdCouldBeSetWithCallback(): void
85
    {
86
        $counter = new FakeCounter(100, 100);
87
        $middleware = $this->createRateLimiter($counter)->withCounterIdCallback(
88
            static function (ServerRequestInterface $request) {
89
                return $request->getMethod();
90
            }
91
        );
92
93
        $middleware->process($this->createRequest(), $this->createRequestHandler());
94
        $this->assertEquals('GET', $counter->getId());
95
    }
96
97
    private function createRequestHandler(): RequestHandlerInterface
98
    {
99
        return new class implements RequestHandlerInterface {
100
            public function handle(ServerRequestInterface $request): ResponseInterface
101
            {
102
                return new Response(200);
103
            }
104
        };
105
    }
106
107
    private function createRequest(string $method = Method::GET, string $uri = '/'): ServerRequestInterface
108
    {
109
        return new ServerRequest($method, $uri);
110
    }
111
112
    private function createRateLimiter(CounterInterface $counter): RateLimiterMiddleware
113
    {
114
        return new RateLimiterMiddleware($counter, new Psr17Factory());
115
    }
116
}
117