Completed
Push — master ( 8c5203...c6433c )
by Gerrit
23:20
created

shouldAddFlashMessageUponException()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 34

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 34
c 0
b 0
f 0
rs 9.376
cc 1
nc 1
nop 0
1
<?php
2
/**
3
 * Copyright (C) 2017  Gerrit Addiks.
4
 * This package (including this file) was released under the terms of the GPL-3.0.
5
 * You should have received a copy of the GNU General Public License along with this program.
6
 * If not, see <http://www.gnu.org/licenses/> or send me a mail so i can send you a copy.
7
 * @license GPL-3.0
8
 * @author Gerrit Addiks <[email protected]>
9
 */
10
11
namespace Addiks\SymfonyGenerics\Tests\Unit\Controllers;
12
13
use PHPUnit\Framework\TestCase;
14
use Addiks\SymfonyGenerics\Controllers\GenericExceptionResponseController;
15
use Addiks\SymfonyGenerics\Controllers\ControllerHelperInterface;
16
use Serializable;
17
use Symfony\Component\HttpFoundation\Response;
18
use InvalidArgumentException;
19
use DivisionByZeroError;
20
use Addiks\SymfonyGenerics\Services\ArgumentCompilerInterface;
21
use Symfony\Component\HttpFoundation\Request;
22
use Symfony\Component\HttpFoundation\RedirectResponse;
23
24
final class GenericExceptionResponseControllerTest extends TestCase
25
{
26
27
    /**
28
     * @var GenericExceptionResponseController
29
     */
30
    private $controller;
31
32
    /**
33
     * @var ControllerHelperInterface
34
     */
35
    private $controllerHelper;
36
37
    /**
38
     * @var Serializable
39
     */
40
    private $innerController;
41
42
    /**
43
     * @var ArgumentCompilerInterface
44
     */
45
    private $argumentBuilder;
46
47
    public function setUp()
48
    {
49
        $this->controllerHelper = $this->createMock(ControllerHelperInterface::class);
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->createMock(\Addik...HelperInterface::class) of type object<PHPUnit\Framework\MockObject\MockObject> is incompatible with the declared type object<Addiks\SymfonyGen...trollerHelperInterface> of property $controllerHelper.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
50
        $this->innerController = $this->createMock(Serializable::class);
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->createMock(\Serializable::class) of type object<PHPUnit\Framework\MockObject\MockObject> is incompatible with the declared type object<Serializable> of property $innerController.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
51
        $this->argumentBuilder = $this->createMock(ArgumentCompilerInterface::class);
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->createMock(\Addik...mpilerInterface::class) of type object<PHPUnit\Framework\MockObject\MockObject> is incompatible with the declared type object<Addiks\SymfonyGen...umentCompilerInterface> of property $argumentBuilder.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
52
    }
53
54
    /**
55
     * @test
56
     */
57
    public function shouldexecuteInnerControllerSafely()
58
    {
59
        $controller = new GenericExceptionResponseController($this->controllerHelper, $this->argumentBuilder, [
60
            'inner-controller' => $this->innerController,
61
            'inner-controller-method' => "serialize",
62
        ]);
63
64
        $this->innerController->method("serialize")->willReturn(new Response("foo", 205));
65
66
        /** @var Request $request */
67
        $request = $this->createMock(Request::class);
68
69
        /** @var Response $response */
70
        $response = $controller->executeInnerControllerSafely($request);
71
72
        $this->assertEquals("foo", $response->getContent());
73
        $this->assertEquals(205, $response->getStatusCode());
74
    }
75
76
    /**
77
     * @test
78
     */
79 View Code Duplication
    public function shouldOverrideSuccessResponse()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
80
    {
81
        $controller = new GenericExceptionResponseController($this->controllerHelper, $this->argumentBuilder, [
82
            'inner-controller' => $this->innerController,
83
            'inner-controller-method' => "serialize",
84
            'success-response' => "Some success!",
85
            'success-response-code' => 234,
86
        ]);
87
88
        $this->innerController->method("serialize")->willReturn(new Response("foo", 205));
89
90
        /** @var Request $request */
91
        $request = $this->createMock(Request::class);
92
93
        /** @var Response $response */
94
        $response = $controller->executeInnerControllerSafely($request);
95
96
        $this->assertEquals("Some success!", $response->getContent());
97
        $this->assertEquals(234, $response->getStatusCode());
98
    }
99
100
    /**
101
     * @test
102
     */
103 View Code Duplication
    public function shouldOverrideSuccessResponseWithDefaultResponseCode()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
104
    {
105
        $controller = new GenericExceptionResponseController($this->controllerHelper, $this->argumentBuilder, [
106
            'inner-controller' => $this->innerController,
107
            'inner-controller-method' => "serialize",
108
            'success-response' => "Some success!",
109
        ]);
110
111
        $this->innerController->method("serialize")->willReturn(new Response("foo", 205));
112
113
        /** @var Request $request */
114
        $request = $this->createMock(Request::class);
115
116
        /** @var Response $response */
117
        $response = $controller->executeInnerControllerSafely($request);
118
119
        $this->assertEquals("Some success!", $response->getContent());
120
        $this->assertEquals(200, $response->getStatusCode());
121
    }
122
123
    /**
124
     * @test
125
     */
126
    public function shouldTriggerSuccessFlashMessage()
127
    {
128
        $controller = new GenericExceptionResponseController($this->controllerHelper, $this->argumentBuilder, [
129
            'inner-controller' => $this->innerController,
130
            'inner-controller-method' => "serialize",
131
            'success-flash-message' => 'Some Success Message!'
132
        ]);
133
134
        $this->controllerHelper->expects($this->once())->method('addFlashMessage')->with(
0 ignored issues
show
Bug introduced by
The method expects() does not seem to exist on object<Addiks\SymfonyGen...trollerHelperInterface>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
135
            $this->equalTo('Some Success Message!'),
136
            $this->equalTo('success')
137
        );
138
139
        $this->innerController->method("serialize")->willReturn(new Response("foo", 200));
140
141
        /** @var Request $request */
142
        $request = $this->createMock(Request::class);
143
144
        $controller->executeInnerControllerSafely($request);
145
    }
146
147
    /**
148
     * @test
149
     */
150
    public function shouldAddFlashMessageUponException()
151
    {
152
        $controller = new GenericExceptionResponseController($this->controllerHelper, $this->argumentBuilder, [
153
            'inner-controller' => $this->innerController,
154
            'inner-controller-method' => "serialize",
155
            'exception-responses' => [
156
                InvalidArgumentException::class => [
157
                    'flash-type' => 'danger',
158
                    'flash-message' => 'Something happened: %s'
159
                ]
160
            ]
161
        ]);
162
163
        $this->innerController->method("serialize")->will($this->returnCallback(
164
            function () {
165
                throw new InvalidArgumentException("Lorem ipsum!");
166
            }
167
        ));
168
169
        $this->controllerHelper->expects($this->once())->method('handleException');
0 ignored issues
show
Bug introduced by
The method expects() does not seem to exist on object<Addiks\SymfonyGen...trollerHelperInterface>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
170
        $this->controllerHelper->expects($this->once())->method('addFlashMessage')->with(
0 ignored issues
show
Bug introduced by
The method expects() does not seem to exist on object<Addiks\SymfonyGen...trollerHelperInterface>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
171
            $this->equalTo('Something happened: Lorem ipsum!'),
172
            $this->equalTo('danger')
173
        );
174
175
        /** @var Request $request */
176
        $request = $this->createMock(Request::class);
177
178
        /** @var Response $response */
179
        $response = $controller->executeInnerControllerSafely($request);
180
181
        $this->assertEquals("Lorem ipsum!", $response->getContent());
182
        $this->assertEquals(500, $response->getStatusCode());
183
    }
184
185
    /**
186
     * @test
187
     */
188
    public function shouldForwardThrowExceptionIfNotHandled()
189
    {
190
        /** @var mixed $controller */
191
        $controller = new GenericExceptionResponseController($this->controllerHelper, $this->argumentBuilder, [
192
            'inner-controller' => $this->innerController,
193
            'inner-controller-method' => "serialize",
194
        ]);
195
196
        $this->innerController->method("serialize")->will($this->returnCallback(
197
            function () {
198
                throw new InvalidArgumentException("Lorem ipsum!");
199
            }
200
        ));
201
202
        $this->expectException(InvalidArgumentException::class);
203
204
        /** @var Request $request */
205
        $request = $this->createMock(Request::class);
206
207
        $controller->executeInnerControllerSafely($request);
208
    }
209
210
    /**
211
     * @test
212
     */
213 View Code Duplication
    public function shouldThrowExceptionIfInnerControllerDidNotReturnAResponse()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
214
    {
215
        $controller = new GenericExceptionResponseController($this->controllerHelper, $this->argumentBuilder, [
216
            'inner-controller' => $this->innerController,
217
            'inner-controller-method' => "serialize",
218
        ]);
219
220
        $this->expectException(InvalidArgumentException::class);
221
222
        /** @var Request $request */
223
        $request = $this->createMock(Request::class);
224
225
        $controller->executeInnerControllerSafely($request);
226
    }
227
228
    /**
229
     * @test
230
     */
231
    public function shouldThrowExceptionIfHandledExceptionClassIsNotException()
232
    {
233
        $this->expectException(InvalidArgumentException::class);
234
235
        $controller = new GenericExceptionResponseController($this->controllerHelper, $this->argumentBuilder, [
0 ignored issues
show
Unused Code introduced by
$controller is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
236
            'inner-controller' => $this->innerController,
237
            'inner-controller-method' => "serialize",
238
            'exception-responses' => [
239
                "TotallyNotAnException" => [
240
                    'flash-type' => 'danger',
241
                    'flash-message' => 'Something happened: %s'
242
                ]
243
            ]
244
        ]);
245
    }
246
247
    /**
248
     * @test
249
     */
250
    public function shouldHandleThrowables()
251
    {
252
        $controller = new GenericExceptionResponseController($this->controllerHelper, $this->argumentBuilder, [
253
            'inner-controller' => $this->innerController,
254
            'inner-controller-method' => "serialize",
255
            'exception-responses' => [
256
                DivisionByZeroError::class => [
257
                    'flash-type' => 'danger',
258
                    'flash-message' => 'Something happened: %s'
259
                ]
260
            ]
261
        ]);
262
263
        $this->innerController->method("serialize")->will($this->returnCallback(
264
            function () {
265
                throw new DivisionByZeroError("Lorem ipsum");
0 ignored issues
show
Unused Code introduced by
The call to DivisionByZeroError::__construct() has too many arguments starting with 'Lorem ipsum'.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
266
            }
267
        ));
268
269
        /** @var Request $request */
270
        $request = $this->createMock(Request::class);
271
272
        /** @var Response $response */
273
        $response = $controller->executeInnerControllerSafely($request);
274
275
        $this->assertEquals("Lorem ipsum", $response->getContent());
276
    }
277
278
    /**
279
     * @test
280
     */
281
    public function shouldRejectNonObjectInnerController()
282
    {
283
        $this->expectException(InvalidArgumentException::class);
284
285
        $controller = new GenericExceptionResponseController($this->controllerHelper, $this->argumentBuilder, [
0 ignored issues
show
Unused Code introduced by
$controller is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
286
            'inner-controller' => false,
287
            'inner-controller-method' => "serialize",
288
        ]);
289
    }
290
291
    /**
292
     * @test
293
     */
294
    public function shouldRejectControllerBeingCalledAgain()
295
    {
296
        $this->expectException(InvalidArgumentException::class);
297
298
        $controller = new GenericExceptionResponseController($this->controllerHelper, $this->argumentBuilder, [
299
            'inner-controller' => $this->innerController,
300
            'inner-controller-method' => "serialize",
301
        ]);
302
303
        $controller->__construct($this->controllerHelper, $this->argumentBuilder, [
304
            'inner-controller' => $this->innerController,
305
            'inner-controller-method' => "serialize",
306
        ]);
307
    }
308
309
    /**
310
     * @test
311
     */
312
    public function shouldRedirectFromException()
313
    {
314
        /** @var mixed $controller */
315
        $controller = new GenericExceptionResponseController($this->controllerHelper, $this->argumentBuilder, [
316
            'inner-controller' => $this->innerController,
317
            'inner-controller-method' => "serialize",
318
            'exception-responses' => [
319
                InvalidArgumentException::class => [
320
                    'redirect-route' => 'some_redirect_route',
321
                    'redirect-route-parameters' => [
322
                        'foo' => 'bar'
323
                    ]
324
                ]
325
            ]
326
        ]);
327
328
        $this->innerController->method("serialize")->will($this->returnCallback(
329
            function () {
330
                throw new InvalidArgumentException("Lorem ipsum!");
331
            }
332
        ));
333
334
        /** @var RedirectResponse $redirectResponse */
335
        $redirectResponse = $this->createMock(RedirectResponse::class);
336
337
        $this->controllerHelper->expects($this->once())->method('handleException');
0 ignored issues
show
Bug introduced by
The method expects() does not seem to exist on object<Addiks\SymfonyGen...trollerHelperInterface>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
338
        $this->controllerHelper->expects($this->once())->method('redirectToRoute')->with(
0 ignored issues
show
Bug introduced by
The method expects() does not seem to exist on object<Addiks\SymfonyGen...trollerHelperInterface>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
339
            $this->equalTo('some_redirect_route'),
340
            $this->equalTo([]),
341
            $this->equalTo(301)
342
        )->willReturn($redirectResponse);
343
344
        /** @var Request $request */
345
        $request = $this->createMock(Request::class);
346
347
        /** @var Response $response */
348
        $response = $controller->executeInnerControllerSafely($request);
349
350
        $this->assertSame($redirectResponse, $response);
351
    }
352
353
}
354