Completed
Push — master ( e54ea7...7cecbb )
by Oleg
05:53
created

BuilderTest::testGroup()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 12
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 1 Features 0
Metric Value
c 2
b 1
f 0
dl 0
loc 12
rs 9.4285
cc 1
eloc 7
nc 1
nop 0
1
<?php
2
namespace Malezha\Menu\Tests;
3
4
use Malezha\Menu\Contracts\Attributes;
5
use Malezha\Menu\Contracts\Builder;
6
use Malezha\Menu\Contracts\Item;
7
8
/**
9
 * Class BuilderTest
10
 * @package Malezha\Menu\Tests
11
 */
12
class BuilderTest extends TestCase
13
{
14
    /**
15
     * @return Builder
16
     */
17
    protected function builderFactory()
18
    {
19
        return $this->app->make(Builder::class, [
20
            'name' => 'test', 
21
            'activeAttributes' => $this->app->make(Attributes::class, ['attributes' => ['class' => 'active']]),
22
            'attributes' => $this->app->make(Attributes::class, ['attributes' => ['class' => 'menu']]),
23
        ]);
24
    }
25
    
26
    public function testConstructor()
27
    {
28
        $builder = $this->builderFactory();
29
30
        $this->assertAttributeEquals($this->app, 'container', $builder);
31
        $this->assertAttributeEquals('test', 'name', $builder);
32
        $this->assertAttributeEquals(Builder::UL, 'type', $builder);
33
        $this->assertAttributeInstanceOf(Attributes::class, 'attributes', $builder);
34
        $this->assertAttributeInternalType('array', 'items', $builder);
35
        $this->assertAttributeInstanceOf(Attributes::class, 'activeAttributes', $builder);
36
    }
37
38
    public function testCreate()
39
    {
40
        $builder = $this->builderFactory();
41
42
        $item = $builder->create('index', 'Index', '/', ['class' => 'main-menu'], ['class' => 'link'],
43
            function(Item $item) {
44
                $this->assertAttributeEquals('Index', 'title', $item->getLink());
45
                $item->getLink()->setTitle('Home');
46
            });
47
48
        $this->assertAttributeEquals($builder, 'builder', $item);
49
        $this->assertAttributeInstanceOf(Attributes::class, 'attributes', $item);
50
51
        $link = $item->getLink();
52
        $this->assertAttributeEquals('Home', 'title', $link);
53
        $this->assertAttributeEquals('/', 'url', $link);
54
    }
55
    
56 View Code Duplication
    public function testGet()
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...
57
    {
58
        $builder = $this->builderFactory();
59
        
60
        $item = $builder->create('test', 'Test', '/test');
61
        
62
        $this->assertEquals($item, $builder->get('test'));
63
        $this->assertEquals(null, $builder->get('notFound'));
64
    }
65
    
66
    public function testHas()
67
    {
68
        $builder = $this->builderFactory();
69
70
        $this->assertFalse($builder->has('test'));
71
    }
72
    
73
    public function testType()
74
    {
75
        $builder = $this->builderFactory();
76
        
77
        $this->assertEquals(Builder::UL, $builder->getType());
78
        $builder->setType(Builder::OL);
79
        $this->assertAttributeEquals(Builder::OL, 'type', $builder);
80
    }
81
    
82 View Code Duplication
    public function testAll()
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...
83
    {
84
        $builder = $this->builderFactory();
85
        
86
        $this->assertEquals([], $builder->all());
87
        $item = $builder->create('test', 'Test', '/test');
88
        $this->assertEquals(['test' => $item], $builder->all());
89
    }
90
    
91
    public function testForget()
92
    {
93
        $builder = $this->builderFactory();
94
95
        $builder->create('test', 'Test', '/test');
96
        $this->assertTrue($builder->has('test'));
97
        $builder->forget('test');
98
        $this->assertFalse($builder->has('test'));
99
    }
100
    
101
    public function testActiveAttributes()
102
    {
103
        $builder = $this->builderFactory();
104
        $activeAttributes = $builder->activeAttributes();
105
        
106
        $this->assertInstanceOf(Attributes::class, $activeAttributes);
107
108
        $result = $builder->activeAttributes(function(Attributes $attributes) {
109
            $this->assertInstanceOf(Attributes::class, $attributes);
110
            
111
            return $attributes->get('class');
112
        });
113
        
114
        $this->assertEquals('active', $result);
115
    }
116
    
117
    public function testSubMenu()
118
    {
119
        $builder = $this->builderFactory();
120
        
121
        $group = $builder->submenu('test', function(Item $item) use ($builder) {
122
            $this->assertAttributeEquals($builder, 'builder', $item);
123
        }, function(Builder $menu) use ($builder) {
124
            $this->assertEquals($builder->activeAttributes()->all(), $menu->activeAttributes()->all());
125
        });
126
127
        $this->assertEquals($group, $builder->get('test'));
128
    }
129
130
    public function testRender()
131
    {
132
        $builder = $this->builderFactory();
133
134
        $index = $builder->create('index', 'Index Page', url('/'));
135
        $index->getLink()->getAttributes()->push(['class' => 'menu-link']);
136
137
        $builder->submenu('orders', function(Item $item) {
138
            $item->getAttributes()->push(['class' => 'child-menu']);
139
            
140
            $link = $item->getLink();
141
            $link->setTitle('Orders');
142
            $link->setUrl('javascript:;');
143
144 View Code Duplication
        }, function(Builder $menu) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
145
            $menu->create('all', 'All', url('/orders/all'));
0 ignored issues
show
Bug introduced by
It seems like url('/orders/all') targeting url() can also be of type object<Illuminate\Contracts\Routing\UrlGenerator>; however, Malezha\Menu\Contracts\Builder::create() does only seem to accept string, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
146
            $menu->create('type_1', 'Type 1', url('/orders/1'), [], ['class' => 'text-color-red']);
0 ignored issues
show
Bug introduced by
It seems like url('/orders/1') targeting url() can also be of type object<Illuminate\Contracts\Routing\UrlGenerator>; however, Malezha\Menu\Contracts\Builder::create() does only seem to accept string, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
147
148
            $menu->create('type_2', 'Type 2', url('/orders/2'), [], [], function(Item $item) {
0 ignored issues
show
Bug introduced by
It seems like url('/orders/2') targeting url() can also be of type object<Illuminate\Contracts\Routing\UrlGenerator>; however, Malezha\Menu\Contracts\Builder::create() does only seem to accept string, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
149
                $item->getLink()->getAttributes()->push(['data-attribute' => 'value']);
150
            });
151
        });
152
        
153
        $html = $builder->render();
154
        $file = file_get_contents(__DIR__ . '/stub/menu.html');
155
        
156
        $this->assertEquals($file, $html);
157
    }
