Skip to content

Commit 391920d

Browse files
committed
Add every, some, none methods to ArrayAssertions with tests and README updates
1 parent 2848baa commit 391920d

File tree

8 files changed

+262
-81
lines changed

8 files changed

+262
-81
lines changed

README.md

Lines changed: 9 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -65,72 +65,16 @@ fact([])->isEmptyArray(); // Passes
6565
fact([1, 2])->isEmptyArray(); // Fails
6666

6767
fact([1, 2])->isNotEmptyArray(); // Passes
68-
fact([])->isNotEmptyArray(); // Fails
68+
fact([])->isNotEmptyArray(); // Fails
6969

70-
```
71-
72-
### Boolean assertions
73-
```php
74-
fact(true)->true(); // Passes
75-
fact(1)->true(); // Fails due to strict comparison
76-
77-
fact(false)->notTrue(); // Passes
78-
fact(true)->notTrue(); // Fails
79-
80-
fact(false)->false(); // Passes
81-
fact(0)->false(); // Fails due to strict comparison
82-
83-
fact(true)->notFalse(); // Passes
84-
fact(false)->notFalse(); // Fails
85-
```
86-
87-
88-
### Comparison and equality assertions
89-
```php
90-
fact(42)->is(42); // Passes
91-
fact(42)->is('42'); // Fails due to type difference
92-
93-
fact(42)->equals(42); // Passes
94-
fact(42)->equals('42'); // Passes due to loose comparison
95-
96-
fact(42)->not(43); // Passes
97-
fact(42)->not(42); // Fails
98-
```
70+
fact([2, 4, 6])->every(fn($v) => $v % 2 === 0); // Passes
71+
fact([1, 2, 3])->every(fn($v) => $v > 5); // Fails
9972

73+
fact([1, 2, 3])->some(fn($v) => $v > 2); // Passes
74+
fact([1, 2, 3])->some(fn($v) => $v > 10); // Fails
10075

101-
### Null assertions
102-
```php
103-
fact(null)->null(); // Passes
104-
fact('')->null(); // Fails
105-
106-
fact(42)->notNull(); // Passes
107-
fact(null)->notNull(); // Fails
108-
```
109-
110-
### Numeric assertions
111-
```php
112-
fact(5)->isLowerThan(10); // Passes
113-
fact(10)->isLowerThan(5); // Fails
114-
115-
fact(10)->isGreaterThan(5); // Passes
116-
fact(5)->isGreaterThan(10); // Fails
117-
118-
fact(5)->isPositive(); // Passes
119-
fact(-3)->isPositive(); // Fails
120-
121-
fact(-3)->isNegative(); // Passes
122-
fact(5)->isNegative(); // Fails
123-
124-
fact(0)->isZero(); // Passes
125-
fact(0.0)->isZero(); // Passes
126-
fact(1)->isZero(); // Fails
127-
128-
fact(5)->isBetween(1, 10); // Passes
129-
fact(15)->isBetween(1, 10); // Fails
130-
```
131-
132-
### Special assertions
133-
```php
76+
fact([1, 2, 3])->none(fn($v) => $v > 10); // Passes
77+
fact([1, 2, 3])->none(fn($v) => $v > 2); // Fails
13478
```
13579

13680
### String assertions
@@ -174,6 +118,8 @@ fact('invalid json')->isJson(); // Fails
174118
fact('[email protected]')->isValidEmail(); // Passes
175119
fact('invalid-email')->isValidEmail(); // Fails
176120

121+
fact('01ARZ3NDEKTSV4RRFFQ69G5FAV')->ulid(); // Passes (if valid ULID)
122+
fact('invalid-ulid')->ulid(); // Fails
177123
```
178124

179125
### Type Checking assertions

src/FluentAssertions.php

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
use K2gl\PHPUnitFluentAssertions\Traits\ComparisonAndEqualityAssertions;
1010
use K2gl\PHPUnitFluentAssertions\Traits\NullAssertions;
1111
use K2gl\PHPUnitFluentAssertions\Traits\NumericAssertions;
12-
use K2gl\PHPUnitFluentAssertions\Traits\SpecialAssertions;
1312
use K2gl\PHPUnitFluentAssertions\Traits\StringAssertions;
1413
use K2gl\PHPUnitFluentAssertions\Traits\TypeCheckingAssertions;
1514

@@ -22,7 +21,6 @@ class FluentAssertions
2221
use StringAssertions;
2322
use ArrayAssertions;
2423
use TypeCheckingAssertions;
25-
use SpecialAssertions;
2624

