Passed
Pull Request — master (#17)
by Mihail
15:10
created

MockHttpHeader

Complexity

Total Complexity 0

Size/Duplication

Total Lines 3
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
eloc 2
c 1
b 0
f 1
dl 0
loc 3
wmc 0
1
<?php
2
3
namespace Tests\Koded\Http;
4
5
use Koded\Http\HeaderTrait;
6
use Koded\Http\Interfaces\HttpStatus;
7
use PHPUnit\Framework\TestCase;
8
9
class MockHttpHeader
10
{
11
    use HeaderTrait;
12
}
13
14
class HeaderTraitTest extends TestCase
15
{
16
    use AssertionTestSupportTrait;
17
18
    private MockHttpHeader $SUT;
19
20
    public function test_get_header_not_set()
21
    {
22
        $this->assertSame([], $this->SUT->getHeader('foo'));
23
    }
24
25
    public function test_get_headers()
26
    {
27
        $this->assertSame([], $this->SUT->getHeaders());
28
    }
29
30
    public function test_get_header_line()
31
    {
32
        $this->assertSame('', $this->SUT->getHeaderLine('foo'));
33
34
        $response = $this->SUT->withAddedHeader('foo', '1');
35
        $response = $response->withAddedHeader('foo', ['1']);
36
        $response = $response->withAddedHeader('foo', 'two');
37
        $response = $response->withAddedHeader('foo', 'two');
38
        $response = $response->withAddedHeader('foo', 'two');
39
        $response = $response->withAddedHeader('foo', ['1']);
40
41
        $this->assertSame('1,two', $response->getHeaderLine('foo'),
42
            'Added values are unique / exists only once');
43
44
        $response = $this->SUT->withAddedHeader('bar', 'baz');
45
        $this->assertSame('baz', $response->getHeaderLine('bar'));
46
    }
47
48
    public function test_set_header_line_with_invalid_array_values()
49
    {
50
        $this->expectException(\InvalidArgumentException::class);
51
        $this->expectExceptionCode(HttpStatus::BAD_REQUEST);
52
        $this->expectExceptionMessage('expects a string or array of strings');
53
        $this->SUT->withHeader('foo', ['bar', 1]);
54
    }
55
56
     public function test_set_header_line_with_invalid_scalar_value()
57
    {
58
        $this->expectException(\InvalidArgumentException::class);
59
        $this->expectExceptionCode(HttpStatus::BAD_REQUEST);
60
        $this->expectExceptionMessage('expects a string or array of strings');
61
        $this->SUT->withHeader('foo', 0);
62
    }
63
64
    public function test_add_header_value()
65
    {
66
        $response = $this->SUT->withHeader('foo', 'bar');
67
68
        // $name is case-insensitive
69
        $this->assertSame(['bar'], $response->getHeader('foo'));
70
        $this->assertSame(['bar'], $response->getHeader('Foo'));
71
        return $response;
72
    }
73
74
    /**
75
     * @depends test_add_header_value
76
     *
77
     * @param MockHttpHeader $sut
78
     */
79
    public function test_has_header(MockHttpHeader $sut)
80
    {
81
        $this->assertTrue($sut->hasHeader('Foo'));
82
        $this->assertTrue($sut->hasHeader('foo'));
83
        $this->assertFalse($sut->hasHeader('zim'));
84
    }
85
86
    /**
87
     * @depends test_add_header_value
88
     *
89
     * @param MockHttpHeader $sut
90
     */
91
    public function test_delete_header(MockHttpHeader $sut)
92
    {
93
        $this->assertTrue($sut->hasHeader('Foo'));
94
        $response = $sut->withoutHeader('Foo');
95
96
        $this->assertTrue($sut->hasHeader('Foo'));
97
        $this->assertFalse($response->hasHeader('Foo'));
98
    }
99
100
    /**
101
     * @depends test_add_header_value
102
     *
103
     * @param MockHttpHeader $sut
104
     */
105
    public function test_delete_header_if_not_exist(MockHttpHeader $sut)
106
    {
107
        $this->assertFalse($sut->hasHeader('foobar'));
108
        $response = $sut->withoutHeader('foobar');
0 ignored issues
show
Unused Code introduced by
The assignment to $response is dead and can be removed.
Loading history...
109
        $this->assertFalse($sut->hasHeader('foobar'),
110
            'Should not throw exception if header is not set');
111
    }
112
113
    public function test_replace_headers()
114
    {
115
        $SUT = $this->SUT->withHeader('FOO_BAR', 'baz');
116
        $this->assertSame(['baz'], $SUT->getHeader('foo_bar'));
117
118
        $SUT = $SUT->replaceHeaders([
119
            'LONG_HEADER_NAME_1' => 'foo',
120
            'HEADER_2'           => 'bar'
121
        ]);
122
123
        $properties = $this->getObjectProperties($SUT);
124
125
        $this->assertSame([
126
            'Long-Header-Name-1' => ['foo'],
127
            'Header-2'           => ['bar'],
128
        ], $properties['headers']);
129
130
        $this->assertSame([
131
            'long-header-name-1' => 'Long-Header-Name-1',
132
            'header-2'           => 'Header-2',
133
        ], $properties['headersMap']);
134
    }
135
136
    public function test_flattened_header()
137
    {
138
        $this->SUT = $this->SUT->withHeaders([
139
            'content-type'   => 'application/json',
140
            'content-length' => '1',
141
            'x-param'        => ['foo', 'bar'],
142
        ]);
143
144
        $this->assertSame([
145
            'Content-Type:application/json',
146
            'Content-Length:1',
147
            'X-Param:foo,bar'
148
        ],
149
            $this->SUT->getFlattenedHeaders(),
150
            'The spaces are removed, keys are capitalized');
151
    }
152
153
    public function test_empty_flattened_headers()
154
    {
155
        $this->assertSame([], $this->SUT->getFlattenedHeaders());
156
    }
157
158
    public function test_canonicalized_header()
159
    {
160
        $this->SUT = $this->SUT->withHeaders([
161
            'Content-type'   => 'application/json',
162
            'X-Param'        => ['foo', 'bar'],
163
            'content-length' => '1',
164
            'Accept' => '*/*'
165
        ]);
166
167
        $this->assertSame(
168
            'accept:*/*' . "\n" .
169
            'content-length:1' . "\n" .
170
            'content-type:application/json' . "\n" .
171
            'x-param:foo,bar',
172
            $this->SUT->getCanonicalizedHeaders());
173
    }
174
175
    public function test_empty_canonicalized_headers()
176
    {
177
        $this->assertSame('', $this->SUT->getCanonicalizedHeaders());
178
    }
179
180
    public function test_canonicalized_headers_with_names()
181
    {
182
        $this->SUT = $this->SUT->withHeaders([
183
            'Content-type'   => 'application/json',
184
            'X-Param'        => ['foo', 'bar'],
185
            'content-length' => '1',
186
            'Accept' => '*/*'
187
        ]);
188
189
        $this->assertSame(
190
            'content-length:1' . "\n" .
191
            'x-param:foo,bar',
192
            $this->SUT->getCanonicalizedHeaders(['content-length', 'x-param']));
193
    }
194
195
    public function test_canonicalized_headers_with_nonexistent_headers()
196
    {
197
        $this->assertSame("x-fubar:", $this->SUT->getCanonicalizedHeaders([
198
            'X_Fubar'
199
        ]), 'One matched header does not have a newline');
200
201
        $this->assertSame("x-fubar:\nx-param-1:", $this->SUT->getCanonicalizedHeaders([
202
            'X_Fubar',
203
            'X-PARAM-1'
204
        ]), 'The last element is without a newline');
205
    }
206
207
    public function test_normalizing_headers_key_and_value()
208
    {
209
        $this->SUT = $this->SUT->withHeaders([
210
            "HTTP/1.1 401 Authorization Required\r\n" => "\r\n",
211
            "cache-control\n" => " no-cache, no-store, must-revalidate, pre-check=0, post-check=0\r\n",
212
            "x-xss-protection\r\n" => "0 \r\n",
213
            " Nasty-\tHeader-\r\nName" => "weird\nvalue\r",
214
        ]);
215
216
        $this->assertSame([
217
            'Http/1.1 401 authorization required' => [''],
218
            'Cache-Control' => ['no-cache, no-store, must-revalidate, pre-check=0, post-check=0'],
219
            'X-Xss-Protection' => ['0'],
220
            "Nasty-Header-Name" => ["weird value"],
221
        ], $this->SUT->getHeaders());
222
    }
223
224
    protected function setUp(): void
225
    {
226
        $this->SUT = new MockHttpHeader;
227
    }
228
}
229