Issues (99)

test/Mvc/RouterTest.php (5 issues)

1
<?php
2
/**
3
 * DronePHP (http://www.dronephp.com)
4
 *
5
 * @link      http://github.com/Pleets/DronePHP
6
 * @copyright Copyright (c) 2016-2018 Pleets. (http://www.pleets.org)
7
 * @license   http://www.dronephp.com/license
8
 * @author    Darío Rivera <[email protected]>
9
 */
10
11
namespace DroneTest\Util;
12
13
use Drone\Mvc\AbstractController;
14
use Drone\Mvc\Exception\MethodExecutionNotAllowedException;
15
use Drone\Mvc\Exception\RouteNotFoundException;
16
use Drone\Mvc\ModuleFactory;
17
use Drone\Mvc\Router;
18
use PHPUnit\Framework\TestCase;
19
20
class RouterTest extends TestCase
21
{
22
    /**
23
     * Tests if the router can create an instance of a class
24
     *
25
     * @return null
26
     */
27
    public function testSimpleRouteMatch()
28
    {
29
        $router = new Router();
30
31
        $router->addRoute([
32
            'App1' => [
33
                'module'     => 'App',
34
                'controller' => 'Index',
35
                'view'       => 'home',
36
            ],
37
        ]);
38
39
        $router->setIdentifiers('App', 'Index', 'home');
40
        $router->match();
41
42
        $ctrl = $router->getController();
43
44
        $this->assertEquals("App\Index", get_class($ctrl));
45
    }
46
47
    /**
48
     * Tests if the router can create an instance of a class when the route does not exists
49
     *
50
     * @return null
51
     */
52
    public function testSimpleRouteMatchFail()
53
    {
54
        $router = new Router();
55
56
        $router->addRoute([
57
            'App1' => [
58
                'module'     => 'MyApp',
59
                'controller' => 'IndexController',
60
                'view'       => 'home',
61
            ],
62
        ]);
63
64
        $router->setIdentifiers('App', 'Index', 'home');
65
66
        $errorObject = null;
67
68
        try {
69
            $router->match();
70
        } catch (\Exception $e) {
71
            $errorObject = ($e instanceof RouteNotFoundException);
72
        } finally {
73
            $this->assertTrue($errorObject, $e->getMessage());
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $e does not seem to be defined for all execution paths leading up to this point.
Loading history...
74
        }
75
    }
76
77
    /**
78
     * Tests if the router can create an instance of a class by a default route
79
     *
80
     * @return null
81
     */
82
    public function testDefaultRouteMatch()
83
    {
84
        $router = new Router();
85
86
        $router->addRoute([
87
            'AppRoute1' => [
88
                'module'     => 'App',
89
                'controller' => 'Index',
90
                'view'       => 'home',
91
            ],
92
        ]);
93
94
        $router->addRoute([
95
            'AppRoute2' => [
96
                'module'     => 'App',
97
                'controller' => 'Index2',
98
                'view'       => 'home',
99
            ],
100
        ]);
101
102
        $router->setDefaults('App', 'Index', 'home');
103
        $router->match();
104
        $ctrl = $router->getController();
105
106
        $this->assertEquals("App\Index", get_class($ctrl));
107
108
        $router->setIdentifiers('App', 'Index2', 'home');
109
        $router->match();
110
        $ctrl = $router->getController();
111
112
        $this->assertEquals("App\Index2", get_class($ctrl));
113
    }
114
115
    /**
116
     * Tests if the router can create an instance of a class with non-default class name builder
117
     *
118
     * @return null
119
     */
120
    public function testSimpleRouteMatchWithParticularName()
121
    {
122
        $router = new Router();
123
124
        $router->addRoute([
125
            'App3' => [
126
                'module'     => 'App',
127
                'controller' => 'Index',
128
                'view'       => 'about',
129
            ],
130
        ]);
131
132
        $router->setIdentifiers('App', 'Index', 'about');
133
134
        $router->setClassNameBuilder(function ($module, $class) {
135
            return "\\$module\Controller\\$class";
136
        });
137
138
        $router->match();
139
140
        $ctrl = $router->getController();
141
142
        $this->assertEquals("App\Controller\Index", get_class($ctrl));
143
    }
144
145
    /**
146
     * Tests method execution behaviour handled by the a module
147
     *
148
     * @return null
149
     */
150
    public function testModuleAndControllerComposition()
151
    {
152
        $router = new Router();
153
154
        $router->addRoute([
155
            'App4' => [
156
                'module'     => 'App',
157
                'controller' => 'Index',
158
                'view'       => 'about',
159
            ],
160
        ]);
161
162
        $router->setIdentifiers('App', 'Index', 'about');
163
164
        $router->setClassNameBuilder(function ($module, $class) {
165
            return "\\$module\Controller\\$class";
166
        });
167
168
        $router->match();
169
170
        # inject the module dependency to the controller
171
        $router->getController()->setModule(ModuleFactory::create("App"));
0 ignored issues
show
Drone\Mvc\ModuleFactory::create('App') of type null is incompatible with the type Drone\Mvc\AbstractModule expected by parameter $module of Drone\Mvc\AbstractController::setModule(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

171
        $router->getController()->setModule(/** @scrutinizer ignore-type */ ModuleFactory::create("App"));
Loading history...
Are you sure the usage of Drone\Mvc\ModuleFactory::create('App') targeting Drone\Mvc\ModuleFactory::create() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
172
173
        $this->assertNotTrue($router->getController()->getModule()->executionIsAllowed());
0 ignored issues
show
Are you sure the usage of $router->getController()...)->executionIsAllowed() targeting Drone\Mvc\AbstractModule::executionIsAllowed() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
174
175
        $errorObject = null;
176
177
        try {
178
            $router->run();
179
        } catch (\Exception $e) {
180
            $errorObject = ($e instanceof MethodExecutionNotAllowedException);
181
        } finally {
182
            $this->assertTrue($errorObject, $e->getMessage());
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $e does not seem to be defined for all execution paths leading up to this point.
Loading history...
183
        }
184
185
        $router->getController()->getModule()->allowExecution();
186
187
        # returns the result of the method execution in the matched controller
188
        $result = $router->run();
189
190
        $expected = ["foo" => "bar"];
191
        $this->assertSame($expected, $result);
192
    }
193
}
194
195
/*
196
|--------------------------------------------------------------------------
197
| Controller classes
198
|--------------------------------------------------------------------------
199
|
200
| This are simple controllers implementing AbstractController.
201
|
202
*/
203
204
namespace App;
205
206
use Drone\Mvc\AbstractController;
207
208
class Index extends AbstractController
209
{
210
    public function home()
211
    {
212
        return [];
213
    }
214
}
215
216
class Index2 extends AbstractController
217
{
218
    public function home()
219
    {
220
        return [];
221
    }
222
}
223
224
/*
225
|--------------------------------------------------------------------------
226
| Another Controller class
227
|--------------------------------------------------------------------------
228
|
229
| This is a simple controller implementing AbstractController. In order to
230
| build a framework behavior, we need all classes inside Controller namespace.
231
|
232
*/
233
234
namespace App\Controller;
235
236
use Drone\Mvc\AbstractController;
237
238
class Index extends AbstractController
239
{
240
    public function about()
241
    {
242
        return ['foo' => 'bar'];
243
    }
244
}
245
246
/*
247
|--------------------------------------------------------------------------
248
| Module Class
249
|--------------------------------------------------------------------------
250
|
251
| Each module could have a Module class that handles method execution. It's
252
| useful for execute some code before method execution or for stop it.
253
|
254
*/
255
256
namespace App;
257
258
use Drone\Mvc\AbstractModule;
259
260
class Module extends AbstractModule
261
{
262
    public function init()
263
    {
264
        # disallowing method execution
265
        $this->disallowExecution();
266
    }
267
}
268