2725
public function __construct(
2826
public readonly mixed $variable = null

src/Traits/ArrayAssertions.php

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,4 +240,103 @@ public function isNotEmptyArray(string $message = ''): self
240240

241241
return $this;
242242
}
243+
244+
/**
245+
* Asserts that every element in the array satisfies the given callback.
246+
*
247+
* This method checks if all elements pass the condition defined by the callback.
248+
* The callback receives the value and optionally the key.
249+
*
250+
* Example usage:
251+
* fact([2, 4, 6])->every(fn($v) => $v % 2 === 0); // Passes
252+
* fact([1, 2, 3])->every(fn($v) => $v > 5); // Fails
253+
*
254+
* @param callable $callback The function to test each element (receives value and key).
255+
* @param string $message Optional custom error message.
256+
*
257+
* @return self Enables fluent chaining of assertion methods.
258+
*/
259+
public function every(callable $callback, string $message = ''): self
260+
{
261+
$array = $this->variable;
262+
if (!is_array($array)) {
263+
Assert::assertTrue(false, $message ?: 'Variable is not an array.');
264+
}
265+
if (empty($array)) {
266+
Assert::assertTrue(false, $message ?: 'Array is empty, cannot evaluate condition on elements.');
267+
}
268+
foreach ($array as $key => $value) {
269+
if (!$callback($value, $key)) {
270+
Assert::assertTrue(false, $message ?: 'Not all elements satisfy the condition.');
271+
}
272+
}
273+
Assert::assertTrue(true, $message);
274+
return $this;
275+
}
276+
277+
/**
278+
* Asserts that at least one element in the array satisfies the given callback.
279+
*
280+
* This method checks if any element passes the condition defined by the callback.
281+
* The callback receives the value and optionally the key.
282+
*
283+
* Example usage:
284+
* fact([1, 2, 3])->some(fn($v) => $v > 2); // Passes
285+
* fact([1, 2, 3])->some(fn($v) => $v > 10); // Fails
286+
*
287+
* @param callable $callback The function to test each element (receives value and key).
288+
* @param string $message Optional custom error message.
289+
*
290+
* @return self Enables fluent chaining of assertion methods.
291+
*/
292+
public function some(callable $callback, string $message = ''): self
293+
{
294+
$array = $this->variable;
295+
if (!is_array($array)) {
296+
Assert::assertTrue(false, $message ?: 'Variable is not an array.');
297+
}
298+
if (empty($array)) {
299+
Assert::assertTrue(false, $message ?: 'Array is empty, cannot evaluate condition on elements.');
300+
}
301+
foreach ($array as $key => $value) {
302+
if ($callback($value, $key)) {
303+
Assert::assertTrue(true, $message);
304+
return $this;
305+
}
306+
}
307+
Assert::assertTrue(false, $message ?: 'No elements satisfy the condition.');
308+
}
309+
310+
/**
311+
* Asserts that no elements in the array satisfy the given callback.
312+
*
313+
* This method checks if none of the elements pass the condition defined by the callback.
314+
* The callback receives the value and optionally the key.
315+
*
316+
* Example usage:
317+
* fact([1, 2, 3])->none(fn($v) => $v > 10); // Passes
318+
* fact([1, 2, 3])->none(fn($v) => $v > 2); // Fails
319+
*
320+
* @param callable $callback The function to test each element (receives value and key).
321+
* @param string $message Optional custom error message.
322+
*
323+
* @return self Enables fluent chaining of assertion methods.
324+
*/
325+
public function none(callable $callback, string $message = ''): self
326+
{
327+
$array = $this->variable;
328+
if (!is_array($array)) {
329+
Assert::assertTrue(false, $message ?: 'Variable is not an array.');
330+
}
331+
if (empty($array)) {
332+
Assert::assertTrue(false, $message ?: 'Array is empty, cannot evaluate condition on elements.');
333+
}
334+
foreach ($array as $key => $value) {
335+
if ($callback($value, $key)) {
336+
Assert::assertTrue(false, $message ?: 'At least one element satisfies the condition.');
337+
}
338+
}
339+
Assert::assertTrue(true, $message);
340+
return $this;
341+
}
243342
}

src/Traits/SpecialAssertions.php

Lines changed: 0 additions & 15 deletions
This file was deleted.

