Passed
Push — main ( f1c997...ae6b2e )
by Daniel
13:01
created

InvalidHeaderFilterTest   A

Complexity

Total Complexity 7

Size/Duplication

Total Lines 134
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 7
eloc 57
c 1
b 0
f 0
dl 0
loc 134
rs 10

7 Methods

Rating   Name   Duplication   Size   Complexity  
A providesValidRequests() 0 19 1
A testConstructorAcceptsOptions() 0 10 1
A testConstructor() 0 13 1
A testIsAFilter() 0 3 1
A testInvokeReturnsFalseIfTheValueOfAHeaderIsValid() 0 19 1
A testInvokeReturnsTrueIfTheValueOfAHeaderIsInvalid() 0 21 1
A providesInvalidRequests() 0 21 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace DanBettles\Defence\Tests\Filter;
6
7
use DanBettles\Defence\Envelope;
8
use DanBettles\Defence\Filter\AbstractFilter;
9
use DanBettles\Defence\Filter\InvalidHeaderFilter;
10
use DanBettles\Defence\Tests\AbstractTestCase;
11
use Psr\Log\LogLevel;
12
use Psr\Log\NullLogger;
13
use Symfony\Component\HttpFoundation\Request;
14
15
use const false;
16
use const true;
17
18
/**
19
 * @phpstan-type FilterArgs array{selector:string,validator:\Closure}
20
 */
21
class InvalidHeaderFilterTest extends AbstractTestCase
22
{
23
    public function testIsAFilter(): void
24
    {
25
        $this->assertSubclassOf(AbstractFilter::class, InvalidHeaderFilter::class);
26
    }
27
28
    public function testConstructor(): void
29
    {
30
        $selector = 'User-Agent';
31
        $validator = fn () => true;
32
33
        $filter = new InvalidHeaderFilter($selector, $validator);
34
35
        $this->assertSame($selector, $filter->getSelector());
36
        $this->assertSame($validator, $filter->getValidator());
37
38
        $this->assertSame([
39
            'log_level' => LogLevel::WARNING,
40
        ], $filter->getOptions());
41
    }
42
43
    public function testConstructorAcceptsOptions(): void
44
    {
45
        $filter = new InvalidHeaderFilter('Anything', fn () => true, [
46
            'foo' => 'bar',
47
        ]);
48
49
        $this->assertSame([
50
            'log_level' => LogLevel::WARNING,
51
            'foo' => 'bar',
52
        ], $filter->getOptions());
53
    }
54
55
    /** @return array<mixed[]> */
56
    public function providesInvalidRequests(): array
57
    {
58
        $request = $this
59
            ->getRequestFactory()
60
            ->createWithHeaders(['User-Agent' => 'anything'])
61
        ;
62
63
        $validator = fn (): bool => false;
64
65
        return [
66
            // Title-case selector
67
            [
68
                'expectedLogMessage' => 'The value of header `User-Agent`, `anything`, is invalid',
69
                $request,
70
                ['selector' => 'User-Agent', 'validator' => $validator],
71
            ],
72
            // Lowercase selector
73
            [
74
                'expectedLogMessage' => 'The value of header `user-agent`, `anything`, is invalid',
75
                $request,
76
                ['selector' => 'user-agent', 'validator' => $validator],
77
            ],
78
        ];
79
    }
80
81
    /**
82
     * @dataProvider providesInvalidRequests
83
     * @phpstan-param FilterArgs $filterArgs
84
     */
85
    public function testInvokeReturnsTrueIfTheValueOfAHeaderIsInvalid(
86
        ?string $expectedLogMessage,
87
        Request $request,
88
        array $filterArgs,
89
    ): void {
90
        $envelope = new Envelope($request, new NullLogger());
91
92
        $mockFilter = $this
93
            ->getMockBuilder(InvalidHeaderFilter::class)
94
            ->setConstructorArgs($filterArgs)
95
            ->onlyMethods(['envelopeAddLogEntry'])
96
            ->getMock()
97
        ;
98
99
        $mockFilter
100
            ->expects($this->once())
101
            ->method('envelopeAddLogEntry')
102
            ->with($envelope, $expectedLogMessage)
103
        ;
104
105
        $this->assertTrue($mockFilter($envelope));
106
    }
107
108
    /** @return array<mixed[]> */
109
    public function providesValidRequests(): array
110
    {
111
        $request = $this
112
            ->getRequestFactory()
113
            ->createWithHeaders(['User-Agent' => 'anything'])
114
        ;
115
116
        $validator = fn (): bool => true;
117
118
        return [
119
            // Title-case selector
120
            [
121
                $request,
122
                'filterArgs' => ['selector' => 'User-Agent', 'validator' => $validator],
123
            ],
124
            // Lowercase selector
125
            [
126
                $request,
127
                'filterArgs' => ['selector' => 'user-agent', 'validator' => $validator],
128
            ],
129
        ];
130
    }
131
132
    /**
133
     * @dataProvider providesValidRequests
134
     * @phpstan-param FilterArgs $filterArgs
135
     */
136
    public function testInvokeReturnsFalseIfTheValueOfAHeaderIsValid(
137
        Request $request,
138
        array $filterArgs,
139
    ): void {
140
        $mockFilter = $this
141
            ->getMockBuilder(InvalidHeaderFilter::class)
142
            ->setConstructorArgs($filterArgs)
143
            ->onlyMethods(['envelopeAddLogEntry'])
144
            ->getMock()
145
        ;
146
147
        $mockFilter
148
            ->expects($this->never())
149
            ->method('envelopeAddLogEntry')
150
        ;
151
152
        $envelope = new Envelope($request, new NullLogger());
153
154
        $this->assertFalse($mockFilter($envelope));
155
    }
156
}
157