Completed
Push — master ( 1de9b7...830752 )
by Kristof
38:46 queued 24:09
created

MenuBuilderTest   A

Complexity

Total Complexity 8

Size/Duplication

Total Lines 192
Duplicated Lines 11.98 %

Coupling/Cohesion

Components 1
Dependencies 10

Importance

Changes 0
Metric Value
wmc 8
lcom 1
cbo 10
dl 23
loc 192
rs 10
c 0
b 0
f 0

8 Methods

Rating   Name   Duplication   Size   Complexity  
A setUp() 0 18 1
A testGetCurrent() 0 18 1
A testGetBreadcrumbs() 0 13 1
A testGetLowestTopChild() 11 11 1
A testGetLowestTopChildNonTop() 0 14 1
A testAdaptChildren() 0 18 1
A testModulesMenuAdaptor() 12 12 1
A testSimpleMenuAdaptor() 0 46 1

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

1
<?php
2
3
namespace Kunstmaan\AdminBundle\Tests\Helper\Menu;
4
5
use Kunstmaan\AdminBundle\Helper\Menu\MenuBuilder;
6
use Kunstmaan\AdminBundle\Helper\Menu\ModulesMenuAdaptor;
7
use Kunstmaan\AdminBundle\Helper\Menu\SettingsMenuAdaptor;
8
use Kunstmaan\AdminBundle\Helper\Menu\SimpleMenuAdaptor;
9
use Kunstmaan\AdminBundle\Helper\Menu\TopMenuItem;
10
use Kunstmaan\MenuBundle\Entity\MenuItem;
11
use Kunstmaan\AdminBundle\Helper\Menu\MenuItem as MenuItemHelper;
12
use PHPUnit\Framework\TestCase;
13
use ReflectionClass;
14
use Symfony\Component\DependencyInjection\ContainerInterface;
15
use Symfony\Component\HttpFoundation\Request;
16
use Symfony\Component\HttpFoundation\RequestStack;
17
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
18
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
19
20
class MenuBuilderTest extends TestCase
21
{
22
    /**
23
     * @var MenuBuilder
24
     */
25
    protected $object;
26
27
    /**
28
     * @var ContainerInterface (mock)
29
     */
30
    protected $container;
31
32
    /**
33
     * @var AuthorizationCheckerInterface (mock)
34
     */
35
    protected $authCheck;
36
37
    /**
38
     * @var RequestStack (mock)
39
     */
40
    protected $stack;
41
42
    protected function setUp()
43
    {
44
        $storage = $this->createMock(TokenStorageInterface::class);
45
        $authCheck = $this->createMock(AuthorizationCheckerInterface::class);
46
        $authCheck->tokenStorage = $storage;
0 ignored issues
show
Bug introduced by
Accessing tokenStorage on the interface PHPUnit\Framework\MockObject\MockObject suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
47
        $this->authCheck = $authCheck;
0 ignored issues
show
Documentation Bug introduced by
It seems like $authCheck of type object<PHPUnit\Framework\MockObject\MockObject> is incompatible with the declared type object<Symfony\Component...zationCheckerInterface> of property $authCheck.

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...
48
        $container = $this->createMock(ContainerInterface::class);
49
        $stack = $this->createMock(RequestStack::class);
50
        $this->stack = $stack;
0 ignored issues
show
Documentation Bug introduced by
It seems like $stack of type object<PHPUnit\Framework\MockObject\MockObject> is incompatible with the declared type object<Symfony\Component...oundation\RequestStack> of property $stack.

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
52
        $container->expects($this->any())->method('getParameter')->willReturn(true);
53
        $container->expects($this->any())->method('get')->will($this->onConsecutiveCalls(
54
            $stack, $stack, $authCheck
55
        ));
56
57
        $this->container = $container;
0 ignored issues
show
Documentation Bug introduced by
It seems like $container of type object<PHPUnit\Framework\MockObject\MockObject> is incompatible with the declared type object<Symfony\Component...ion\ContainerInterface> of property $container.

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...
58
        $this->object = new MenuBuilder($container);
0 ignored issues
show
Documentation introduced by
$container is of type object<PHPUnit\Framework\MockObject\MockObject>, but the function expects a object<Symfony\Component...ion\ContainerInterface>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
59
    }
60
61
    /**
62
     * @throws \ReflectionException
63
     */
64
    public function testGetCurrent()
65
    {
66
        $this->stack->expects($this->atLeastOnce())
0 ignored issues
show
Bug introduced by
The method expects() does not seem to exist on object<Symfony\Component...oundation\RequestStack>.

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...
67
            ->method('getCurrentRequest')
68
            ->willReturn(new Request([], [], ['_route' => 'KunstmaanAdminBundle_settings']));
69
        $this->authCheck->expects($this->any())->method('isGranted')->willReturn(true);
0 ignored issues
show
Bug introduced by
The method expects() does not seem to exist on object<Symfony\Component...zationCheckerInterface>.

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...
70
        $adapter = new SettingsMenuAdaptor($this->authCheck, true);
71
        $this->object->addAdaptMenu($adapter);
72
        $current = $this->object->getCurrent();
73
        $this->assertInstanceOf(TopMenuItem::class, $current);
74
75
        $mirror = new ReflectionClass(MenuBuilder::class);
76
        $property = $mirror->getProperty('currentCache');
77
        $property->setAccessible(true);
78
        $property->setValue($this->object, new MenuItem());
79
        $current = $this->object->getCurrent();
80
        $this->assertInstanceOf(MenuItem::class, $current);
81
    }
82
83
    public function testGetBreadcrumbs()
84
    {
85
        $this->stack->expects($this->atLeastOnce())
0 ignored issues
show
Bug introduced by
The method expects() does not seem to exist on object<Symfony\Component...oundation\RequestStack>.

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...
86
        ->method('getCurrentRequest')
87
        ->willReturn(new Request([], [], ['_route' => 'KunstmaanAdminBundle_settings']));
88
        $this->authCheck->expects($this->any())->method('isGranted')->willReturn(true);
0 ignored issues
show
Bug introduced by
The method expects() does not seem to exist on object<Symfony\Component...zationCheckerInterface>.

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...
89
        $adapter = new SettingsMenuAdaptor($this->authCheck, true);
90
        $this->object->addAdaptMenu($adapter);
91
        $crumb = $this->object->getBreadCrumb();
92
        $this->assertTrue(is_array($crumb));
93
        $this->assertCount(1, $crumb);
0 ignored issues
show
Documentation introduced by
$crumb is of type array<integer,object<Kun...\Helper\Menu\MenuItem>>, but the function expects a object<Countable>|object...nit\Framework\iterable>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
94
        $this->assertInstanceOf(TopMenuItem::class, $crumb[0]);
95
    }
96
97 View Code Duplication
    public function testGetLowestTopChild()
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...
98
    {
99
        $this->stack->expects($this->atLeastOnce())
0 ignored issues
show
Bug introduced by
The method expects() does not seem to exist on object<Symfony\Component...oundation\RequestStack>.

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...
100
            ->method('getCurrentRequest')
101
            ->willReturn(new Request([], [], ['_route' => 'KunstmaanAdminBundle_settings']));
102
        $this->authCheck->expects($this->any())->method('isGranted')->willReturn(true);
0 ignored issues
show
Bug introduced by
The method expects() does not seem to exist on object<Symfony\Component...zationCheckerInterface>.

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...
103
        $adapter = new SettingsMenuAdaptor($this->authCheck, true);
104
        $this->object->addAdaptMenu($adapter);
105
        $lowest = $this->object->getLowestTopChild();
106
        $this->assertInstanceOf(TopMenuItem::class, $lowest);
107
    }
108
109
    /**
110
     * @throws \ReflectionException
111
     */
112
    public function testGetLowestTopChildNonTop()
113
    {
114
        $parent = new MenuItem();
115
        $child = new MenuItem();
116
        $child->setParent($parent);
117
118
        $mirror = new ReflectionClass(MenuBuilder::class);
119
        $property = $mirror->getProperty('currentCache');
120
        $property->setAccessible(true);
121
        $property->setValue($this->object, $child);
122
123
        $lowest = $this->object->getLowestTopChild();
124
        $this->assertNull($lowest);
125
    }
126
127
    /**
128
     * @throws \ReflectionException
129
     */
130
    public function testAdaptChildren()
131
    {
132
        $this->authCheck->expects($this->any())->method('isGranted')->willReturn(true);
0 ignored issues
show
Bug introduced by
The method expects() does not seem to exist on object<Symfony\Component...zationCheckerInterface>.

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...
133
134
        $parent = $this->createMock(MenuItemHelper::class);
135
        $parent->expects($this->exactly(2))->method('getRoute')->willReturn('KunstmaanAdminBundle_settings');
136
137
        $container = $this->createMock(ContainerInterface::class);
138
        $container->expects($this->any())->method('getParameter')->willReturn(true);
139
        $container->expects($this->any())->method('get')->willReturn($this->authCheck);
140
141
        $this->container = $container;
0 ignored issues
show
Documentation Bug introduced by
It seems like $container of type object<PHPUnit\Framework\MockObject\MockObject> is incompatible with the declared type object<Symfony\Component...ion\ContainerInterface> of property $container.

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...
142
        $this->object = new MenuBuilder($container);
0 ignored issues
show
Documentation introduced by
$container is of type object<PHPUnit\Framework\MockObject\MockObject>, but the function expects a object<Symfony\Component...ion\ContainerInterface>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
143
144
        $adapter = new SettingsMenuAdaptor($this->authCheck, true);
145
        $array = [];
146
        $adapter->adaptChildren($this->object, $array, $parent, new Request([], [], ['_route' => 'KunstmaanAdminBundle_settings_bundle_version']));
0 ignored issues
show
Documentation introduced by
$parent is of type object<PHPUnit\Framework\MockObject\MockObject>, but the function expects a null|object<Kunstmaan\Ad...e\Helper\Menu\MenuItem>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
147
    }
148
149 View Code Duplication
    public function testModulesMenuAdaptor()
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...
150
    {
151
        $this->stack->expects($this->atLeastOnce())
0 ignored issues
show
Bug introduced by
The method expects() does not seem to exist on object<Symfony\Component...oundation\RequestStack>.

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...
152
            ->method('getCurrentRequest')
153
            ->willReturn(new Request([], [], ['_route' => 'KunstmaanAdminBundle_modules']));
154
155
        $this->authCheck->expects($this->any())->method('isGranted')->willReturn(true);
0 ignored issues
show
Bug introduced by
The method expects() does not seem to exist on object<Symfony\Component...zationCheckerInterface>.

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...
156
        $adapter = new ModulesMenuAdaptor();
157
        $this->object->addAdaptMenu($adapter);
158
        $current = $this->object->getCurrent();
159
        $this->assertInstanceOf(TopMenuItem::class, $current);
160
    }
161
162
    /**
163
     * @throws \ReflectionException
164
     */
165
    public function testSimpleMenuAdaptor()
166
    {
167
        $this->stack->expects($this->atLeastOnce())
0 ignored issues
show
Bug introduced by
The method expects() does not seem to exist on object<Symfony\Component...oundation\RequestStack>.

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...
168
            ->method('getCurrentRequest')
169
            ->willReturn(new Request([], [], ['_route' => 'KunstmaanAdminBundle_modules']));
170
171
        $this->authCheck->expects($this->any())->method('isGranted')->willReturn(true);
0 ignored issues
show
Bug introduced by
The method expects() does not seem to exist on object<Symfony\Component...zationCheckerInterface>.

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...
172
        $adapter = new SimpleMenuAdaptor($this->authCheck, [[
173
            'label' => 'label',
174
            'parent' => null,
175
            'role' => 'ADMIN',
176
            'route' => 'KunstmaanAdminBundle_modules',
177
            'params' => ['x' => 'y'],
178
        ]]);
179
        $this->object->addAdaptMenu($adapter);
180
181
        $mirror = new ReflectionClass(MenuBuilder::class);
182
        $property = $mirror->getProperty('topMenuItems');
183
        $property->setAccessible(true);
184
185
        $helper = new MenuItemHelper($this->object);
186
        $helper->setActive(true);
187
        $property->setValue($this->object, [$helper]);
188
189
        $current = $this->object->getCurrent();
190
        $this->assertInstanceOf(TopMenuItem::class, $current);
191
192
        $mirror = new ReflectionClass(SimpleMenuAdaptor::class);
193
        $method = $mirror->getMethod('parentMatches');
194
        $method->setAccessible(true);
195
        $bool = $method->invoke($adapter, null, ['parent' => null]);
196
        $this->assertTrue($bool);
197
198
        $authCheck = $this->createMock(AuthorizationCheckerInterface::class);
199
        $authCheck->expects($this->any())->method('isGranted')->willReturn(false);
200
        $adapter = new SimpleMenuAdaptor($authCheck, [[
0 ignored issues
show
Documentation introduced by
$authCheck is of type object<PHPUnit\Framework\MockObject\MockObject>, but the function expects a object<Symfony\Component...zationCheckerInterface>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
201
            'label' => 'label',
202
            'parent' => null,
203
            'role' => 'ADMIN',
204
            'route' => 'KunstmaanAdminBundle_modules',
205
            'params' => ['x' => 'y'],
206
        ]]);
207
        $array = [];
208
        $adapter->adaptChildren($this->object, $array, null, new Request());
209
        $this->assertEmpty($array);
210
    }
211
}
212