Completed
Push — master ( c8d3eb...7bdd8d )
by Oleg
03:59
created

BuilderTest::testCreateCallbackException()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 9
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 1 Features 0
Metric Value
c 1
b 1
f 0
dl 0
loc 9
rs 9.6666
cc 1
eloc 5
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\Element\Link;
7
use Malezha\Menu\Element\SubMenu;
8
use Malezha\Menu\Element\Text;
9
use Malezha\Menu\Factory\LinkFactory;
10
use Malezha\Menu\Factory\SubMenuFactory;
11
use Malezha\Menu\Factory\TextFactory;
12
13
/**
14
 * Class BuilderTest
15
 * @package Malezha\Menu\Tests
16
 */
17
class BuilderTest extends TestCase
18
{
19
    /**
20
     * @return Builder
21
     */
22
    protected function builderFactory()
23
    {
24
        return $this->app->make(Builder::class, [
25
            'activeAttributes' => $this->app->make(Attributes::class, ['attributes' => ['class' => 'active']]),
26
            'attributes' => $this->app->make(Attributes::class, ['attributes' => ['class' => 'menu']]),
27
        ]);
28
    }
29
    
30
    protected function serializeStub()
31
    {
32
        return $this->getStub('serialized/builder.txt');
33
    }
34
    
35
    protected function toArrayStub()
36
    {
37
        return [
38
            'type' => 'ul',
39
            'view' => 'menu::view',
40
            'attributes' => [
41
                'class' => 'menu',
42
            ],
43
            'activeAttributes' => [
44
                'class' => 'active',
45
            ],
46
            'elements' => [
47
                'index' => [
48
                    'view' => 'menu::elements.link',
49
                    'title' => 'Index',
50
                    'url' => 'http://localhost',
51
                    'attributes' => [],
52
                    'activeAttributes' => [
53
                        'class' => 'active',
54
                    ],
55
                    'linkAttributes' => [],
56
                    'displayRule' => true,
57
                    'type' => 'link',
58
                ],
59
                'submenu' => [
60
                    'view' => 'menu::elements.submenu',
61
                    'title' => '',
62
                    'url' => '#',
63
                    'attributes' => [],
64
                    'activeAttributes' => [
65
                        'class' => 'active',
66
                    ],
67
                    'linkAttributes' => [],
68
                    'displayRule' => true,
69
                    'builder' => [
70
                        'type' => 'ul',
71
                        'view' => 'menu::view',
72
                        'attributes' => [],
73
                        'activeAttributes' => [],
74
                        'elements' => [
75
                            'item_1' => [
76
                                'view' => 'menu::elements.link',
77
                                'title' => 'Item 1',
78
                                'url' => 'http://localhost/item/1',
79
                                'attributes' => [],
80
                                'activeAttributes' => [],
81
                                'linkAttributes' => [],
82
                                'displayRule' => true,
83
                                'type' => 'link',
84
                            ],
85
                            'item_2' => [
86
                                'view' => 'menu::elements.link',
87
                                'title' => 'Item 2',
88
                                'url' => 'http://localhost/item/2',
89
                                'attributes' => [],
90
                                'activeAttributes' => [],
91
                                'linkAttributes' => [],
92
                                'displayRule' => true,
93
                                'type' => 'link',
94
                            ],
95
                            'item_3' => [
96
                                'view' => 'menu::elements.link',
97
                                'title' => 'Item 3',
98
                                'url' => 'http://localhost/item/3',
99
                                'attributes' => [],
100
                                'activeAttributes' => [],
101
                                'linkAttributes' => [],
102
                                'displayRule' => true,
103
                                'type' => 'link',
104
                            ],
105
                        ],
106
                    ],
107
                    'type' => 'submenu',
108
                ],
109
            ],
110
        ];
111
    }
112
    
113
    public function testConstructor()
114
    {
115
        $builder = $this->builderFactory();
116
117
        $this->assertAttributeEquals($this->app, 'app', $builder);
118
        $this->assertAttributeEquals(Builder::UL, 'type', $builder);
119
        $this->assertAttributeInstanceOf(Attributes::class, 'attributes', $builder);
120
        $this->assertAttributeInternalType('array', 'elements', $builder);
121
        $this->assertAttributeInstanceOf(Attributes::class, 'activeAttributes', $builder);
122
    }
123
124
    public function testCreate()
125
    {
126
        $builder = $this->builderFactory();
127
128
        /** @var LinkFactory $item */
129
        $item = $builder->create('index', Link::class, function(LinkFactory $factory) {
130
            $factory->title = 'Home';
131
            $factory->url = '/';
132
        });
133
134
        $this->assertAttributeEquals(['index' => $item], 'elements', $builder);
135
        $this->assertAttributeEquals(['index' => 0], 'indexes', $builder);
136
        $this->assertInstanceOf(LinkFactory::class, $item);
137
138
        $item = $item->build();
139
        $this->assertInstanceOf(Link::class, $item);
140
        $this->assertAttributeEquals('Home', 'title', $item);
141
        $this->assertAttributeEquals('/', 'url', $item);
142
    }
143
144
    public function testCreateIfExists()
145
    {
146
        $this->expectException(\RuntimeException::class);
147
        
148
        $builder = $this->builderFactory();
149
150
        $builder->create('index', Link::class,
151
            function (LinkFactory $factory) {});
0 ignored issues
show
Unused Code introduced by
The parameter $factory 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...
152
        $builder->create('index', SubMenu::class,
153
            function (SubMenuFactory $factory) {}); // Duplicate
0 ignored issues
show
Unused Code introduced by
The parameter $factory 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...
154
    }
155
    
156 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...
157
    {
158
        $builder = $this->builderFactory();
159
        
160
        $item = $builder->create('test', Link::class,
161
            function (LinkFactory $factory) {});
0 ignored issues
show
Unused Code introduced by
The parameter $factory 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...
162
        
163
        $this->assertEquals($item, $builder->get('test'));
164
        $this->assertEquals(null, $builder->get('notFound'));
165
        $this->assertEquals($item, $builder['test']);
166
        $this->assertEquals(null, $builder['notFound']);
167
    }
168
169 View Code Duplication
    public function testGetByIndex()
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...
170
    {
171
        $builder = $this->builderFactory();
172
173
        $item = $builder->create('test', Link::class,
174
            function (LinkFactory $factory) {});
0 ignored issues
show
Unused Code introduced by
The parameter $factory 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...
175
176
        $this->assertEquals($item, $builder->getByIndex(0));
177
        $this->assertEquals(null, $builder->getByIndex(1));
178
        $this->assertEquals($item, $builder[0]);
179
        $this->assertEquals(null, $builder[1]);
180
    }
181
    
182
    public function testHas()
183
    {
184
        $builder = $this->builderFactory();
185
186
        $this->assertFalse($builder->has('test'));
187
        $this->assertFalse(isset($builder['test']));
188
    }
189
    
190
    public function testType()
191
    {
192
        $builder = $this->builderFactory();
193
        
194
        $this->assertEquals(Builder::UL, $builder->getType());
195
        $builder->setType(Builder::OL);
196
        $this->assertAttributeEquals(Builder::OL, 'type', $builder);
197
    }
198
    
199
    public function testAll()
200
    {
201
        $builder = $this->builderFactory();
202
        
203
        $this->assertEquals([], $builder->all());
204
        $item = $builder->create('test', Link::class,
205
            function (LinkFactory $factory) {});
0 ignored issues
show
Unused Code introduced by
The parameter $factory 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...
206
        $this->assertEquals(['test' => $item], $builder->all());
207
    }
208
    
209
    public function testForget()
210
    {
211
        $builder = $this->builderFactory();
212
213
        $builder->create('test', Link::class,
214
            function (LinkFactory $factory) {});
0 ignored issues
show
Unused Code introduced by
The parameter $factory 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...
215
        $builder->create('another', Text::class,
216
            function (TextFactory $factory) {});
0 ignored issues
show
Unused Code introduced by
The parameter $factory 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...
217
        
218
        $this->assertTrue($builder->has('test'));
219
        $builder->forget('test');
220
        $this->assertFalse($builder->has('test'));
221
        
222
        $this->assertTrue($builder->has('another'));
223
        unset($builder['another']);
224
        $this->assertFalse($builder->has('another'));
225
    }
226
    
227
    public function testActiveAttributes()
228
    {
229
        $builder = $this->builderFactory();
230
        $activeAttributes = $builder->getActiveAttributes();
231
        
232
        $this->assertInstanceOf(Attributes::class, $activeAttributes);
233
234
        $result = $builder->getActiveAttributes(function(Attributes $attributes) {
235
            $this->assertInstanceOf(Attributes::class, $attributes);
236
            
237
            return $attributes->get('class');
238
        });
239
        
240
        $this->assertEquals('active', $result);
241
    }
242
243
    public function testRender()
244
    {
245
        $builder = $this->builderFactory();
246
247
        $builder->create('index', Link::class, function(LinkFactory $factory) {
248
            $factory->title = 'Index Page';
249
            $factory->url = url('/');
250
            $factory->linkAttributes->push(['class' => 'menu-link']);
251
        });
252
        
253 View Code Duplication
        $builder->create('orders', SubMenu::class, function(SubMenuFactory $factory) {
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...
254
            $factory->attributes->push(['class' => 'child-menu']);
255
            $factory->title = 'Orders';
256
            $factory->url = 'javascript:;';
257
            
258
            $factory->builder->create('all', Link::class, function(LinkFactory $factory) {
259
                $factory->title = 'All';
260
                $factory->url = url('/orders/all');
261
            });
262
            $factory->builder->create('type_1', Link::class, function(LinkFactory $factory) {
263
                $factory->title = 'Type 1';
264
                $factory->url = url('/orders/1');
265
                $factory->linkAttributes->push(['class' => 'text-color-red']);
266
            });
267
            $factory->builder->create('type_2', Link::class, function(LinkFactory $factory) {
268
                $factory->title = 'Type 2';
269
                $factory->url = url('/orders/2');
270
                $factory->linkAttributes->push(['data-attribute' => 'value']);
271
            });
272
        });
273
        
274
        $html = $builder->render();
275
        
276
        $this->assertEquals($this->getStub('menu.html'), $html);
277
    }
278
    
279
    public function testDisplayRules()
280
    {
281
        $builder = $this->builderFactory();
282
283
        $builder->create('index', Link::class, function(LinkFactory $factory) {
284
            $factory->title = 'Index Page';
285
            $factory->url = url('/');
286
        });
287
        $builder->create('login', Link::class, function(LinkFactory $factory) {
288
            $factory->title = 'Login';
289
            $factory->url = url('/login');
290
            $factory->displayRule = function() {
291
                return true;
292
            };
293
        });
294
        $builder->create('admin', Link::class, function(LinkFactory $factory) {
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...
295
            $factory->title = 'Admin';
296
            $factory->url = url('/admin');
297
            $factory->displayRule = false;
298
        });
299
        $builder->create('logout', Link::class, function(LinkFactory $factory) {
300
            $factory->title = 'Logout';
301
            $factory->url = url('/logout');
302
            $factory->displayRule = null;
303
        });
304
305
        $html = $builder->render();
306
307
        $this->assertEquals($this->getStub('display_rules.html'), $html);
308
    }
309
310
    public function testAnotherViewRender()
311
    {
312
        view()->addLocation(__DIR__ . '/stub');
313
        $this->app['config']->prepend('menu.paths', __DIR__ . '/stub');
314
        
315
        $builder = $this->builderFactory();
316
        $builder->create('index', Link::class, function(LinkFactory $factory) {
317
            $factory->title = 'Index Page';
318
            $factory->url = url('/');
319
        });
320 View Code Duplication
        $builder->create('group', SubMenu::class, function(SubMenuFactory $factory) {
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...
321
            $factory->builder->create('one', Link::class, function(LinkFactory $factory) {
322
                $factory->title = 'One';
323
                $factory->url = url('/one');
324
            });
325
326
            return $factory->build();
327
        });
328
        
329
        $this->assertEquals($this->getStub('another_menu.html'), $builder->render('another'));
330
331
        $builder->get('group')->getBuilder()->setView('another');
332
        $this->assertEquals($this->getStub('another_sub_menu.html'), $builder->render());
333
334
        $builder->setView('another');
335
        $builder->get('group')->getBuilder()->setView('menu::view');
336
        $this->assertEquals($this->getStub('another_set_view_menu.html'), $builder->render());
337
    }
338
    
339
    public function testInsert()
340
    {
341
        $builder = $this->builderFactory();
342
        $builder->create('index', Link::class, function(LinkFactory $factory) {
343
            $factory->title = 'Index Page';
344
            $factory->url = url('/');
345
        });
346
        $builder->create('logout', Link::class, function(LinkFactory $factory) {
347
            $factory->title = 'Logout';
348
            $factory->url = url('logout');
349
        });
350
        
351
        $builder->insertAfter('index', function (Builder $builder) {
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...
352
            $builder->create('users', Link::class, function(LinkFactory $factory) {
353
                $factory->title = 'Users';
354
                $factory->url = url('users');
355
            });
356
        });
357
        
358
        $builder->insertBefore('users', function (Builder $builder) {
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...
359
            $builder->create('profile', Link::class, function(LinkFactory $factory) {
360
                $factory->title = 'Profile';
361
                $factory->url = url('profile');
362
            });
363
        });
364
365
        $this->assertEquals($this->getStub('insert.html'), $builder->render('another'));
366
    }
367
368
    public function testInsertExceptionHasNot()
369
    {
370
        $this->expectException(\RuntimeException::class);
371
372
        $builder = $this->builderFactory();
373
        $builder->insertBefore('not_exist', function (Builder $builder) {});
0 ignored issues
show
Unused Code introduced by
The parameter $builder 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...
374
    }
375
376
    public function testInsertExceptionDuplicate()
377
    {
378
        $this->expectException(\RuntimeException::class);
379
380
        $builder = $this->builderFactory();
381
        $builder->create('home', Link::class, function(LinkFactory $factory) {
382
            $factory->title = 'Home';
383
            $factory->url = '/';
384
        });
385
        $builder->create('some', Link::class, function(LinkFactory $factory) {
386
            $factory->title = 'Some';
387
            $factory->url = '/';
388
        });
389
        $builder->insertAfter('home', function (Builder $builder) {
390
            $builder->create('some', Text::class, function(TextFactory $factory) {
391
                $factory->text = 'Duplicate some';
392
            });
393
        });
394
    }
395
    
396
    public function testSerialization()
397
    {
398
        $builder = $this->builderFactory();
399
        $builder->create('index', Link::class, function(LinkFactory $factory) {
400
            $factory->title = 'Index';
401
            $factory->url = url('/');
402
        });
403
        $builder->create('users', SubMenu::class, function(SubMenuFactory $factory) {
404
            $factory->title = 'Users';
405
            $factory->builder->getAttributes()->put('class', 'menu');
406
            $factory->builder->create('all', Link::class, function(LinkFactory $factory) {
407
                $factory->title = 'All';
408
                $factory->url = url('/users');
409
            });
410
            $factory->builder->create('admins', Link::class, function(LinkFactory $factory) {
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...
411
                $factory->title = 'Admins';
412
                $factory->url = url('/users', ['role' => 'admin']);
413
                $factory->displayRule = false;
414
            });
415
            $factory->builder->create('create', SubMenu::class, function(SubMenuFactory $factory) {
416
                $factory->title = 'Create';
417
                $factory->builder->create('user', Link::class, function(LinkFactory $factory) {
418
                    $factory->title = 'User';
419
                    $factory->url = url('/users/create/user');
420
                });
421
                $factory->builder->create('role', Link::class, function(LinkFactory $factory) {
422
                    $factory->title = 'Role';
423
                    $factory->url = url('/users/create/role');
424
                });
425
            });
426
        });
427
        $builder->create('settings', Link::class, function(LinkFactory $factory) {
428
            $factory->displayRule = function () {return false;};
429
            $factory->title = 'Settings';
430
            $factory->url = url('/settings');
431
        });
432
        $builder->create('deliver', Text::class, function(TextFactory $factory) {
433
            $factory->text = '-';
434
        });
435
        $builder->create('logout', Link::class, function(LinkFactory $factory) {
436
            $factory->title = 'Logout';
437
            $factory->url = url('/logout');
438
        });
439
440
        $this->assertEquals($this->serializeStub(), serialize($builder));
441
        $this->assertEquals($builder, unserialize($this->serializeStub()));
442
    }
443
    
444
    public function testArray()
445
    {
446
        $builder = $this->builderFactory();
447
        $builder->create('index', Link::class, function(LinkFactory $factory) {
448
            $factory->title = 'Index';
449
            $factory->url = url('/');
450
        });
451
        $builder->create('submenu', SubMenu::class, function(SubMenuFactory $factory) {
452
            for ($i = 1; $i <= 3; ++$i) {
453
                $factory->builder->create('item_' . $i, Link::class, function(LinkFactory $factory) use ($i) {
454
                    $factory->title = 'Item ' . $i;
455
                    $factory->url = url('/item', ['id' => $i]);
456
                });
457
            }
458
        });
459
        
460
        $this->assertEquals($this->toArrayStub(), $builder->toArray());
461
462
        $builderFormArray = $builder->fromArray($builder->toArray());
463
        $this->assertEquals($builder->render(), $builderFormArray->render());
464
    }
465
    
466
    public function testSet()
467
    {
468
        $builder = $this->builderFactory();
469
        $element = (new TextFactory($this->app))->build([
470
            'text' => 'Text',
471
        ]);
472
        $notElement = [];
473
        
474
        $builder['element'] = $element;
475
        $builder['notElement'] = $notElement;
476
        
477
        $this->assertTrue($builder->has('element'));
478
        $this->assertFalse($builder->has('notElement'));
479
    }
480
481
    public function testCreateCallbackException()
482
    {
483
        $this->expectException(\RuntimeException::class);
484
485
        $builder = $this->builderFactory();
486
        $builder->create('test', Link::class, function(LinkFactory $factory) {
0 ignored issues
show
Unused Code introduced by
The parameter $factory 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...
487
            return 'string';
488
        });
489
    }
490
}