NodeTest   B
last analyzed

Complexity

Total Complexity 51

Size/Duplication

Total Lines 785
Duplicated Lines 0 %

Importance

Changes 3
Bugs 1 Features 0
Metric Value
wmc 51
eloc 327
c 3
b 1
f 0
dl 0
loc 785
rs 7.92

48 Methods

Rating   Name   Duplication   Size   Complexity  
A findTraversesNodesProvider() 0 14 1
A testSetContentCollection() 0 21 1
A testFindAllShallow() 0 14 1
A toStringReturnsRawContentByDefaultProvider() 0 4 1
A testArrayAccessThrowExceptionWhenMadeDirty() 0 9 1
A testCountWithMixedOffset() 0 17 1
A findAllShallowProvider() 0 10 1
A testFindFindsItself() 0 10 2
A testToStringReturnsRawContentByDefault() 0 5 1
A testReplace() 0 11 1
A isMatchProvider() 0 18 1
A testToString() 0 15 1
A testSetContentWillThrowExceptionOnNonStringLikeContent() 0 5 1
A testSetContentNull() 0 11 1
A testConstructAddsIntents() 0 6 1
A testConstructFailure() 0 5 1
A testArrayAccessWithoutOffset() 0 12 1
A testArrayAccessWithExplicitOffset() 0 12 1
A toStringCanReturnTranslatedContentProvider() 0 6 1
A offsetSetFailureProvider() 0 10 1
A createCollectionStub() 0 3 1
A testArrayAccessFailureWithExplicitOffset() 0 7 1
A hasIntentProvider() 0 7 1
A setUp() 0 3 1
A testGetExtendedNodes() 0 11 1
A testArrayAccessUnset() 0 13 1
A testGetRawContentReturnsNonTranslatedContent() 0 3 1
A testCountWithExplicitOffset() 0 13 1
A testToStringCanReturnTranslatedContent() 0 12 1
A testIterator() 0 22 2
A testArrayAccessWithMixedOffset() 0 17 1
A replaceProvider() 0 48 1
A testArrayAccessFailureWithoutOffset() 0 7 1
A findAllProvider() 0 18 1
A testFindAll() 0 9 1
A setContentProvider() 0 19 1
A testSetContentNode() 0 9 1
A testForceGetNodes() 0 15 1
A testSetTranslatorSetTranslatorOnNodes() 0 10 1
A testAddIntent() 0 10 1
A testCountWithoutOffset() 0 13 1
A testFindTraversesNodes() 0 12 2
A testGetNodes() 0 11 1
A testHasIntentChecksIfAGivenIntentHasBeenSet() 0 12 1
A testSetIntent() 0 11 1
A contentFailureProvider() 0 6 1
A testIsMatch() 0 7 1
A testSetContentFailure() 0 7 1

How to fix   Complexity   

Complex Class

