testWhenConstructedFromTraversable_iteratorHasAllElements()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 0
dl 0
loc 11
rs 9.9
c 0
b 0
f 0
1
<?php
2
3
declare( strict_types = 1 );
4
5
namespace WMDE\IterableFunction\Tests;
6
7
use PHPUnit\Framework\TestCase;
8
use WMDE\TraversableIterator\TraversableIterator;
9
10
/**
11
 * @covers WMDE\TraversableIterator\TraversableIterator
12
 *
13
 * @license GNU GPL v2+
14
 * @author Jeroen De Dauw < [email protected] >
15
 */
16
class TraversableIteratorTest extends TestCase {
17
18
	/**
19
	 * @dataProvider iteratorProvider
20
	 */
21
	public function testIteratorsAppearUnmodified( \Traversable $traversable ) {
22
		$this->assertIterablesHaveSameContent( $traversable, new TraversableIterator( $traversable ) );
23
	}
24
25
	public function iteratorProvider() {
26
		return [
27
			'empty iterator' => [
28
				new \ArrayIterator()
29
			],
30
			'normal iterator' => [
31
				new \ArrayIterator( [ 'a', 'b', 'c' ] )
32
			],
33
			'iterator with keys' => [
34
				new \ArrayIterator( [ 'a' => 10, 'b' => 20, 'c' => 30 ] )
35
			],
36
			'iterator with some explicit keys' => [
37
				new \ArrayIterator( [ 3 => null, 'a' => 10, 20, 'c' => 30 ] )
38
			],
39
		];
40
	}
41
42
	private function assertIterablesHaveSameContent( $expected, $actual ) {
43
		$this->assertSame(
44
			$this->iterableToArray( $expected ),
45
			$this->iterableToArray( $actual )
46
		);
47
	}
48
49
	private function iterableToArray( $iterable ): array {
50
		if ( is_array( $iterable ) ) {
51
			return $iterable;
52
		}
53
54
		return iterator_to_array( $iterable );
55
	}
56
57
	public function testWhenConstructedFromTraversable_iteratorHasAllElements() {
58
		$traversable = new \DatePeriod(
59
			new \DateTime( '2012-08-01' ),
60
			new \DateInterval( 'P1D' ),
61
			new \DateTime( '2012-08-05' )
62
		);
63
64
		$iterator = new TraversableIterator( $traversable );
65
66
		$this->assertCount( 4, $iterator );
0 ignored issues
show
Documentation introduced by
$iterator is of type object<WMDE\TraversableI...or\TraversableIterator>, 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...
67
	}
68
69
	public function testWhenConstructedFromTraversable_iteratorIsRewindable() {
70
		$traversable = new \DatePeriod(
71
			new \DateTime( '2012-08-01' ),
72
			new \DateInterval( 'P1D' ),
73
			new \DateTime( '2012-08-05' )
74
		);
75
76
		$iterator = new TraversableIterator( $traversable );
77
78
		$this->assertContainsOnlyInstancesOf( \DateTime::class, $iterator );
79
		$this->assertContainsOnlyInstancesOf( \DateTime::class, $iterator );
80
	}
81
82
	public function testWhenConstructedFromIteratorAggregate_iteratorHasAllElements() {
83
		$traversable = new class() implements \IteratorAggregate {
84
			public function getIterator() {
85
				return new \ArrayIterator( [ 'a' => 10, 'b' => 20, 'c' => 30 ] );
86
			}
87
		};
88
89
		$iterator = new TraversableIterator( $traversable );
90
91
		$this->assertIterablesHaveSameContent( [ 'a' => 10, 'b' => 20, 'c' => 30 ], $iterator );
92
	}
93
94
	public function testWhenConstructedFromIteratorAggregate_iteratorIsRewindable() {
95
		$traversable = new class() implements \IteratorAggregate {
96
			public function getIterator() {
97
				yield 'a' => 10;
98
				yield 'b' => 20;
99
				yield 'c' => 30;
100
			}
101
		};
102
103
		$iterator = new TraversableIterator( $traversable );
104
105
		$this->assertContainsOnly( 'int', $iterator );
106
		$this->assertContainsOnly( 'int', $iterator );
107
	}
108
109
	public function testWhenConstructedFromIteratorAggregate_getIteratorIsCalledOncePerIteration() {
110
		$traversable = $this->createMock( \IteratorAggregate::class );
111
112
		$traversable->expects( $this->exactly( 4 ) )
113
			->method( 'getIterator' )
114
			->willReturn( new \ArrayIterator() );
115
116
		$iterator = new TraversableIterator( $traversable );
0 ignored issues
show
Documentation introduced by
$traversable is of type object<PHPUnit\Framework\MockObject\MockObject>, but the function expects a object<Traversable>.

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...
117
118
		$this->assertContainsOnly( 'int', $iterator );
119
		$this->assertContainsOnly( 'int', $iterator );
120
		$this->assertContainsOnly( 'int', $iterator );
121
	}
122
123
}
124