src/Traits/StringAssertions.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ trait StringAssertions
2727
* @param string $pattern The regular expression pattern to match against.
2828
* @param string $message Optional custom error message.
2929
*
30-
* @return self Enables fluent chaining of assertion methods.
30+
* @return StringAssertions|FluentAssertions Enables fluent chaining of assertion methods.
3131
*/
3232
public function matchesRegularExpression(string $pattern, string $message = ''): self
3333
{
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
<?php declare(strict_types=1);
2+
3+
namespace K2gl\PHPUnitFluentAssertions\Tests\FluentAssertions\Asserts\Every;
4+
5+
use K2gl\PHPUnitFluentAssertions\Tests\FluentAssertions\FluentAssertionsTestCase;
6+
use K2gl\PHPUnitFluentAssertions\FluentAssertions;
7+
use PHPUnit\Framework\Attributes\CoversMethod;
8+
use PHPUnit\Framework\Attributes\DataProvider;
9+
10+
use function K2gl\PHPUnitFluentAssertions\fact;
11+
12+
#[CoversMethod(className: FluentAssertions::class, methodName: 'every')]
13+
final class EveryTest extends FluentAssertionsTestCase
14+
{
15+
#[DataProvider('everyDataProvider')]
16+
public function testEvery(mixed $variable, callable $callback): void
17+
{
18+
// act
19+
fact($variable)->every($callback);
20+
21+
// assert
22+
$this->correctAssertionExecuted();
23+
}
24+
25+
#[DataProvider('notEveryDataProvider')]
26+
public function testNotEvery(mixed $variable, callable $callback): void
27+
{
28+
// assert
29+
$this->incorrectAssertionExpected();
30+
31+
// act
32+
fact($variable)->every($callback);
33+
}
34+
35+
public static function everyDataProvider(): array
36+
{
37+
return [
38+
[[2, 4, 6], fn($v) => $v % 2 === 0],
39+
[['a' => 1, 'b' => 3], fn($v, $k) => $v > 0],
40+
];
41+
}
42+
43+
public static function notEveryDataProvider(): array
44+
{
45+
return [
46+
[[1, 2, 3], fn($v) => $v > 5],
47+
[[], fn($v) => true], // empty array
48+
['not array', fn($v) => true], // not array
49+
];
50+
}
51+
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
<?php declare(strict_types=1);
2+
3+
namespace K2gl\PHPUnitFluentAssertions\Tests\FluentAssertions\Asserts\None;
4+
5+
use K2gl\PHPUnitFluentAssertions\Tests\FluentAssertions\FluentAssertionsTestCase;
6+
use K2gl\PHPUnitFluentAssertions\FluentAssertions;
7+
use PHPUnit\Framework\Attributes\CoversMethod;
8+
use PHPUnit\Framework\Attributes\DataProvider;
9+
10+
use function K2gl\PHPUnitFluentAssertions\fact;
11+
12+
#[CoversMethod(className: FluentAssertions::class, methodName: 'none')]
13+
final class NoneTest extends FluentAssertionsTestCase
14+
{
15+
#[DataProvider('noneDataProvider')]
16+
public function testNone(mixed $variable, callable $callback): void
17+
{
18+
// act
19+
fact($variable)->none($callback);
20+
21+
// assert
22+
$this->correctAssertionExecuted();
23+
}
24+
25+
#[DataProvider('notNoneDataProvider')]
26+
public function testNotNone(mixed $variable, callable $callback): void
27+
{
28+
// assert
29+
$this->incorrectAssertionExpected();
30+
31+
// act
32+
fact($variable)->none($callback);
33+
}
34+
35+
public static function noneDataProvider(): array
36+
{
37+
return [
38+
[[1, 2, 3], fn($v) => $v > 10],
39+
[['a' => 1, 'b' => 2], fn($v, $k) => $k === 'c'],
40+
];
41+
}
42+
43+
public static function notNoneDataProvider(): array
44+
{
45+
return [
46+
[[1, 2, 3], fn($v) => $v > 2],
47+
[[], fn($v) => true], // empty array
48+
['not array', fn($v) => true], // not array
49+
];
50+
}
51+
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
<?php declare(strict_types=1);
2+
3+
namespace K2gl\PHPUnitFluentAssertions\Tests\FluentAssertions\Asserts\Some;
4+
5+
use K2gl\PHPUnitFluentAssertions\Tests\FluentAssertions\FluentAssertionsTestCase;
6+
use K2gl\PHPUnitFluentAssertions\FluentAssertions;
7+
use PHPUnit\Framework\Attributes\CoversMethod;
8+
use PHPUnit\Framework\Attributes\DataProvider;
9+
10+
use function K2gl\PHPUnitFluentAssertions\fact;
11+
12+
#[CoversMethod(className: FluentAssertions::class, methodName: 'some')]
13+
final class SomeTest extends FluentAssertionsTestCase
14+
{
15+
#[DataProvider('someDataProvider')]
16+
public function testSome(mixed $variable, callable $callback): void
17+
{
18+
// act
19+
fact($variable)->some($callback);
20+
21+
// assert
22+
$this->correctAssertionExecuted();
23+
}
24+
25+
#[DataProvider('notSomeDataProvider')]
26+
public function testNotSome(mixed $variable, callable $callback): void
27+
{
28+
// assert
29+
$this->incorrectAssertionExpected();
30+
31+
// act
32+
fact($variable)->some($callback);
33+
}
34+
35+
public static function someDataProvider(): array
36+
{
37+
return [
38+
[[1, 2, 3], fn($v) => $v > 2],
39+
[['a' => 1, 'b' => 2], fn($v, $k) => $k === 'b'],
40+
];
41+
}
42+
43+
public static function notSomeDataProvider(): array
44+
{
45+
return [
46+
[[1, 2, 3], fn($v) => $v > 10],
47+
[[], fn($v) => true], // empty array
48+
['not array', fn($v) => true], // not array
49+
];
50+
}
51+
}

0 commit comments

Comments
 (0)