Complex classes like NodeTest often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use NodeTest, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
declare(strict_types=1);
4
5
namespace AbterPhp\Framework\Html;
6
7
use AbterPhp\Framework\I18n\ITranslator;
8
use AbterPhp\Framework\TestDouble\Html\CollectionStub;
9
use AbterPhp\Framework\TestDouble\I18n\MockTranslatorFactory;
10
use Closure;
11
use PHPUnit\Framework\TestCase;
12
13
class NodeTest extends TestCase
14
{
15
    /** @var Node - System Under Test */
16
    protected Node $sut;
17
18
    public function setUp(): void
19
    {
20
        $this->sut = new Node();
21
    }
22
23
    /**
24
     * @return array[]
25
     */
26
    public function setContentProvider(): array
27
    {
28
        $fooNode     = new Node('foo');
29
        $fooBarNode  = new Node(['foo', 'bar']);
30
        $fooNodeNode = new Node($fooNode, 'baz');
31
32
        return [
33
            'null'            => [null, '', []],
34
            'false'           => [false, '', []],
35
            'true'            => [true, '1', []],
36
            '12.43'           => [12.43, '12.43', []],
37
            'string'          => ['foo', 'foo', []],
38
            'array'           => [['foo'], 'foo', []],
39
            'strings'         => [['foo', 'bar'], 'foobar', []],
40
            'node'            => [$fooNode, 'foo', [$fooNode]],
41
            'node-with-array' => [$fooBarNode, 'foobar', [$fooBarNode]],
42
            'node-node'       => [$fooNodeNode, 'foo', [$fooNodeNode]],
43
            'node-nodes'      => [[$fooNode, $fooNodeNode], 'foofoo', [$fooNode, $fooNodeNode]],
44
            'mixed'           => [[$fooNode, 'bar', $fooNodeNode], 'foobarfoo', [$fooNode, $fooNodeNode]],
45
        ];
46
    }
47
48
    /**
49
     * @dataProvider setContentProvider
50
     *
51
     * @param        $content
52
     * @param string $expectedAsString
53
     * @param array  $expectedNodes
54
     */
55
    public function testSetContentNode($content, string $expectedAsString, array $expectedNodes)
56
    {
57
        $node = new Node($content);
58
59
        $actualString = (string)$node;
60
        $this->assertEquals($expectedAsString, $actualString);
61
62
        $actualNodes = $node->getExtendedNodes();
63
        $this->assertEquals($expectedNodes, $actualNodes);
64
    }
65
66
    public function testSetContentWillThrowExceptionOnNonStringLikeContent()
67
    {
68
        $this->expectException(\Error::class);
69
70
        new Node(new \stdClass());
71
    }
72
73
    public function testGetNodes()
74
    {
75
        $nodeStub = $this->createMock(Node::class);
76
77
        $expectedResult = [$nodeStub];
78
79
        $sut = new Node(['foo', $nodeStub]);
80
81
        $actualResult = $sut->getNodes();
82
83
        $this->assertSame($expectedResult, $actualResult);
84
    }
85
86
    public function testGetExtendedNodes()
87
    {
88
        $nodeStub = $this->createMock(Node::class);
89
90
        $expectedResult = [$nodeStub];
91
92
        $sut = new Node(['foo', $nodeStub]);
93
94
        $actualResult = $sut->getExtendedNodes();
95
96
        $this->assertSame($expectedResult, $actualResult);
97
    }
98
99
    public function testForceGetNodes()
100
    {
101
        $nodeContent = 'foo';
102
103
        $nodeStub = $this->createMock(Node::class);
104
        $nodeStub2 = new Node($nodeContent);
105
106
        $expectedResult = [$nodeStub2, $nodeStub];
107
108
        $sut = new Node([$nodeContent, $nodeStub]);
109
110
        $actualResult = $sut->forceGetNodes();
111
112
        $this->assertNotSame($expectedResult, $actualResult);
113
        $this->assertEquals($expectedResult, $actualResult);
114
    }
115
116
    public function testConstructAddsIntents()
117
    {
118
        $expectedIntents = ['foo', 'bar'];
119
120
        $node = new Node(null, ...$expectedIntents);
121
        $this->assertEquals($expectedIntents, $node->getIntents());
122
    }
123
124
    public function testSetIntent()
125
    {
126
        $node = new Node(null, 'foo', 'bar');
127
        $this->assertTrue($node->hasIntent('foo'));
128
        $this->assertTrue($node->hasIntent('bar'));
129
130
        $node->setIntent('Foo', 'Bar');
131
        $this->assertFalse($node->hasIntent('foo'));
132
        $this->assertFalse($node->hasIntent('bar'));
133
        $this->assertTrue($node->hasIntent('Foo'));
134
        $this->assertTrue($node->hasIntent('Bar'));
135
    }
136
137
    public function testAddIntent()
138
    {
139
        $sut = new Node(null, 'foo', 'bar');
140
        $this->assertTrue($sut->hasIntent('foo'));
141
        $this->assertTrue($sut->hasIntent('bar'));
142
143
        $sut->addIntent('baz');
144
        $this->assertTrue($sut->hasIntent('foo'));
145
        $this->assertTrue($sut->hasIntent('bar'));
146
        $this->assertTrue($sut->hasIntent('baz'));
147
    }
148
149
    public function testSetTranslatorSetTranslatorOnNodes()
150
    {
151
        $embedded = new Node();
152
        $wrapper  = new Node($embedded);
153
154
        $translatorMock = $this->getMockBuilder(ITranslator::class)->getMock();
155
156
        $wrapper->setTranslator($translatorMock);
157
158
        $this->assertSame($translatorMock, $embedded->getTranslator());
159
    }
160
161
    /**
162
     * @return array[]
163
     */
164
    public function isMatchProvider(): array
165
    {
166
        $f1 = fn(INode $node) => $node->hasIntent('foo');
167
        $f2 = fn() => false;
168
169
        return [
170
            'empty'          => [null, null, [], true],
171
            'inode'          => [INode::class, null, [], true],
172
            'node'           => [Node::class, null, [], true],
173
            'nodetest'       => [NodeTest::class, null, [], false],
174
            'foo'            => [null, null, ['foo'], true],
175
            'bar'            => [null, null, ['bar'], true],
176
            'baz'            => [null, null, ['baz'], false],
177
            'foobar'         => [null, null, ['foo', 'bar'], true],
178
            'node-foobar'    => [Node::class, null, ['foo', 'bar'], true],
179
            'node-foobarbaz' => [Node::class, null, ['foo', 'bar', 'baz'], false],
180
            'f1'             => [null, $f1, [], true],
181
            'f2'             => [null, $f2, [], false],
182
        ];
183
    }
184
185
    /**
186
     * @dataProvider isMatchProvider
187
     *
188
     * @param string|null   $className
189
     * @param \Closure|null $matcher
190
     * @param string[]      $intents
191
     * @param bool          $expectedResult
192
     */
193
    public function testIsMatch(?string $className, ?Closure $matcher, array $intents, bool $expectedResult)
194
    {
195
        $sut = new Node('foo', 'foo', 'bar');
196
197
        $actualResult = $sut->isMatch($className, $matcher, ...$intents);
198
199
        $this->assertSame($expectedResult, $actualResult);
200
    }
201
202
    /**
203
     * @dataProvider isMatchProvider
204
     *
205
     * @param string|null   $className
206
     * @param \Closure|null $matcher
207
     * @param string[]      $intents
208
     * @param bool          $expectedResult
209
     */
210
    public function testFindFindsItself(?string $className, ?Closure $matcher, array $intents, bool $expectedResult)
211
    {
212
        $sut = new Node('foo', 'foo', 'bar');
213
214
        $actualResult = $sut->find($className, $matcher, ...$intents);
215
216
        if ($expectedResult) {
217
            $this->assertSame($sut, $actualResult);
218
        } else {
219
            $this->assertNull($actualResult);
220
        }
221
    }
222
223
    /**
224
     * @return array[]
225
     */
226
    public function findTraversesNodesProvider(): array
227
    {
228
        $f1 = fn(INode $node) => $node->hasIntent('foo');
229
        $f2 = fn() => false;
230
231
        return [
232
            'foo'            => [null, null, ['foo'], true],
233
            'bar'            => [null, null, ['bar'], true],
234
            'baz'            => [null, null, ['baz'], false],
235
            'foobar'         => [null, null, ['foo', 'bar'], true],
236
            'node-foobar'    => [Node::class, null, ['foo', 'bar'], true],
237
            'node-foobarbaz' => [Node::class, null, ['foo', 'bar', 'baz'], false],
238
            'f1'             => [null, $f1, [], true],
239
            'f2'             => [null, $f2, [], false],
240
        ];
241
    }
242
243
    /**
244
     * @dataProvider findTraversesNodesProvider
245
     *
246
     * @param string|null   $className
247
     * @param \Closure|null $matcher
248
     * @param string[]      $intents
249
     * @param bool          $expectedResult
250
     */
251
    public function testFindTraversesNodes(?string $className, ?Closure $matcher, array $intents, bool $expectedResult)
252
    {
253
        $grandChild = new Node('foo', 'foo', 'bar');
254
        $child      = new Node([new Node(), '', $grandChild]);
255
        $sut        = new Node($child);
256
257
        $actualResult = $sut->find($className, $matcher, ...$intents);
258
259
        if ($expectedResult) {
260
            $this->assertSame($grandChild, $actualResult);
261
        } else {
262
            $this->assertNull($actualResult);
263
        }
264
    }
265
266
    /**
267
     * @return array[]
268
     */
269
    public function findAllProvider(): array
270
    {
271
        $f1 = fn(INode $node) => $node->hasIntent('foo');
272
        $f2 = fn() => false;
273
274
        return [
275
            'empty'          => [null, null, [], 4],
276
            'inode'          => [INode::class, null, [], 4],
277
            'node'           => [Node::class, null, [], 4],
278
            'nodetest'       => [NodeTest::class, null, [], 0],
279
            'foo'            => [null, null, ['foo'], 1],
280
            'bar'            => [null, null, ['bar'], 1],
281
            'baz'            => [null, null, ['baz'], 0],
282
            'foobar'         => [null, null, ['foo', 'bar'], 1],
283
            'node-foobar'    => [Node::class, null, ['foo', 'bar'], 1],
284
            'node-foobarbaz' => [Node::class, null, ['foo', 'bar', 'baz'], 0],
285
            'f1'             => [null, $f1, [], 1],
286
            'f2'             => [null, $f2, [], 0],
287
        ];
288
    }
289
290
    /**
291
     * @dataProvider findAllProvider
292
     *
293
     * @param string|null   $className
294
     * @param \Closure|null $matcher
295
     * @param string[]      $intents
296
     * @param int           $expectedLength
297
     */
298
    public function testFindAll(?string $className, ?Closure $matcher, array $intents, int $expectedLength)
299
    {
300
        $grandChild = new Node('foo', 'foo', 'bar');
301
        $child      = new Node([new Node(), '', $grandChild]);
302
        $sut        = new Node($child);
303
304
        $actualResult = $sut->findAll($className, $matcher, ...$intents);
305
306
        $this->assertSame($expectedLength, count($actualResult));
307
    }
308
309
    /**
310
     * @return array[]
311
     */
312
    public function findAllShallowProvider(): array
313
    {
314
        return [
315
            'empty-3'  => [3, null, null, [], 4],
316
            'empty-2'  => [2, null, null, [], 4],
317
            'empty-1'  => [1, null, null, [], 2],
318
            'empty-0'  => [0, null, null, [], 1],
319
            'empty--1' => [-1, null, null, [], 4],
320
            'foo-2'    => [2, null, null, ['foo'], 1],
321
            'foo-1'    => [1, null, null, ['foo'], 0],
322
        ];
323
    }
324
325
    /**
326
     * @dataProvider findAllShallowProvider
327
     *
328
     * @param int           $maxDepth
329
     * @param string|null   $className
330
     * @param \Closure|null $matcher
331
     * @param string[]      $intents
332
     * @param int           $expectedLength
333
     */
334
    public function testFindAllShallow(
335
        int $maxDepth,
336
        ?string $className,
337
        ?Closure $matcher,
338
        array $intents,
339
        int $expectedLength
340
    ) {
341
        $grandChild = new Node('foo', 'foo', 'bar');
342
        $child      = new Node([new Node(), '', $grandChild]);
343
        $sut        = new Node($child);
344
345
        $actualResult = $sut->findAllShallow($maxDepth, $className, $matcher, ...$intents);
346
347
        $this->assertSame($expectedLength, count($actualResult));
348
    }
349
350
    public function testToString()
351
    {
352
        $grandChild = new Node('foo', 'foo', 'bar');
353
        $child      = new Node([new Node(), '', $grandChild]);
354
        $sut        = new Node($child);
355
356
        $expectedResult = 'bar';
357
358
        $translatorMock = MockTranslatorFactory::createSimpleTranslator($this, ['foo' => 'bar']);
359
360
        $sut->setTranslator($translatorMock);
361
362
        $actualResult = (string)$sut;
363
364
        $this->assertSame($expectedResult, $actualResult);
365
    }
366
    public function toStringReturnsRawContentByDefaultProvider(): array
367
    {
368
        return [
369
            'INode[]' => [[new Node('foo')], 'foo'],
370
        ];
371
    }
372
373
    /**
374
     * @dataProvider toStringReturnsRawContentByDefaultProvider
375
     *
376
     * @param mixed  $rawContent
377
     * @param string $expectedResult
378
     */
379
    public function testToStringReturnsRawContentByDefault($rawContent, string $expectedResult): void
380
    {
381
        $sut = $this->createCollectionStub($rawContent);
382
383
        $this->assertStringContainsString($expectedResult, (string)$sut);
384
    }
385
386
    /**
387
     * @return array
388
     */
389
    public function toStringCanReturnTranslatedContentProvider(): array
390
    {
391
        $translations = ['foo' => 'bar'];
392
393
        return [
394
            'INode[]' => [[new Node('foo')], $translations, 'bar'],
395
        ];
396
    }
397
398
    /**
399
     * @dataProvider toStringCanReturnTranslatedContentProvider
400
     *
401
     * @param mixed  $rawContent
402
     * @param array  $translations
403
     * @param string $expectedResult
404
     */
405
    public function testToStringCanReturnTranslatedContent(
406
        $rawContent,
407
        array $translations,
408
        string $expectedResult
409
    ): void {
410
        $translatorMock = MockTranslatorFactory::createSimpleTranslator($this, $translations);
411
412
        $sut = $this->createCollectionStub($rawContent);
413
414
        $sut->setTranslator($translatorMock);
415
416
        $this->assertStringContainsString($expectedResult, (string)$sut);
417
    }
418
419
    public function testCountWithoutOffset(): void
420
    {
421
        $expectedResult = 2;
422
423
        $node1 = new Node('1');
424
        $node2 = new Node('2');
425
426
        $sut = $this->createCollectionStub();
427
428
        $sut[] = $node1;
429
        $sut[] = $node2;
430
431
        $this->assertSame($expectedResult, count($sut));
432
    }
433
434
    public function testCountWithExplicitOffset(): void
435
    {
436
        $expectedResult = 2;
437
438
        $node1 = new Node('1');
439
        $node2 = new Node('2');
440
441
        $sut = $this->createCollectionStub();
442
443
        $sut[0] = $node1;
444
        $sut[1] = $node2;
445
446
        $this->assertSame($expectedResult, count($sut));
447
    }
448
449
    public function testCountWithMixedOffset(): void
450
    {
451
        $node1 = new Node('1');
452
        $node2 = new Node('2');
453
454
        $expectedCount = 5;
455
456
        $sut = $this->createCollectionStub();
457
458
        $sut[]  = $node1;
459
        $sut[]  = $node1;
460
        $sut[1] = $node2;
461
        $sut[2] = $node1;
462
        $sut[3] = $node1;
463
        $sut[]  = $node1;
464
465
        $this->assertSame($expectedCount, count($sut));
466
    }
467
468
    public function testArrayAccessWithoutOffset(): void
469
    {
470
        $node1 = new Node('1');
471
        $node2 = new Node('2');
472
473
        $sut = $this->createCollectionStub();
474
475
        $sut[] = $node1;
476
        $sut[] = $node2;
477
478
        $this->assertSame($node1, $sut[0]);
479
        $this->assertSame($node2, $sut[1]);
480
    }
481
482
    public function testArrayAccessWithExplicitOffset(): void
483
    {
484
        $node1 = new Node('1');
485
        $node2 = new Node('2');
486
487
        $sut = $this->createCollectionStub();
488
489
        $sut[0] = $node1;
490
        $sut[1] = $node2;
491
492
        $this->assertSame($node1, $sut[0]);
493
        $this->assertSame($node2, $sut[1]);
494
    }
495
496
    public function testArrayAccessThrowExceptionWhenMadeDirty(): void
497
    {
498
        $this->expectException(\InvalidArgumentException::class);
499
500
        $node1 = new Node('1');
501
502
        $sut = $this->createCollectionStub();
503
504
        $sut[1] = $node1;
505
    }
506
507
    public function testArrayAccessWithMixedOffset(): void
508
    {
509
        $node1 = new Node('1');
510
        $node2 = new Node('2');
511
512
        $expectedNodes = [0 => $node1, 1 => $node2, 2 => $node1, 3 => $node1, 4 => $node1];
513
514
        $sut = $this->createCollectionStub();
515
516
        $sut[]  = $node1;
517
        $sut[]  = $node1;
518
        $sut[1] = $node2;
519
        $sut[2] = $node1;
520
        $sut[3] = $node1;
521
        $sut[]  = $node1;
522
523
        $this->assertEquals($expectedNodes, $sut->getExtendedNodes());
524
    }
525
526
    /**
527
     * @return array[]
528
     */
529
    public function contentFailureProvider(): array
530
    {
531
        return [
532
            'string wrapped'          => [['']],
533
            'non-node object wrapped' => [[new \StdClass()]],
534
            'node double wrapped'     => [[[new Node()]]],
535
        ];
536
    }
537
538
    /**
539
     * @dataProvider contentFailureProvider
540
     */
541
    public function testConstructFailure($item): void
542
    {
543
        $this->expectException(\AssertionError::class);
544
545
        $this->createCollectionStub($item);
546
    }
547
548
    /**
549
     * @dataProvider contentFailureProvider
550
     */
551
    public function testSetContentFailure($item): void
552
    {
553
        $this->expectException(\AssertionError::class);
554
555
        $sut = $this->createCollectionStub();
556
557
        $sut->setContent($item);
558
    }
559
560
    /**
561
     * @return array
562
     */
563
    public function offsetSetFailureProvider(): array
564
    {
565
        $contentFailure = $this->contentFailureProvider();
566
567
        $offsetFailure = [
568
            'string'       => ['foo'],
569
            'node wrapped' => [[new Node()]],
570
        ];
571
572
        return array_merge($contentFailure, $offsetFailure);
573
    }
574
575
    /**
576
     * @dataProvider offsetSetFailureProvider
577
     */
578
    public function testArrayAccessFailureWithoutOffset($item): void
579
    {
580
        $this->expectException(\AssertionError::class);
581
582
        $sut = $this->createCollectionStub();
583
584
        $sut[] = $item;
585
    }
586
587
    /**
588
     * @dataProvider offsetSetFailureProvider
589
     */
590
    public function testArrayAccessFailureWithExplicitOffset($item): void
591
    {
592
        $this->expectException(\AssertionError::class);
593
594
        $sut = $this->createCollectionStub();
595
596
        $sut[] = $item;
597
    }
598
599
    public function testArrayAccessUnset(): void
600
    {
601
        $node1 = new Node('1');
602
603
        $sut = $this->createCollectionStub();
604
605
        $sut[] = $node1;
606
607
        $this->assertTrue($sut->offsetExists(0));
608
609
        unset($sut[0]);
610
611
        $this->assertfalse($sut->offsetExists(0));
612
    }
613
614
    public function testSetContentNull(): void
615
    {
616
        $expectedNodes = [];
617
618
        $sut = $this->createCollectionStub();
619
620
        $sut->setContent(null);
621
622
        $actualResult = $sut->getNodes();
623
624
        $this->assertEquals($expectedNodes, $actualResult);
625
    }
626
627
    public function testSetContentCollection(): void
628
    {
629
        $node1 = new Node('1');
630
        $node2 = new Node('2');
631
632
        $expectedNodes = [$node1];
633
634
        $sut = $this->createCollectionStub();
635
636
        $sut[]  = $node1;
637
        $sut[]  = $node1;
638
        $sut[1] = $node2;
639
        $sut[2] = $node1;
640
        $sut[3] = $node1;
641
        $sut[]  = $node1;
642
643
        $sut->setContent($node1);
644
645
        $actualResult = $sut->getNodes();
646
647
        $this->assertEquals($expectedNodes, $actualResult);
648
    }
649
650
    public function testIterator(): void
651
    {
652
        $node1 = new Node('1');
653
        $node2 = new Node('2');
654
655
        $expectedKeys  = [0, 1, 2, 3, 4];
656
        $expectedNodes = [$node1, $node2, $node1, $node1, $node1];
657
658
        $sut = $this->createCollectionStub();
659
660
        $sut[]  = $node1;
661
        $sut[]  = $node1;
662
        $sut[1] = $node2;
663
        $sut[2] = $node1;
664
        $sut[3] = $node1;
665
        $sut[]  = $node1;
666
667
        $pos = 0;
668
        foreach ($sut as $key => $node) {
669
            $this->assertSame($expectedKeys[$pos], $key);
670
            $this->assertSame($expectedNodes[$pos], $node);
671
            $pos++;
672
        }
673
    }
674
675
    public function testGetRawContentReturnsNonTranslatedContent(): void
676
    {
677
        $this->assertTrue(true, 'No need to test getRawContent');
678
    }
679
680
    /**
681
     * @return array
682
     */
683
    public function replaceProvider(): array
684
    {
685
        $needle = new Node('1');
686
        $node2  = new Node('2');
687
        $node3  = new Node('3');
688
689
        return [
690
            'empty-content'                  => [
691
                [],
692
                $needle,
693
                [$node2],
694
                [],
695
            ],
696
            'only-non-matching-content'      => [
697
                [$node2, $node3],
698
                $needle,
699
                [$needle, $node3],
700
                [$node2, $node3],
701
            ],
702
            'only-non-matching-content-deep' => [
703
                [$node2, $node3, new CollectionStub([$node2, $node3])],
704
                $needle,
705
                [$needle, $node3],
706
                [$node2, $node3, new CollectionStub([$node2, $node3])],
707
            ],
708
            'only-matching-content'          => [
709
                [$needle],
710
                $needle,
711
                [$node2, $node3],
712
                [$node2, $node3],
713
            ],
714
            'non-first-matching-content'     => [
715
                [$node2, $needle],
716
                $needle,
717
                [$node3, $node3],
718
                [$node2, $node3, $node3],
719
            ],
720
            'non-last-matching-content'      => [
721
                [$needle, $node2],
722
                $needle,
723
                [$node3, $node3],
724
                [$node3, $node3, $node2],
725
            ],
726
            'deep-first-matching-content'    => [
727
                [$node2, new CollectionStub([$node2, $needle])],
728
                $needle,
729
                [$node3, $node3],
730
                [$node2, new CollectionStub([$node2, $node3, $node3])],
731
            ],
732
        ];
733
    }
734
735
    /**
736
     * @dataProvider replaceProvider
737
     *
738
     * @param INode[] $content
739
     * @param INode   $nodeToFind
740
     * @param INode[] $nodesToInsert
741
     * @param INode[] $expectedNodes
742
     */
743
    public function testReplace(
744
        array $content,
745
        INode $nodeToFind,
746
        array $nodesToInsert,
747
        array $expectedNodes
748
    ): void {
749
        $sut = $this->createCollectionStub($content);
750
751
        $sut->replace($nodeToFind, ...$nodesToInsert);
752
753
        $this->assertEquals($expectedNodes, $sut->getNodes());
754
    }
755
756
    /**
757
     * @return array
758
     */
759
    public function hasIntentProvider(): array
760
    {
761
        return [
762
            [[], 'foo', false],
763
            [['foo'], 'foo', true],
764
            [['bar'], 'foo', false],
765
            [['foo', 'bar', 'baz'], 'bar', true],
766
        ];
767
    }
768
769
    /**
770
     * @dataProvider hasIntentProvider
771
     *
772
     * @param array  $intents
773
     * @param string $intentToCheck
774
     * @param bool   $expectedResult
775
     */
776
    public function testHasIntentChecksIfAGivenIntentHasBeenSet(
777
        array $intents,
778
        string $intentToCheck,
779
        bool $expectedResult
780
    ): void {
781
        $sut = $this->createCollectionStub();
782
783
        $sut->setIntent(...$intents);
784
785
        $actualResult = $sut->hasIntent($intentToCheck);
786
787
        $this->assertSame($expectedResult, $actualResult);
788
    }
789
790
    /**
791
     * @param INode[]|INode|null $content
792
     *
793
     * @return CollectionStub
794
     */
795
    private function createCollectionStub($content = null): CollectionStub
796
    {
797
        return new CollectionStub($content);
798
    }
799
}
800