-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathCollectionFilterOperationTest.php
More file actions
142 lines (114 loc) · 5.18 KB
/
CollectionFilterOperationTest.php
File metadata and controls
142 lines (114 loc) · 5.18 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
<?php
declare(strict_types=1);
namespace Test\TinyBlocks\Collection\Operations\Filter;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;
use Test\TinyBlocks\Collection\Models\CryptoCurrency;
use TinyBlocks\Collection\Collection;
use TinyBlocks\Mapper\KeyPreservation;
final class CollectionFilterOperationTest extends TestCase
{
public function testFilterAppliesMultiplePredicates(): void
{
/** @Given a collection with elements */
$collection = Collection::createFrom(elements: [1, 2, 3, 4, 5, 6]);
/**
* @When filtering the collection with three predicates,
* the first predicate filters out values less than or equal to 2,
* the second predicate keeps only even numbers,
* and the third predicate filters out values greater than or equal to 6.
*/
$actual = $collection->filter(
static fn(int $value): bool => $value > 2,
static fn(int $value): bool => $value % 2 === 0,
static fn(int $value): bool => $value < 6
);
/** @Then the filtered collection should discard the keys and return the expected values */
self::assertSame([4], $actual->toArray(keyPreservation: KeyPreservation::DISCARD));
}
public function testFilterFailsIfPredicatesAreNotReindex(): void
{
/** @Given a collection with elements */
$collection = Collection::createFrom(elements: [10, 20, 30]);
/** @When filtering with a null predicate in the first position. */
$actual = $collection->filter(
null,
static fn(int $value): bool => $value > 15
);
/** @Then the filter should still work correctly. */
$elements = iterator_to_array($actual);
self::assertCount(2, $elements);
self::assertContains(20, $elements);
self::assertContains(30, $elements);
}
public function testFilterIgnoresNullPredicatesAndReindexesWeights(): void
{
/** @Given a collection with elements */
$collection = Collection::createFrom(elements: [1, 2, 3, 4, 5]);
/** @When filtering using null values interspersed with valid predicates. */
$actual = $collection->filter(
null,
static fn(int $value): bool => $value > 2,
null,
static fn(int $value): bool => $value < 5
);
/** @Then it should only apply the valid predicates (result should be 3 and 4) */
self::assertSame([3, 4], $actual->toArray(keyPreservation: KeyPreservation::DISCARD));
}
#[DataProvider('elementsDataProvider')]
public function testFilterAppliesDefaultArrayFilter(iterable $elements, iterable $expected): void
{
/** @Given a collection with elements */
$collection = Collection::createFrom(elements: $elements);
/** @When filtering the collection without any predicates (using default truthy filter) */
$actual = $collection->filter();
/** @Then the filtered collection should contain only truthy elements */
self::assertSame(array_values((array)$expected), $actual->toArray(keyPreservation: KeyPreservation::DISCARD));
}
#[DataProvider('elementsDataProviderWithKeys')]
public function testFilterPreservesKeys(iterable $elements, iterable $expected): void
{
/** @Given a collection with elements and keys */
$collection = Collection::createFrom(elements: $elements);
/** @When filtering the collection without any predicates (using default truthy filter) */
$actual = $collection->filter();
/** @Then the filtered collection should preserve keys for truthy elements */
self::assertSame($expected, $actual->toArray());
}
public static function elementsDataProvider(): iterable
{
$bitcoin = new CryptoCurrency(name: 'Bitcoin', price: (float)rand(60000, 999999), symbol: 'BTC');
yield 'Empty array' => [
'elements' => [],
'expected' => []
];
yield 'Array with boolean values' => [
'elements' => [false, true, false, true],
'expected' => [true, true]
];
yield 'Array with null and numbers' => [
'elements' => [null, 1, 2, 0],
'expected' => [1, 2]
];
yield 'Array with only falsy values' => [
'elements' => [0, '', null, false],
'expected' => []
];
yield 'Array with objects and truthy values' => [
'elements' => [$bitcoin, 1, 'valid string'],
'expected' => [$bitcoin->toArray(keyPreservation: KeyPreservation::DISCARD), 1, 'valid string']
];
}
public static function elementsDataProviderWithKeys(): iterable
{
$bitcoin = new CryptoCurrency(name: 'Bitcoin', price: 60000.0, symbol: 'BTC');
yield 'Array with keys preserved' => [
'elements' => ['a' => false, 'b' => true, 'c' => false, 'd' => true],
'expected' => ['b' => true, 'd' => true]
];
yield 'Mixed elements with keys' => [
'elements' => ['first' => null, 'second' => 1, 'third' => $bitcoin],
'expected' => ['second' => 1, 'third' => $bitcoin->toArray()]
];
}
}