158
    
159
    public function testDisplayRules()
160
    {
161
        $builder = $this->builderFactory();
162
163
        $builder->create('index', 'Index Page', url('/'));
164
        $builder->create('login', 'Login', url('/login'))->setDisplayRule(function() {
0 ignored issues
show
Bug introduced by
It seems like url('/login') targeting url() can also be of type object<Illuminate\Contracts\Routing\UrlGenerator>; however, Malezha\Menu\Contracts\Builder::create() does only seem to accept string, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
165
            return true;
166
        });
167
        $builder->create('admin', 'Admin', url('/admin'))->setDisplayRule(false);
0 ignored issues
show
Bug introduced by
It seems like url('/admin') targeting url() can also be of type object<Illuminate\Contracts\Routing\UrlGenerator>; however, Malezha\Menu\Contracts\Builder::create() does only seem to accept string, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
168
        $builder->create('logout', 'Logout', url('/logout'))->setDisplayRule(null);
0 ignored issues
show
Bug introduced by
It seems like url('/logout') targeting url() can also be of type object<Illuminate\Contracts\Routing\UrlGenerator>; however, Malezha\Menu\Contracts\Builder::create() does only seem to accept string, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
169
170
        $html = $builder->render();
171
        $file = file_get_contents(__DIR__ . '/stub/display_rules.html');
172
173
        $this->assertEquals($file, $html);
174
    }
175
176
    public function testAnotherViewRender()
177
    {
178
        view()->addLocation(__DIR__ . '/stub');
179
        $this->app['config']->prepend('menu.paths', __DIR__ . '/stub');
180
        
181
        $builder = $this->builderFactory();
182
        $builder->create('index', 'Index Page', url('/'));
183
        $builder->submenu('group', function(Item $item){}, function(Builder $menu) {
0 ignored issues
show
Unused Code introduced by
The parameter $item is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
184
            $menu->create('one', 'One', url('/one'));
0 ignored issues
show
Bug introduced by
It seems like url('/one') targeting url() can also be of type object<Illuminate\Contracts\Routing\UrlGenerator>; however, Malezha\Menu\Contracts\Builder::create() does only seem to accept string, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
185
        });
186
187
        $html = $builder->render('another');
188
        $file = file_get_contents(__DIR__ . '/stub/another_menu.html');
189
        $this->assertEquals($file, $html);
190
191
        $builder->get('group')->getMenu()->setView('another');
0 ignored issues
show
Bug introduced by
The method getMenu does only exist in Malezha\Menu\Contracts\SubMenu, but not in Malezha\Menu\Contracts\Item.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
192
        $html = $builder->render();
193
        $file = file_get_contents(__DIR__ . '/stub/another_sub_menu.html');
194
        $this->assertEquals($file, $html);
195
196
        $builder->setView('another');
197
        $builder->get('group')->getMenu()->setView('menu::view');
198
        $html = $builder->render();
199
        $file = file_get_contents(__DIR__ . '/stub/another_set_view_menu.html');
200
        $this->assertEquals($file, $html);
201
    }
202
}