diff --git a/.github/workflows/run-tests-coverage.yml b/.github/workflows/run-tests-coverage.yml index 9141917..52e31cf 100644 --- a/.github/workflows/run-tests-coverage.yml +++ b/.github/workflows/run-tests-coverage.yml @@ -13,8 +13,8 @@ jobs: strategy: matrix: operating-system: [ubuntu-latest] - php-versions: [ '8.3' ] - dependency-stability: [ 'prefer-none' ] + php-versions: ["8.5"] + dependency-stability: ["prefer-none"] name: P${{ matrix.php-versions }} - L${{ matrix.laravel }} - ${{ matrix.dependency-stability }} - ${{ matrix.operating-system}} @@ -24,6 +24,7 @@ jobs: uses: shivammathur/setup-php@v2 with: php-version: ${{ matrix.php-versions }} + coverage: xdebug - name: Install Dependencies if: steps.vendor-cache.outputs.cache-hit != 'true' run: composer install -q --no-ansi --no-interaction --no-scripts --no-progress --prefer-dist @@ -35,7 +36,6 @@ jobs: if: matrix.dependency-stability == 'prefer-lowest' run: composer update --prefer-stable --prefer-lowest - - name: Show dir run: pwd - name: PHP Version @@ -43,15 +43,15 @@ jobs: # Code quality - - name: Execute tests (Unit and Feature tests) via PestPHP + - name: Execute tests (Unit and Feature tests) via PHPUnit # Set environment env: SESSION_DRIVER: array - run: vendor/bin/pest --coverage-clover clover.xml + run: vendor/bin/phpunit --coverage-clover clover.xml - name: Generate test coverage badge uses: timkrase/phpunit-coverage-badge@v1.2.1 with: - coverage_badge_path: 'badge-coverage.svg' + coverage_badge_path: "badge-coverage.svg" push_badge: true repo_token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index 95cb062..e589d16 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -9,12 +9,12 @@ jobs: fail-fast: true matrix: os: [ubuntu-latest, windows-latest] - php: [8.1, 8.2, 8.3] + php: [8.2, 8.3, 8.4, 8.5] exclude: - - os: windows-latest - php: 8.1 - os: windows-latest php: 8.2 + - os: windows-latest + php: 8.3 name: P${{ matrix.php }} - ${{ matrix.os }} @@ -27,7 +27,7 @@ jobs: with: php-version: ${{ matrix.php }} extensions: dom, curl, libxml, mbstring, zip, pcntl, bcmath, intl, iconv, fileinfo - coverage: none + coverage: xdebug - name: Setup problem matchers run: | diff --git a/.gitignore b/.gitignore index 3b3fcd5..3c5de25 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,4 @@ vendor .php-cs-fixer.cache /.phpunit.cache .DS_Store +.build/ diff --git a/CHANGELOG.md b/CHANGELOG.md index c9f3e9b..3bacc9d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Changelog +## 2.0.0 - WIP +- Update to PHP 8.5 +- Migrate tests from Pest PHP v2 to PHPUnit 11 +- Remove deprecated code + ## 1.1.0 - 2024-06-13 - Add the Arr `set()` method supports 'dot' (or custom) notation for nested arrays for setting nested values, for example, `$arr`->set('first-level.second-level.third-level', "something")` - Renamed the `$index` parameter, into `$key` for `set()` and `get()` method. Why: in my opinion "index" is more related to array integer keys . "key" is more generic and refers to generic keys (string for example). diff --git a/composer.json b/composer.json index 7cd9c7e..64e7b5d 100644 --- a/composer.json +++ b/composer.json @@ -15,11 +15,11 @@ } ], "require": { - "php": "^8.1|^8.2|^8.3" + "php": "^8.2|^8.3|^8.4|^8.5" }, "require-dev": { "laravel/pint": "^1.2", - "pestphp/pest": "^2", + "phpunit/phpunit": "^11.0", "phpstan/phpstan": "^1.6", "rector/rector": "^1" }, @@ -35,18 +35,17 @@ }, "scripts": { "all": [ - "@test", "@format", "@phpstan" + "@test", + "@format", + "@phpstan" ], - "test": "vendor/bin/pest", - "test-coverage": "vendor/bin/pest --coverage", + "test": "vendor/bin/phpunit", + "test-coverage": "vendor/bin/phpunit --coverage-html ./.build/tests", "phpstan": "vendor/bin/phpstan", "format": "vendor/bin/pint" }, "config": { - "sort-packages": true, - "allow-plugins": { - "pestphp/pest-plugin": true - } + "sort-packages": true }, "minimum-stability": "dev", "prefer-stable": true diff --git a/phpunit.xml.dist b/phpunit.xml.dist index d67e5d2..5ec8aae 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -1,5 +1,5 @@ - + tests diff --git a/src/Arr.php b/src/Arr.php index b1fbea5..01fc73c 100755 --- a/src/Arr.php +++ b/src/Arr.php @@ -432,7 +432,7 @@ public function join(string $separator = ','): string * @param int $start start index (array start from 0, start included) * @param int|null $end end index (array starts from 0, end not included) */ - public function slice(int $start, int $end = null): Arr + public function slice(int $start, ?int $end = null): Arr { if (is_null($end)) { $end = $this->length(); @@ -507,7 +507,7 @@ public function some(callable $callback): bool * * @param int|null $fromIndex */ - public function includes(mixed $element, int $fromIndex = null): bool + public function includes(mixed $element, ?int $fromIndex = null): bool { if (is_null($fromIndex)) { return in_array($element, $this->arr, true); @@ -598,7 +598,7 @@ public function flatMap(callable $callback): self * @param int $start start index (from 0) * @param int|null $end end index (default, the end of array) */ - public function fill(mixed $value, int $start = 0, int $end = null): void + public function fill(mixed $value, int $start = 0, ?int $end = null): void { if (is_null($end)) { $end = $this->length() - 1; @@ -665,7 +665,7 @@ public function sort(): Arr * @param int|null $deleteCount an integer indicating the number of elements in the array to remove from $start * @return Arr an array containing the deleted elements */ - public function splice(int $start, int $deleteCount = null, mixed $newElements = []): Arr + public function splice(int $start, ?int $deleteCount = null, mixed $newElements = []): Arr { return self::make(array_splice($this->arr, $start, $deleteCount, $newElements)); } @@ -770,7 +770,7 @@ public function find(callable $callback): mixed * @param int|null $end * @return array */ - public function copyWithin(int $target, int $start = 0, int $end = null): array + public function copyWithin(int $target, int $start = 0, ?int $end = null): array { $arrayLength = $this->length(); $chuck = $this->slice($start, $end); diff --git a/tests/Arr/ArrFromTest.php b/tests/Arr/ArrFromTest.php index 03edf37..1a92b2e 100644 --- a/tests/Arr/ArrFromTest.php +++ b/tests/Arr/ArrFromTest.php @@ -1,28 +1,36 @@ arr()) - ->toBeArray() - ->toBe(['f','o','o']); -}); +use HiFolks\DataType\Arr; +use PHPUnit\Framework\TestCase; -it('converts a generator to an array', function (): void { - function generator(): Generator +class ArrFromTest extends TestCase +{ + public function test_converts_a_string_to_an_array(): void { - yield 1; - yield 8; - yield 7; + $result = Arr::from('foo')->arr(); + $this->assertIsArray($result); + $this->assertSame(['f', 'o', 'o'], $result); } - expect(Arr::from(generator())->arr()) - ->toBeArray() - ->toBe([1, 8, 7]); -}); + public function test_converts_a_generator_to_an_array(): void + { + $generator = function (): \Generator { + yield 1; + yield 8; + yield 7; + }; -it('takes a function to map over the given array', function (): void { - expect(Arr::from([1, 2, 3], fn ($x): float|int|array => $x + $x)->arr()) - ->toBeArray() - ->toBe([2, 4, 6]); -}); + $result = Arr::from($generator())->arr(); + $this->assertIsArray($result); + $this->assertSame([1, 8, 7], $result); + } + + public function test_takes_a_function_to_map_over_the_given_array(): void + { + $result = Arr::from([1, 2, 3], fn ($x): float|int|array => $x + $x)->arr(); + $this->assertIsArray($result); + $this->assertSame([2, 4, 6], $result); + } +} diff --git a/tests/ArrGetTest.php b/tests/ArrGetTest.php index 8130f0d..266a469 100644 --- a/tests/ArrGetTest.php +++ b/tests/ArrGetTest.php @@ -1,108 +1,116 @@ get(1))->toBe('B'); - expect($arr->get(4))->toBeNull(); - expect($arr->get(4, 'AAAA'))->toBe("AAAA"); -}); +namespace HiFolks\Array\Tests; -it('Basic nested get', function (): void { - $arr = Arr::make([ - 'A' => 'First', - 'B' => ['some', 'thing'], - 'C' => [ 'nested-item-1' => 10, 'nested-item-2' => 20], - 'D' => [] - ]); - expect($arr->get('A'))->toBe('First'); - expect($arr->get('B'))->toBeArray(); - expect($arr->get('B.0'))->toBe('some'); - expect($arr->get('B.1'))->toBe('thing'); - expect($arr->get('B.2'))->toBeNull(); - expect($arr->get('B.2', 1234))->toBe(1234); - expect($arr->get('B#0', charNestedKey: '#'))->toBe('some'); - expect($arr->get('B#1', charNestedKey: '#'))->toBe('thing'); - expect($arr->get('B#2', charNestedKey: '#'))->toBeNull(); - expect($arr->get('B#2', 1234, '#'))->toBe(1234); - - expect($arr->get('C.0'))->toBeNull(); - expect($arr->get('C.nested-item-1'))->toBe(10); - expect($arr->get('C.nested-item-2'))->toBe(20); - expect($arr->get('C.nested-item-2.other'))->toBeNull(); - expect($arr->get('C.nested-item-2.other', 'zzz'))->toBe('zzz'); - expect($arr->get('C#nested-item-2#other', 'zzz', '#'))->toBe('zzz'); - expect($arr->get('C#nested-item-2#other', 'zzz'))->toBe('zzz'); - expect($arr->get('C#nested-item-2', 'zzz'))->toBe('zzz'); - expect($arr->get('C#nested-item-4', 'zzz'))->toBe('zzz'); - expect($arr->get('D#nested-item-4', 'zzz'))->toBe('zzz'); - expect($arr->get('D.0'))->toBeNull(); - expect($arr->get('D', '0'))->toBeArray()->toHaveLength(0); +use HiFolks\DataType\Arr; +use PHPUnit\Framework\TestCase; -}); +class ArrGetTest extends TestCase +{ + public function test_basic_get(): void + { + $arr = Arr::make(['A', 'B', 'C']); + $this->assertSame('B', $arr->get(1)); + $this->assertNull($arr->get(4)); + $this->assertSame("AAAA", $arr->get(4, 'AAAA')); + } + public function test_basic_nested_get(): void + { + $arr = Arr::make([ + 'A' => 'First', + 'B' => ['some', 'thing'], + 'C' => ['nested-item-1' => 10, 'nested-item-2' => 20], + 'D' => [] + ]); + $this->assertSame('First', $arr->get('A')); + $this->assertIsArray($arr->get('B')); + $this->assertSame('some', $arr->get('B.0')); + $this->assertSame('thing', $arr->get('B.1')); + $this->assertNull($arr->get('B.2')); + $this->assertSame(1234, $arr->get('B.2', 1234)); + $this->assertSame('some', $arr->get('B#0', charNestedKey: '#')); + $this->assertSame('thing', $arr->get('B#1', charNestedKey: '#')); + $this->assertNull($arr->get('B#2', charNestedKey: '#')); + $this->assertSame(1234, $arr->get('B#2', 1234, '#')); -it('Basic getArr', function (): void { - $arr = Arr::make(['A','B','C']); - expect($arr->getArr(1))->toBeInstanceOf(Arr::class); - expect($arr->getArr(1)->at(0))->toBe('B'); - expect($arr->getArrNullable(4))->toBeNull(); - expect($arr->getArr(4, 'AAAA'))->toBeInstanceOf(Arr::class); - expect($arr->getArr(4, 'AAAA')->get(0))->toBe('AAAA'); + $this->assertNull($arr->get('C.0')); + $this->assertSame(10, $arr->get('C.nested-item-1')); + $this->assertSame(20, $arr->get('C.nested-item-2')); + $this->assertNull($arr->get('C.nested-item-2.other')); + $this->assertSame('zzz', $arr->get('C.nested-item-2.other', 'zzz')); + $this->assertSame('zzz', $arr->get('C#nested-item-2#other', 'zzz', '#')); + $this->assertSame('zzz', $arr->get('C#nested-item-2#other', 'zzz')); + $this->assertSame('zzz', $arr->get('C#nested-item-2', 'zzz')); + $this->assertSame('zzz', $arr->get('C#nested-item-4', 'zzz')); + $this->assertSame('zzz', $arr->get('D#nested-item-4', 'zzz')); + $this->assertNull($arr->get('D.0')); + $result = $arr->get('D', '0'); + $this->assertIsArray($result); + $this->assertCount(0, $result); + } + public function test_basic_get_arr(): void + { + $arr = Arr::make(['A', 'B', 'C']); + $this->assertInstanceOf(Arr::class, $arr->getArr(1)); + $this->assertSame('B', $arr->getArr(1)->at(0)); + $this->assertNull($arr->getArrNullable(4)); + $this->assertInstanceOf(Arr::class, $arr->getArr(4, 'AAAA')); + $this->assertSame('AAAA', $arr->getArr(4, 'AAAA')->get(0)); - $arr = Arr::make([ - 'A' => 'First', - 'B' => ['some', 'thing'], - 'C' => [ 'nested-item-1' => 10, 'nested-item-2' => 20], - 'D' => [] - ]); + $arr = Arr::make([ + 'A' => 'First', + 'B' => ['some', 'thing'], + 'C' => ['nested-item-1' => 10, 'nested-item-2' => 20], + 'D' => [] + ]); - expect($arr->getArr('C')->get('nested-item-1'))->toBe(10); - expect($arr->getArr('C')->entries()->get(0))->toBeArray(); - expect($arr->getArr('C')->entries()->get(0))->toBe(['nested-item-1',10]); - expect($arr->getArr('C')->keys())->toBe(['nested-item-1','nested-item-2' ]); + $this->assertSame(10, $arr->getArr('C')->get('nested-item-1')); + $this->assertIsArray($arr->getArr('C')->entries()->get(0)); + $this->assertSame(['nested-item-1', 10], $arr->getArr('C')->entries()->get(0)); + $this->assertSame(['nested-item-1', 'nested-item-2'], $arr->getArr('C')->keys()); - $arr = Arr::make( - [ - "avocado" => - [ - 'name' => 'Avocado', - 'fruit' => '🥑', - 'wikipedia' => 'https://en.wikipedia.org/wiki/Avocado' - ], - "apple" => - [ - 'name' => 'Apple', - 'fruit' => '🍎', - 'wikipedia' => 'https://en.wikipedia.org/wiki/Apple' - ], - "banana" => - [ - 'name' => 'Banana', - 'fruit' => '🍌', - 'wikipedia' => 'https://en.wikipedia.org/wiki/Banana' - ], - "cherry" => - [ - 'name' => 'Cherry', - 'fruit' => '🍒', - 'wikipedia' => 'https://en.wikipedia.org/wiki/Cherry' - ], - ] - ); - $appleArr = $arr->getArr("apple"); - expect($appleArr->count())->toBe(3) - ->and($appleArr->get("name"))->toBe('Apple'); - $appleNameArr = $arr->getArr("apple.name"); - expect($appleNameArr->get(0))->toBe('Apple'); - $appleNoExists = $arr->getArr("apple.name.noexists"); - expect($appleNoExists)->toBeInstanceOf(Arr::class); - expect($appleNoExists->count())->toBe(0); - $appleNoExists = $arr->getArrNullable("apple.name.noexists"); - expect($appleNoExists)->toBeNull(); - $appleNoExists = $arr->getArr("apple.name.noexists", "some"); - expect($appleNoExists)->toBeInstanceOf(Arr::class) - ->and($appleNoExists->get(0))->toBe("some"); -}); + $arr = Arr::make( + [ + "avocado" => + [ + 'name' => 'Avocado', + 'fruit' => '🥑', + 'wikipedia' => 'https://en.wikipedia.org/wiki/Avocado' + ], + "apple" => + [ + 'name' => 'Apple', + 'fruit' => '🍎', + 'wikipedia' => 'https://en.wikipedia.org/wiki/Apple' + ], + "banana" => + [ + 'name' => 'Banana', + 'fruit' => '🍌', + 'wikipedia' => 'https://en.wikipedia.org/wiki/Banana' + ], + "cherry" => + [ + 'name' => 'Cherry', + 'fruit' => '🍒', + 'wikipedia' => 'https://en.wikipedia.org/wiki/Cherry' + ], + ] + ); + $appleArr = $arr->getArr("apple"); + $this->assertSame(3, $appleArr->count()); + $this->assertSame('Apple', $appleArr->get("name")); + $appleNameArr = $arr->getArr("apple.name"); + $this->assertSame('Apple', $appleNameArr->get(0)); + $appleNoExists = $arr->getArr("apple.name.noexists"); + $this->assertInstanceOf(Arr::class, $appleNoExists); + $this->assertSame(0, $appleNoExists->count()); + $appleNoExists = $arr->getArrNullable("apple.name.noexists"); + $this->assertNull($appleNoExists); + $appleNoExists = $arr->getArr("apple.name.noexists", "some"); + $this->assertInstanceOf(Arr::class, $appleNoExists); + $this->assertSame("some", $appleNoExists->get(0)); + } +} diff --git a/tests/ArrSetTest.php b/tests/ArrSetTest.php index ce134ab..7054c98 100644 --- a/tests/ArrSetTest.php +++ b/tests/ArrSetTest.php @@ -1,32 +1,36 @@ set(0, 1)); - expect($arr)->toHaveCount(3); - expect($arr->set("some", 1)); - expect($arr)->toHaveCount(4); - $arr->set("some.thing", 123); - expect($arr)->toHaveCount(4); - expect($arr->get("some.thing"))->toBe(123); - $arr->set("test.key.not.exists", "999"); - expect($arr)->toHaveCount(5); - expect($arr->get("test"))->toHaveCount(1); - expect($arr->get("test.key"))->toHaveCount(1); - expect($arr->get("test.XXX"))->toBeNull(); - $arr->set("test#key#not#exists", "111", "#"); - expect($arr)->toHaveCount(5); - expect($arr->get("test"))->toHaveCount(1); - expect($arr->get("test.key"))->toHaveCount(1); - expect($arr->get("test.XXX"))->toBeNull(); - //$arr->set(null,1); -}); +class ArrSetTest extends TestCase +{ + public function test_basic_set(): void + { + $arr = Arr::make(['A', 'B', 'C']); + $arr->set(0, 1); + $this->assertCount(3, $arr); + $arr->set("some", 1); + $this->assertCount(4, $arr); + $arr->set("some.thing", 123); + $this->assertCount(4, $arr); + $this->assertSame(123, $arr->get("some.thing")); + $arr->set("test.key.not.exists", "999"); + $this->assertCount(5, $arr); + $this->assertCount(1, $arr->get("test")); + $this->assertCount(1, $arr->get("test.key")); + $this->assertNull($arr->get("test.XXX")); + $arr->set("test#key#not#exists", "111", "#"); + $this->assertCount(5, $arr); + $this->assertCount(1, $arr->get("test")); + $this->assertCount(1, $arr->get("test.key")); + $this->assertNull($arr->get("test.XXX")); + } -it( - 'Nested set array', - function (): void { + public function test_nested_set_array(): void + { $articleText = "Some words as a sample sentence"; $textFieldArray = [ "type" => "doc", @@ -48,14 +52,13 @@ function (): void { $textField->set("content.0.content.0.type", "text"); $textField->set("content.0.type", "paragraph"); - expect($textField->arr()["content"][0]["content"][0]["text"])->toBe($articleText); - expect($textField->getArr("content.0.content.0.text"))->toHaveCount(1); - expect($textField->get("content.0.content.0.text"))->toBeString(); + $this->assertSame($articleText, $textField->arr()["content"][0]["content"][0]["text"]); + $this->assertCount(1, $textField->getArr("content.0.content.0.text")); + $this->assertIsString($textField->get("content.0.content.0.text")); $textField->set("content.0.content.0.text", "Changing Text"); - expect($textField->arr()["content"][0]["content"][0]["text"])->toBe("Changing Text"); - expect($textField->getArr("content.0.content.0.text"))->toHaveCount(1); - expect($textField->get("content.0.content.0.text"))->toBeString(); - + $this->assertSame("Changing Text", $textField->arr()["content"][0]["content"][0]["text"]); + $this->assertCount(1, $textField->getArr("content.0.content.0.text")); + $this->assertIsString($textField->get("content.0.content.0.text")); } -); +} diff --git a/tests/ArrTest.php b/tests/ArrTest.php index 1b3c090..62f6e68 100644 --- a/tests/ArrTest.php +++ b/tests/ArrTest.php @@ -1,666 +1,729 @@ assertIsArray($arr->arr()); + } + + public function test_creates_arr_from_function(): void + { + $arr = Arr::fromFunction(fn (): int => random_int(0, 100), 500); + $this->assertIsArray($arr->arr()); + $this->assertEquals(500, $arr->length()); + + $this->assertTrue($arr->every(fn ($element): bool => $element >= 0)); + $this->assertTrue($arr->every(fn ($element): bool => $element <= 100)); + + $arr = Arr::fromFunction(fn ($i) => $i, 5000); + $this->assertIsArray($arr->arr()); + $this->assertEquals(5000, $arr->length()); + + $this->assertTrue($arr->every(fn ($element): bool => $element >= 0)); + $this->assertTrue($arr->every(fn ($element): bool => $element <= 5000)); + } + + public function test_creates_arr_from_value(): void + { + $arr = Arr::fromValue(0, 5000); + $this->assertIsArray($arr->arr()); + $this->assertEquals(5000, $arr->length()); + $this->assertTrue($arr->every(fn ($element): bool => $element === 0)); + } + + public function test_is_array_empty(): void + { + $arr = Arr::make(); + $this->assertIsArray($arr->arr()); + $this->assertEquals(0, count($arr->arr())); + $this->assertEquals(0, $arr->count()); + $this->assertEquals(0, $arr->length()); + } + + public function test_is_array_length_1(): void + { + $arr = Arr::make([99]); + $this->assertIsArray($arr->arr()); + $this->assertEquals(1, count($arr->arr())); + $this->assertEquals(1, $arr->count()); + $this->assertEquals(1, $arr->length()); + } + + public function test_is_array_for_each(): void + { + $arr = Arr::make([99, 98]); + $this->assertIsArray($arr->arr()); + $this->assertEquals(2, count($arr->arr())); + $this->assertEquals(2, $arr->count()); + $this->assertEquals(2, $arr->length()); + $this->assertEquals(3, $arr->push(100)); + $this->assertEquals(3, $arr->length()); + $x = $arr->forEach(fn ($element, $key): string => $key * $element . PHP_EOL); + $this->assertEquals(3, $x->length()); + $this->assertEquals(200, $x->get(2)); + } + + public function test_shift_array(): void + { + $arr = Arr::make([99, 98, 97]); + $this->assertEquals(3, $arr->length()); + $this->assertEquals(99, $arr->shift()); + $this->assertEquals(2, $arr->length()); + } + + public function test_unshift_array(): void + { + $arr = Arr::make([99, 98, 97]); + $this->assertEquals(3, $arr->length()); + $this->assertEquals(4, $arr->unshift(200)); + $this->assertEquals(200, $arr->get(0)); + $this->assertEquals(99, $arr->get(1)); + + $arr = Arr::make([1, 2]); + $arr->unshift(0); + $this->assertEquals('0,1,2', $arr->toString()); + $arr->unshift(-2, -1); + $this->assertEquals('-2,-1,0,1,2', $arr->toString()); + } + + public function test_append_array(): void + { + $arr = Arr::make([99, 98, 97])->append([1, 2, 3]); + $this->assertEquals(6, $arr->length()); + $arr->append([12], [13, 14]); + $this->assertEquals(9, $arr->length()); + $arr = Arr::make(); + $arr->append([11]); + $this->assertEquals(1, $arr->length()); + $number = $arr->pop(); + $this->assertEquals(0, $arr->length()); + $this->assertEquals(11, $number); + } + + public function test_joins_arrays(): void + { + $arr = Arr::make([99, 98, 97])->append([1, 2, 3]); + $this->assertEquals('99,98,97,1,2,3', $arr->join()); + } + + public function test_concats_arrays(): void + { + $arr = Arr::make([99, 98, 97])->append([1, 2, 3]); + $arr2 = $arr->concat([1000, 1001]); + $this->assertIsArray($arr2->arr()); + $this->assertEquals(8, $arr2->length()); + $this->assertEquals(6, $arr->length()); + } + + public function test_concats_more_types(): void + { + $arr = Arr::make([99, 98, 97])->concat([1, 2, 3], [1000, 1001]); + $this->assertIsArray($arr->arr()); + $this->assertEquals(8, $arr->length()); + $arr2 = $arr->concat(9, true); + $this->assertEquals(10, $arr2->length()); + $arr3 = $arr->concat($arr2); + $this->assertEquals(18, $arr3->length()); + } + + public function test_concats_indexed_associative_arrays(): void + { + $fruits = Arr::make([ + 3 => '🥝', + -1 => '🍓', + 1 => '🍋', + 'mango' => '🥭', + 'apple' => '🍎', + 'banana' => '🍌', + ]); + $fruits2 = $fruits->concat(['🍊', '🍍']); + + $this->assertIsArray($fruits2->arr()); + $this->assertEquals(8, $fruits2->length()); + $this->assertEquals('🥭', $fruits2['mango']); + $this->assertEquals('🍍', $fruits2[4]); + } + + public function test_slices_arrays(): void + { + $arr = Arr::make([99, 98, 97])->append([1, 2, 3]); + $arr2 = $arr->slice(1, 2); + $this->assertIsArray($arr2->arr()); + $this->assertEquals(1, $arr2->length()); + $this->assertEquals(98, $arr2->get(0)); + $this->assertNull($arr2->get(1)); + $this->assertEquals(6, $arr->length()); + + $animals = Arr::make(['ant', 'bison', 'camel', 'duck', 'elephant']); + $arr = $animals->slice(2, 4); + $this->assertIsArray($arr->arr()); + $this->assertEquals(2, $arr->length()); + $this->assertEquals('camel', $arr[0]); + $this->assertEquals('duck', $arr[1]); + $this->assertNull($arr->get(2)); + + $arr = $animals->slice(2); + $this->assertIsArray($arr->arr()); + $this->assertEquals(3, $arr->length()); + $this->assertEquals('camel', $arr[0]); + $this->assertEquals('duck', $arr[1]); + $this->assertEquals('elephant', $arr[2]); + $this->assertNull($arr->get(3)); + $this->assertNull($arr[3]); + + $arr = $animals->slice(1, 5); + $this->assertIsArray($arr->arr()); + $this->assertEquals(4, $arr->length()); + $this->assertEquals('bison', $arr[0]); + $this->assertEquals('camel', $arr[1]); + $this->assertEquals('duck', $arr[2]); + $this->assertEquals('elephant', $arr[3]); + $this->assertNull($arr->get(4)); + $this->assertNull($arr[4]); + + $arr = $animals->slice(-2); + $this->assertIsArray($arr->arr()); + $this->assertEquals(2, $arr->length()); + $this->assertEquals('duck', $arr[0]); + $this->assertEquals('elephant', $arr[1]); + $this->assertNull($arr->get(2)); + $this->assertNull($arr[2]); + + $arr = $animals->slice(2, -1); + $this->assertIsArray($arr->arr()); + $this->assertEquals(2, $arr->length()); + $this->assertEquals('camel', $arr[0]); + $this->assertEquals('duck', $arr[1]); + $this->assertNull($arr->get(2)); + $this->assertNull($arr[2]); + + $arr = $animals->slice(-3, -1); + $this->assertIsArray($arr->arr()); + $this->assertEquals(2, $arr->length()); + $this->assertEquals('camel', $arr[0]); + $this->assertEquals('duck', $arr[1]); + $this->assertNull($arr->get(2)); + $this->assertNull($arr[2]); + + $arr = $animals->slice(27, -1); + $this->assertIsArray($arr->arr()); + $this->assertEquals(0, $arr->length()); + $this->assertNull($arr[0]); + } + + public function test_searches_arrays(): void + { + $arr = Arr::make([99, 98, 97])->append([1, 2, 3]); + $index = $arr->indexOf(1); + $this->assertIsInt($index); + $this->assertEquals(3, $index); + $this->assertEquals(6, $arr->length()); + $arr = Arr::make(['L' => 'Leon', 'T' => 'Tiger', 'B' => 'Bird']); + $index = $arr->indexOf('Tiger'); + $this->assertIsString($index); + $this->assertEquals('T', $index); + $this->assertEquals(3, $arr->length()); + } + + public function test_searches_last_occurrence_arrays(): void + { + $arr = Arr::make([1, 2, 3, 4, 5, 6, 7, 8, 9, 8, 7, 6, 5, 4, 3, 2, 1]); + $index = $arr->lastIndexOf(5); + $this->assertIsInt($index); + $this->assertEquals(12, $index); + $this->assertEquals(17, $arr->length()); + $arr = Arr::make(['L1' => 'Leon', 'T1' => 'Tiger', 'B1' => 'Bird', 'T2' => 'Tiger', 'B2' => 'Bird']); + $index = $arr->lastIndexOf('Tiger'); + $this->assertIsString($index); + $this->assertEquals('T2', $index); + $this->assertEquals(5, $arr->length()); + } + + public function test_matches_every_element(): void + { + $arr = Arr::make([1, 2, 3, 4, 5, 6, 7, 8, 9, 8, 7, 6, 5, 4, 3, 2, 1]); + $bool = $arr->every(fn ($element): bool => $element > 0); + $this->assertEquals(true, $bool); + $bool = $arr->every(fn ($element): bool => $element > 1); + $this->assertEquals(false, $bool); + $bool = $arr->every(fn ($element): bool => $element > 10000); + $this->assertEquals(false, $bool); + } + + public function test_matches_some_element(): void + { + $arr = Arr::make([1, 2, 3, 4, 5, 6, 7, 8, 9, 8, 7, 6, 5, 4, 3, 2, 1]); + $bool = $arr->some(fn ($element): bool => $element > 0); + $this->assertEquals(true, $bool); + $bool = $arr->some(fn ($element): bool => $element > 1); + $this->assertEquals(true, $bool); + $bool = $arr->some(fn ($element): bool => $element > 10000); + $this->assertEquals(false, $bool); + + $arr = Arr::make([1, 2, 3, 4, 5]); + $even = fn ($element): bool => $element % 2 === 0; + $bool = $arr->some($even); + $this->assertEquals(true, $bool); + } + + public function test_filters_some_element(): void + { + $arr = Arr::make([1, 2, 3, 4, 5, 6, 7, 8, 9, 8, 7, 6, 5, 4, 3, 2, 1]); + $arr2 = $arr->filter(fn ($element): bool => $element > 3); + $this->assertEquals(17, $arr->length()); + $this->assertEquals(11, $arr2->length()); + $this->assertTrue($arr->every(fn ($element): bool => $element > 0)); + $this->assertFalse($arr->every(fn ($element): bool => $element <= 3)); + $this->assertTrue($arr2->every(fn ($element): bool => $element > 3)); + } + + public function test_finds_the_first_element(): void + { + $intArr = Arr::make([1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 11]); + $strArr = Arr::make(['begin', 'middle', 'end']); + + $result = $intArr->find(fn ($element): bool => $element > 0); + $this->assertIsInt($result); + $this->assertEquals(1, $result); + + $result = $intArr->find(fn ($element): bool => $element < 5); + $this->assertIsInt($result); + $this->assertEquals(1, $result); + + $result = $intArr->find(fn ($element): bool => $element > 5); + $this->assertIsInt($result); + $this->assertEquals(6, $result); + + $result = $intArr->find(fn ($element, $index): bool => $element > 1 && $index > 1); + $this->assertIsInt($result); + $this->assertEquals(3, $result); + + $result = $intArr->find(fn ($element): bool => $element > 50); + $this->assertNull($result); + + $result = $strArr->find(fn ($element): bool => $element == 'end'); + $this->assertIsString($result); + $this->assertSame('end', $result); + + $result = $strArr->find(fn ($element): bool => str_contains((string) $element, 'e')); + $this->assertIsString($result); + $this->assertSame('begin', $result); + + $result = $strArr->find(fn ($element): bool => $element == 'prefix'); + $this->assertNull($result); + } + + public function test_finds_the_first_index_of_some_element(): void + { + $arr = Arr::make([1, 2, 3, 4, 5, 6, 7, 8, 9, 8, 7, 6, 5, 4, 3, 2, 1]); + $index = $arr->findIndex(fn ($element): bool => $element > 0); + $this->assertIsInt($index); + $this->assertEquals(0, $index); + $index = $arr->findIndex(fn ($element): bool => $element > 1); + $this->assertEquals(1, $index); + $index = $arr->findIndex(fn ($element): bool => $element > 10000); + $this->assertEquals(-1, $index); + $index = $arr->findIndex(fn ($element, $index): bool => $element > 1 && $index > 1); + $this->assertEquals(2, $index); + } + + public function test_maps_elements(): void + { + $arr = Arr::make([1, 2, 3, 4, 5, 6, 7, 8, 9, 8, 7, 6, 5, 4, 3, 2, 1]); + $arr2 = $arr->map(fn ($element): int|float => $element + 1); + + $this->assertEquals(17, $arr->length()); + $this->assertEquals(17, $arr2->length()); + $this->assertTrue($arr->every(fn ($element): bool => $element > 0)); + $this->assertFalse($arr->every(fn ($element): bool => $element > 1)); + $this->assertTrue($arr2->every(fn ($element): bool => $element > 1)); + } + + public function test_flats_array(): void + { + $arr = Arr::make([1, [2, 3], 4, [5, 6, 7]]); + + $arr2 = $arr->flat(); + $this->assertEquals(4, $arr->length()); + $this->assertEquals(7, $arr2->length()); + } + + public function test_flats_and_maps_array(): void + { + $arr = Arr::make([1, 2, 3, 4, 5, 6, 7]); + + $arr2 = $arr->flatMap(fn ($element): array => [$element, $element * 2]); + $this->assertEquals(7, $arr->length()); + $this->assertEquals(14, $arr2->length()); + $this->assertEquals([1, 2, 2, 4, 3, 6, 4, 8, 5, 10, 6, 12, 7, 14], $arr2->arr()); + + $arr2 = $arr->flatMap(fn ($element) => $element); + $this->assertEquals(7, $arr->length()); + $this->assertEquals(7, $arr2->length()); + $this->assertEquals([1, 2, 3, 4, 5, 6, 7], $arr2->arr()); + } + + public function test_fills_array(): void + { + $arr = Arr::make([1, 2, 3, 4, 5, 6, 7]); + $this->assertEquals(7, $arr->length()); + $arr->fill(0, 0, 3); + $this->assertEquals(7, $arr->length()); + $this->assertEquals(0, $arr[0]); + $this->assertEquals(0, $arr[1]); + $this->assertEquals(0, $arr[2]); + $this->assertEquals(0, $arr[3]); + $this->assertEquals(5, $arr[4]); + $this->assertEquals(6, $arr[5]); + $this->assertEquals(7, $arr[6]); + $arr2 = $arr->filter(fn ($element): bool => $element == 0); + $this->assertEquals(4, $arr2->length()); + $arr = Arr::make([1, 2, 3, 4, 5, 6, 7]); + $arr->fill(0); + $allAreZeros = $arr->every(fn ($element): bool => $element === 0); + $this->assertEquals(7, $arr->length()); + $this->assertTrue($allAreZeros); + } + + public function test_reduces_arr(): void + { + $arr = Arr::make([1, 2, 3, 4, 5, 6, 7]); + $value = $arr->reduce(fn ($previousValue, $currentValue): float|int|array => $previousValue + $currentValue); + $this->assertIsInt($value); + $this->assertEquals(28, $value); + } + + public function test_reduces_arr_in_reverse_way(): void + { + $arr = Arr::make([1, 2, 3, 4, 5, 6, 7]); + $value = $arr->reduceRight(fn ($previousValue, $currentValue): float|int|array => $previousValue + $currentValue); + $this->assertIsInt($value); + $this->assertEquals(28, $value); + } + + public function test_reverses_arr(): void + { + $arr = Arr::make([1, 2, 3, 4, 5, 6, 7]); + $arr2 = $arr->reverse(); + $this->assertEquals(7, $arr2->length()); + $this->assertEquals('7,6,5,4,3,2,1', $arr2->join()); + $this->assertEquals('7,6,5,4,3,2,1', $arr->join()); + $arr->push(0); + $this->assertEquals('7,6,5,4,3,2,1', $arr2->join()); + $this->assertEquals('7,6,5,4,3,2,1,0', $arr->join()); + } + + public function test_sorts_arr(): void + { + $arr = Arr::make([6, 2, 4, 2, 1, 9, 7]); + $this->assertEquals('6,2,4,2,1,9,7', $arr->join()); + $arr->sort(); + $this->assertEquals(7, $arr->length()); + $this->assertEquals('1,2,2,4,6,7,9', $arr->join()); + } + + public function test_sorts_and_change_arr(): void + { + $months = Arr::make(['March', 'Jan', 'Feb', 'Dec']); + $monthsSorted = $months->sort(); + $this->assertEquals(4, $months->length()); + $this->assertEquals(4, $monthsSorted->length()); + $this->assertEquals('March', $months[3]); + $this->assertEquals('March', $monthsSorted[3]); + $month = $months->pop(); + $this->assertEquals('March', $month); + $this->assertNull($months[3]); + $this->assertNull($monthsSorted[3]); + } + + public function test_splices_arr(): void + { + $months = Arr::make(['Jan', 'March', 'April', 'June']); + $months->splice(1, 0, 'Feb'); + $this->assertEquals('Jan,Feb,March,April,June', $months->join()); + $months->splice(4, 1, 'May'); + $this->assertEquals('Jan,Feb,March,April,May', $months->join()); + $months->splice(1); + $this->assertEquals('Jan', $months->join()); + } + + public function test_stringifies_an_arr(): void + { + $months = Arr::make(['Jan', 'Feb', 'March', 'April', 'May']); + $this->assertEquals('Jan,Feb,March,April,May', $months->toString()); + + $arr = Arr::make([1, 2, 'a', '1a']); + $this->assertEquals('1,2,a,1a', $arr->toString()); + } + + public function test_checks_is_array(): void + { + $isArray = Arr::isArray(['Jan', 'Feb', 'March', 'April', 'May']); + $this->assertEquals(true, $isArray); + $isArray = Arr::isArray(null); + $this->assertEquals(false, $isArray); + $isArray = Arr::isArray(1); + $this->assertEquals(false, $isArray); + $isArray = Arr::isArray(0); + $this->assertEquals(false, $isArray); + } + + public function test_tests_if_array_is_empty(): void + { + $emptyArr = Arr::make([]); + $this->assertEquals(true, $emptyArr->isEmpty()); + $notEmptyArr = Arr::make([1]); + $this->assertEquals(false, $notEmptyArr->isEmpty()); + } + + public function test_chainable_empty_array(): void + { + $arr = Arr::make([1, 2, 3, 4, 5, 6, 7, 8, 9, 8, 7, 6, 5, 4, 3, 2, 1]); + $this->assertTrue($arr->filter(fn ($element): bool => $element > 100)->isEmpty()); + $this->assertFalse($arr->filter(fn ($element): bool => $element < 100)->isEmpty()); + } + + public function test_implements_of_method(): void + { + $arr = Arr::of('Jan', 'Feb', 'March', 'April', 'May'); + $this->assertEquals(5, $arr->length()); + $this->assertEquals('May', $arr[4]); + + $arr = Arr::of(7); + $this->assertEquals(1, $arr->length()); + $this->assertEquals(7, $arr[0]); + } + + public function test_tests_keys_method(): void + { + $arr = Arr::make( + [ + '01' => 'Jan', '02' => 'Feb', '03' => 'March', '04' => 'April', + '05' => 'May', '06' => 'Jun', '07' => 'Jul', '08' => 'Aug', + '09' => 'Sep', '10' => 'Oct', '11' => 'Nov', '12' => 'Dec', + ] + ); + $this->assertEquals(12, $arr->length()); + $arrKeys = $arr->keys(true); + $this->assertIsObject($arrKeys); + $this->assertEquals(12, $arrKeys->length()); + $this->assertEquals('05', $arrKeys[4]); + + $keys = $arr->keys(); + $this->assertIsArray($keys); + $this->assertEquals(12, is_countable($keys) ? count($keys) : 0); + $this->assertEquals('05', $keys[4]); + + foreach ($arrKeys as $key => $value) { + $this->assertEquals($keys[$key], $arrKeys[$key]); + } + } + + public function test_at_method(): void + { + $arr = Arr::make( + [5, 12, 8, 130, 44] + ); + $this->assertEquals(5, $arr->length()); + $this->assertEquals(8, $arr->at(2)); + $this->assertEquals(130, $arr->at(-2)); + $this->assertNull($arr->at(100)); + } + + public function test_includes_element(): void + { + $arr = Arr::make( + [1, 2, 3] + ); + $this->assertEquals(3, $arr->length()); + $this->assertTrue($arr->includes(2)); + $this->assertFalse($arr->includes('2')); + + $arr = Arr::make( + ['cat', 'dog', 'bat'] + ); + $this->assertEquals(3, $arr->length()); + $this->assertTrue($arr->includes('cat')); + $this->assertFalse($arr->includes('Cat')); + $this->assertFalse($arr->includes('at')); + } + + public function test_includes_element_from_index(): void + { + $arr = Arr::make( + [1, 2, 3] + ); + $this->assertEquals(3, $arr->length()); + $this->assertTrue($arr->includes(2)); + $this->assertFalse($arr->includes(4)); + $this->assertFalse($arr->includes(3, 3)); + $this->assertTrue($arr->includes(3, 2)); + $this->assertTrue($arr->includes(3, -1)); + + $arr = Arr::make( + ['a', 'b', 'c'] + ); + $this->assertFalse($arr->includes('c', 3)); + $this->assertFalse($arr->includes('c', 100)); + + $this->assertTrue($arr->includes('a', -100)); + $this->assertTrue($arr->includes('b', -100)); + $this->assertTrue($arr->includes('c', -100)); + $this->assertFalse($arr->includes('a', -2)); + } + + public function test_extract_values(): void + { + $fruits = Arr::make([ + 7 => '🥝', + -1 => '🍓', + 1 => '🍋', + 'mango' => '🥭', + 'apple' => '🍎', + 'banana' => '🍌', + '🍊', + '🍍', + ]); -it('is Array', function (): void { - $arr = Arr::make(); - expect($arr->arr())->toBeArray(); -}); - -it('creates Arr from function', function (): void { - $arr = Arr::fromFunction(fn (): int => random_int(0, 100), 500); - expect($arr->arr())->toBeArray(); - expect($arr->length())->toEqual(500); - - expect($arr->every(fn ($element): bool => $element >= 0))->toBeTrue(); - expect($arr->every(fn ($element): bool => $element <= 100))->toBeTrue(); - - $arr = Arr::fromFunction(fn ($i) => $i, 5000); - expect($arr->arr())->toBeArray(); - expect($arr->length())->toEqual(5000); - //print_result($arr); - - expect($arr->every(fn ($element): bool => $element >= 0))->toBeTrue(); - expect($arr->every(fn ($element): bool => $element <= 5000))->toBeTrue(); -}); - -it('creates Arr from value', function (): void { - $arr = Arr::fromValue(0, 5000); - expect($arr->arr())->toBeArray(); - expect($arr->length())->toEqual(5000); - expect($arr->every(fn ($element): bool => $element === 0))->toBeTrue(); -}); - -it('is Array empty', function (): void { - $arr = Arr::make(); - expect($arr->arr())->toBeArray(); - expect(count($arr->arr()))->toEqual(0); - expect($arr->count())->toEqual(0); - expect($arr->length())->toEqual(0); -}); -it('is Array length 1', function (): void { - $arr = Arr::make([99]); - expect($arr->arr())->toBeArray(); - expect(count($arr->arr()))->toEqual(1); - expect($arr->count())->toEqual(1); - expect($arr->length())->toEqual(1); -}); - -it('is Array forEach', function (): void { - $arr = Arr::make([99, 98]); - expect($arr->arr())->toBeArray(); - expect(count($arr->arr()))->toEqual(2); - expect($arr->count())->toEqual(2); - expect($arr->length())->toEqual(2); - expect($arr->push(100))->toEqual(3); - expect($arr->length())->toEqual(3); - $x = $arr->forEach(fn ($element, $key): string => $key * $element.PHP_EOL); - expect($x->length())->toEqual(3); - expect($x->get(2))->toEqual(200); -}); - -it('shift array', function (): void { - $arr = Arr::make([99, 98, 97]); - expect($arr->length())->toEqual(3); - expect($arr->shift())->toEqual(99); - expect($arr->length())->toEqual(2); -}); - -it('unshift array', function (): void { - $arr = Arr::make([99, 98, 97]); - expect($arr->length())->toEqual(3); - expect($arr->unshift(200))->toEqual(4); - expect($arr->get(0))->toEqual(200); - expect($arr->get(1))->toEqual(99); - - $arr = Arr::make([1, 2]); - $arr->unshift(0); - expect($arr->toString())->toEqual('0,1,2'); - $arr->unshift(-2, -1); - expect($arr->toString())->toEqual('-2,-1,0,1,2'); -}); -it('append array', function (): void { - $arr = Arr::make([99, 98, 97])->append([1, 2, 3]); - expect($arr->length())->toEqual(6); - $arr->append([12], [13, 14]); - expect($arr->length())->toEqual(9); - $arr = Arr::make(); - $arr->append([11]); - expect($arr->length())->toEqual(1); - $number = $arr->pop(); - expect($arr->length())->toEqual(0); - expect($number)->toEqual(11); -}); -it('joins arrays', function (): void { - $arr = Arr::make([99, 98, 97])->append([1, 2, 3]); - expect($arr->join())->toEqual('99,98,97,1,2,3'); -}); - -it('concats arrays', function (): void { - $arr = Arr::make([99, 98, 97])->append([1, 2, 3]); - $arr2 = $arr->concat([1000, 1001]); - expect($arr2->arr())->toBeArray(); - expect($arr2->length())->toEqual(8); - expect($arr->length())->toEqual(6); -}); -it('concats more types', function (): void { - $arr = Arr::make([99, 98, 97])->concat([1, 2, 3], [1000, 1001]); - expect($arr->arr())->toBeArray(); - expect($arr->length())->toEqual(8); - $arr2 = $arr->concat(9, true); - expect($arr2->length())->toEqual(10); - $arr3 = $arr->concat($arr2); - expect($arr3->length())->toEqual(18); -}); -it('concats indexed/associative arrays', function (): void { - $fruits = Arr::make([ - 3 => '🥝', - -1 => '🍓', - 1 => '🍋', - 'mango' => '🥭', - 'apple' => '🍎', - 'banana' => '🍌', ]); - $fruits2 = $fruits->concat(['🍊', '🍍']); - - expect($fruits2->arr())->toBeArray(); - expect($fruits2->length())->toEqual(8); - expect($fruits2['mango'])->toEqual('🥭'); - expect($fruits2[4])->toEqual('🍍'); -}); -it('slices arrays', function (): void { - $arr = Arr::make([99, 98, 97])->append([1, 2, 3]); - $arr2 = $arr->slice(1, 2); - expect($arr2->arr())->toBeArray(); - expect($arr2->length())->toEqual(1); - expect($arr2->get(0))->toEqual(98); - expect($arr2->get(1))->toBeNull(); - expect($arr->length())->toEqual(6); - - $animals = Arr::make(['ant', 'bison', 'camel', 'duck', 'elephant']); - $arr = $animals->slice(2, 4); - expect($arr->arr())->toBeArray(); - expect($arr->length())->toEqual(2); - expect($arr[0])->toEqual('camel'); - expect($arr[1])->toEqual('duck'); - expect($arr->get(2))->toBeNull(); - - $arr = $animals->slice(2); - expect($arr->arr())->toBeArray(); - expect($arr->length())->toEqual(3); - expect($arr[0])->toEqual('camel'); - expect($arr[1])->toEqual('duck'); - expect($arr[2])->toEqual('elephant'); - expect($arr->get(3))->toBeNull(); - expect($arr[3])->toBeNull(); - - $arr = $animals->slice(1, 5); - expect($arr->arr())->toBeArray(); - expect($arr->length())->toEqual(4); - expect($arr[0])->toEqual('bison'); - expect($arr[1])->toEqual('camel'); - expect($arr[2])->toEqual('duck'); - expect($arr[3])->toEqual('elephant'); - expect($arr->get(4))->toBeNull(); - expect($arr[4])->toBeNull(); - - $arr = $animals->slice(-2); - expect($arr->arr())->toBeArray(); - expect($arr->length())->toEqual(2); - expect($arr[0])->toEqual('duck'); - expect($arr[1])->toEqual('elephant'); - expect($arr->get(2))->toBeNull(); - expect($arr[2])->toBeNull(); - - $arr = $animals->slice(2, -1); - expect($arr->arr())->toBeArray(); - expect($arr->length())->toEqual(2); - expect($arr[0])->toEqual('camel'); - expect($arr[1])->toEqual('duck'); - expect($arr->get(2))->toBeNull(); - expect($arr[2])->toBeNull(); - - $arr = $animals->slice(-3, -1); - expect($arr->arr())->toBeArray(); - expect($arr->length())->toEqual(2); - expect($arr[0])->toEqual('camel'); - expect($arr[1])->toEqual('duck'); - expect($arr->get(2))->toBeNull(); - expect($arr[2])->toBeNull(); - - $arr = $animals->slice(27, -1); - expect($arr->arr())->toBeArray(); - expect($arr->length())->toEqual(0); - expect($arr[0])->toBeNull(); -}); - -it('searches arrays', function (): void { - $arr = Arr::make([99, 98, 97])->append([1, 2, 3]); - $index = $arr->indexOf(1); - expect($index)->toBeInt(); - expect($index)->toEqual(3); - expect($arr->length())->toEqual(6); - $arr = Arr::make(['L' => 'Leon', 'T' => 'Tiger', 'B' => 'Bird']); - $index = $arr->indexOf('Tiger'); - expect($index)->toBeString(); - expect($index)->toEqual('T'); - expect($arr->length())->toEqual(3); -}); - -it('searches last occurrence arrays', function (): void { - $arr = Arr::make([1, 2, 3, 4, 5, 6, 7, 8, 9, 8, 7, 6, 5, 4, 3, 2, 1]); - $index = $arr->lastIndexOf(5); - expect($index)->toBeInt(); - expect($index)->toEqual(12); - expect($arr->length())->toEqual(17); - $arr = Arr::make(['L1' => 'Leon', 'T1' => 'Tiger', 'B1' => 'Bird', 'T2' => 'Tiger', 'B2' => 'Bird']); - $index = $arr->lastIndexOf('Tiger'); - expect($index)->toBeString(); - expect($index)->toEqual('T2'); - expect($arr->length())->toEqual(5); -}); - -it('matches every element', function (): void { - $arr = Arr::make([1, 2, 3, 4, 5, 6, 7, 8, 9, 8, 7, 6, 5, 4, 3, 2, 1]); - $bool = $arr->every(fn ($element): bool => $element > 0); - expect($bool)->toEqual(true); - $bool = $arr->every(fn ($element): bool => $element > 1); - expect($bool)->toEqual(false); - $bool = $arr->every(fn ($element): bool => $element > 10000); - expect($bool)->toEqual(false); -}); - -it('matches some element', function (): void { - $arr = Arr::make([1, 2, 3, 4, 5, 6, 7, 8, 9, 8, 7, 6, 5, 4, 3, 2, 1]); - $bool = $arr->some(fn ($element): bool => $element > 0); - expect($bool)->toEqual(true); - $bool = $arr->some(fn ($element): bool => $element > 1); - expect($bool)->toEqual(true); - $bool = $arr->some(fn ($element): bool => $element > 10000); - expect($bool)->toEqual(false); - - $arr = Arr::make([1, 2, 3, 4, 5]); - $even = fn ($element): bool => $element % 2 === 0; - $bool = $arr->some($even); - expect($bool)->toEqual(true); -}); - -it('filters some element', function (): void { - $arr = Arr::make([1, 2, 3, 4, 5, 6, 7, 8, 9, 8, 7, 6, 5, 4, 3, 2, 1]); - $arr2 = $arr->filter(fn ($element): bool => $element > 3); - expect($arr->length())->toEqual(17); - expect($arr2->length())->toEqual(11); - expect($arr->every(fn ($element): bool => $element > 0))->toBeTrue(); - expect($arr->every(fn ($element): bool => $element <= 3))->toBeFalse(); - expect($arr2->every(fn ($element): bool => $element > 3))->toBeTrue(); -}); - -it('finds the first element') - ->with([ - 'string|int arrays' => (object)[ - 'intArr' => Arr::make([1,2,3,4,5,6,7,8,9,0,11]), - 'strArr' => Arr::make(['begin','middle','end']) - ], - ]) - ->expect(fn ($dataset) => $dataset->intArr->find(fn ($element): bool => $element > 0)) - ->toBeInt()->toEqual(1) - ->expect(fn ($dataset) => $dataset->intArr->find(fn ($element): bool => $element < 5)) - ->toBeInt()->toEqual(1) - ->expect(fn ($dataset) => $dataset->intArr->find(fn ($element): bool => $element > 5)) - ->toBeInt()->toEqual(6) - ->expect(fn ($dataset) => $dataset->intArr->find(fn ($element, $index): bool => $element > 1 && $index > 1)) - ->toBeInt()->toEqual(3) - ->expect(fn ($dataset) => $dataset->intArr->find(fn ($element): bool => $element > 50)) - ->toBeNull() - ->expect(fn ($dataset) => $dataset->strArr->find(fn ($element): bool => $element == 'end')) - ->toBeString()->toBe('end') - ->expect(fn ($dataset) => $dataset->strArr->find(fn ($element): bool => str_contains((string) $element, 'e'))) - ->toBeString()->toBe('begin') - ->expect(fn ($dataset) => $dataset->strArr->find(fn ($element): bool => $element == 'prefix')) - ->toBeNull(); - -it('finds the first index of some element', function (): void { - $arr = Arr::make([1, 2, 3, 4, 5, 6, 7, 8, 9, 8, 7, 6, 5, 4, 3, 2, 1]); - $index = $arr->findIndex(fn ($element): bool => $element > 0); - expect($index)->toBeInt(); - expect($index)->toEqual(0); - $index = $arr->findIndex(fn ($element): bool => $element > 1); - expect($index)->toEqual(1); - $index = $arr->findIndex(fn ($element): bool => $element > 10000); - expect($index)->toEqual(-1); - $index = $arr->findIndex(fn ($element, $index): bool => $element > 1 && $index > 1); - expect($index)->toEqual(2); -}); - -it('maps elements', function (): void { - $arr = Arr::make([1, 2, 3, 4, 5, 6, 7, 8, 9, 8, 7, 6, 5, 4, 3, 2, 1]); - $arr2 = $arr->map(fn ($element): int|float => $element + 1); - - expect($arr->length())->toEqual(17); - expect($arr2->length())->toEqual(17); - expect($arr->every(fn ($element): bool => $element > 0))->toBeTrue(); - expect($arr->every(fn ($element): bool => $element > 1))->toBeFalse(); - expect($arr2->every(fn ($element): bool => $element > 1))->toBeTrue(); -}); - -it('flats array', function (): void { - $arr = Arr::make([1, [2, 3], 4, [5, 6, 7]]); - - $arr2 = $arr->flat(); - expect($arr->length())->toEqual(4); - expect($arr2->length())->toEqual(7); -}); - -it('flats and maps array', function (): void { - $arr = Arr::make([1, 2, 3, 4, 5, 6, 7]); - - $arr2 = $arr->flatMap(fn ($element): array => [$element, $element * 2]); - expect($arr->length())->toEqual(7); - expect($arr2->length())->toEqual(14); - expect($arr2->arr())->toEqual([1, 2, 2, 4, 3, 6, 4, 8, 5, 10, 6, 12, 7, 14]); - - $arr2 = $arr->flatMap(fn ($element) => $element); - expect($arr->length())->toEqual(7); - expect($arr2->length())->toEqual(7); - expect($arr2->arr())->toEqual([1, 2, 3, 4, 5, 6, 7]); -}); - -it('fills array', function (): void { - $arr = Arr::make([1, 2, 3, 4, 5, 6, 7]); - expect($arr->length())->toEqual(7); - $arr->fill(0, 0, 3); - expect($arr->length())->toEqual(7); - expect($arr[0])->toEqual(0); - expect($arr[1])->toEqual(0); - expect($arr[2])->toEqual(0); - expect($arr[3])->toEqual(0); - expect($arr[4])->toEqual(5); - expect($arr[5])->toEqual(6); - expect($arr[6])->toEqual(7); - $arr2 = $arr->filter(fn ($element): bool => $element == 0); - expect($arr2->length())->toEqual(4); - $arr = Arr::make([1, 2, 3, 4, 5, 6, 7]); - $arr->fill(0); - $allAreZeros = $arr->every(fn ($element): bool => $element === 0); - expect($arr->length())->toEqual(7); - expect($allAreZeros)->toBeTrue(); -}); - -it('reduces Arr', function (): void { - $arr = Arr::make([1, 2, 3, 4, 5, 6, 7]); - $value = $arr->reduce(fn ($previousValue, $currentValue): float|int|array => $previousValue + $currentValue); - expect($value)->toBeInt(); - expect($value)->toEqual(28); -}); - -it('reduces Arr in reverse way', function (): void { - $arr = Arr::make([1, 2, 3, 4, 5, 6, 7]); - $value = $arr->reduceRight(fn ($previousValue, $currentValue): float|int|array => $previousValue + $currentValue); - expect($value)->toBeInt(); - expect($value)->toEqual(28); -}); - -it('reverses Arr', function (): void { - $arr = Arr::make([1, 2, 3, 4, 5, 6, 7]); - $arr2 = $arr->reverse(); - expect($arr2->length())->toEqual(7); - expect($arr2->join())->toEqual('7,6,5,4,3,2,1'); - expect($arr->join())->toEqual('7,6,5,4,3,2,1'); - $arr->push(0); - expect($arr2->join())->toEqual('7,6,5,4,3,2,1'); - expect($arr->join())->toEqual('7,6,5,4,3,2,1,0'); -}); - -it('sorts Arr', function (): void { - $arr = Arr::make([6, 2, 4, 2, 1, 9, 7]); - expect($arr->join())->toEqual('6,2,4,2,1,9,7'); - $arr->sort(); - expect($arr->length())->toEqual(7); - expect($arr->join())->toEqual('1,2,2,4,6,7,9'); -}); -it('sorts and change Arr', function (): void { - $months = Arr::make(['March', 'Jan', 'Feb', 'Dec']); - $monthsSorted = $months->sort(); - expect($months->length())->toEqual(4); - expect($monthsSorted->length())->toEqual(4); - expect($months[3])->toEqual('March'); - expect($monthsSorted[3])->toEqual('March'); - $month = $months->pop(); - expect($month)->toEqual('March'); - expect($months[3])->toBeNull(); - expect($monthsSorted[3])->toBeNull(); -}); - -it('splices Arr', function (): void { - $months = Arr::make(['Jan', 'March', 'April', 'June']); - $months->splice(1, 0, 'Feb'); - expect($months->join())->toEqual('Jan,Feb,March,April,June'); - $months->splice(4, 1, 'May'); - expect($months->join())->toEqual('Jan,Feb,March,April,May'); - $months->splice(1); - expect($months->join())->toEqual('Jan'); -}); - -it('stringifies an Arr', function (): void { - $months = Arr::make(['Jan', 'Feb', 'March', 'April', 'May']); - expect($months->toString())->toEqual('Jan,Feb,March,April,May'); - - $arr = Arr::make([1, 2, 'a', '1a']); - expect($arr->toString())->toEqual('1,2,a,1a'); -}); - -it('checks is array', function (): void { - $isArray = Arr::isArray(['Jan', 'Feb', 'March', 'April', 'May']); - expect($isArray)->toEqual(true); - $isArray = Arr::isArray(null); - expect($isArray)->toEqual(false); - $isArray = Arr::isArray(1); - expect($isArray)->toEqual(false); - $isArray = Arr::isArray(0); - expect($isArray)->toEqual(false); -}); - -it('tests if array is empty', function (): void { - $emptyArr = Arr::make([]); - expect($emptyArr->isEmpty())->toEqual(true); - $notEmptyArr = Arr::make([1]); - expect($notEmptyArr->isEmpty())->toEqual(false); -}); - -it('chainable empty array', function (): void { - $arr = Arr::make([1, 2, 3, 4, 5, 6, 7, 8, 9, 8, 7, 6, 5, 4, 3, 2, 1]); - expect($arr->filter(fn ($element): bool => $element > 100)->isEmpty())->toBeTrue(); - expect($arr->filter(fn ($element): bool => $element < 100)->isEmpty())->toBeFalse(); -}); - -it('implements of() method', function (): void { - $arr = Arr::of('Jan', 'Feb', 'March', 'April', 'May'); - expect($arr->length())->toEqual(5); - expect($arr[4])->toEqual('May'); - - $arr = Arr::of(7); - expect($arr->length())->toEqual(1); - expect($arr[0])->toEqual(7); -}); - -it('tests keys() method', function (): void { - $arr = Arr::make( - [ - '01' => 'Jan', '02' => 'Feb', '03' => 'March', '04' => 'April', - '05' => 'May', '06' => 'Jun', '07' => 'Jul', '08' => 'Aug', - '09' => 'Sep', '10' => 'Oct', '11' => 'Nov', '12' => 'Dec', - ] - ); - expect($arr->length())->toEqual(12); - $arrKeys = $arr->keys(true); - expect($arrKeys)->toBeObject(); - expect($arrKeys->length())->toEqual(12); - expect($arrKeys[4])->toEqual('05'); - - $keys = $arr->keys(); - expect($keys)->toBeArray(); - expect(is_countable($keys) ? count($keys) : 0)->toEqual(12); - expect($keys[4])->toEqual('05'); - - foreach ($arrKeys as $key => $value) { - expect($arrKeys[$key])->toEqual($keys[$key]); - } -}); - -it('test keys() method', function (): void { - $arr = Arr::make( - [5, 12, 8, 130, 44] - ); - expect($arr->length())->toEqual(5); - expect($arr->at(2))->toEqual(8); - expect($arr->at(-2))->toEqual(130); - expect($arr->at(100))->toBeNull(); -}); - -it('includes element', function (): void { - $arr = Arr::make( - [1, 2, 3] - ); - expect($arr->length())->toEqual(3); - expect($arr->includes(2))->toBeTrue(); - expect($arr->includes('2'))->toBeFalse(); - - $arr = Arr::make( - ['cat', 'dog', 'bat'] - ); - expect($arr->length())->toEqual(3); - expect($arr->includes('cat'))->toBeTrue(); - expect($arr->includes('Cat'))->toBeFalse(); - expect($arr->includes('at'))->toBeFalse(); -}); - -it('includes element from index', function (): void { - $arr = Arr::make( - [1, 2, 3] - ); - expect($arr->length())->toEqual(3); - expect($arr->includes(2))->toBeTrue(); - expect($arr->includes(4))->toBeFalse(); - expect($arr->includes(3, 3))->toBeFalse(); - expect($arr->includes(3, 2))->toBeTrue(); - expect($arr->includes(3, -1))->toBeTrue(); - - $arr = Arr::make( - ['a', 'b', 'c'] - ); - expect($arr->includes('c', 3))->toBeFalse(); - expect($arr->includes('c', 100))->toBeFalse(); - - expect($arr->includes('a', -100))->toBeTrue(); - expect($arr->includes('b', -100))->toBeTrue(); - expect($arr->includes('c', -100))->toBeTrue(); - expect($arr->includes('a', -2))->toBeFalse(); -}); - -it(' extract values', function (): void { - $fruits = Arr::make([ - 7 => '🥝', - -1 => '🍓', - 1 => '🍋', - 'mango' => '🥭', - 'apple' => '🍎', - 'banana' => '🍌', - '🍊', - '🍍', ]); - - expect($fruits->arr())->toBeArray(); - expect($fruits->length())->toEqual(8); - expect($fruits['mango'])->toEqual('🥭'); - expect($fruits[9])->toEqual('🍍'); - - $onlyFruits = $fruits->values(); - expect($onlyFruits->arr())->toBeArray(); - expect($onlyFruits->length())->toEqual(8); - expect($onlyFruits[3])->toEqual('🥭'); - expect($onlyFruits[7])->toEqual('🍍'); - $i = 0; - foreach ($fruits->values() as $value) { - $i++; - } - expect($i)->toEqual(8); -}); - -it('creates entries', function (): void { - $fruits = Arr::make([ - 7 => '🥝', - -1 => '🍓', - 1 => '🍋', - 'mango' => '🥭', - 'apple' => '🍎', - 'banana' => '🍌', - '🍊', - '🍍', - ]); - - $entries = $fruits->entries(); - expect($entries->arr())->toBeArray(); - expect($entries->length())->toEqual(8); - expect($entries)->toEqual(Arr::make([ - [7, '🥝'], - [-1, '🍓'], - [1, '🍋'], - ['mango', '🥭'], - ['apple', '🍎'], - ['banana', '🍌'], - [8, '🍊'], - [9, '🍍'], - ])); -}); - -it('tests copyWithin() method with one parameter', function (): void { - $arr = Arr::make([1, 2, 3, 4, 5]); - - $result = $arr->copyWithin(-2); - expect($result) - ->toBeArray() - ->toHaveCount(5) - ->toEqual([1, 2, 3, 1, 2]); -}); - -it('tests copyWithin() method with two parameters', function (): void { - $arr = Arr::make([1, 2, 3, 4, 5]); - - $result = $arr->copyWithin(0, 3); - expect($result) - ->toBeArray() - ->toHaveCount(5) - ->toEqual([4, 5, 3, 4, 5]); -}); - -it('tests copyWithin() method with all the parameters', function (): void { - $arr = Arr::make([1, 2, 3, 4, 5]); - - $result = $arr->copyWithin(0, 3, 4); - expect($result) - ->toBeArray() - ->toHaveCount(5) - ->toEqual([4, 2, 3, 4, 5]); -}); - -it('tests copyWithin() method with all the parameters negative', function (): void { - $arr = Arr::make([1, 2, 3, 4, 5]); - - $result = $arr->copyWithin(-2, -3, -1); - expect($result) - ->toBeArray() - ->toHaveCount(5) - ->toEqual([1, 2, 3, 3, 4]); -}); - -it('tests flatMap can handle an array of arrays', function (): void { - $arr = Arr::make([ - [1, 2], - [3, 4] - ]); - - $result = $arr->flatMap(fn ($element): int|float => $element * 2); - expect($result->length())->toEqual(4); - expect($result->arr())->toEqual([2, 4, 6, 8]); -}); - -it('can unset array elements by their keys', function (): void { - $arr = Arr::make([ - 'mango' => '🥭', - 'apple' => '🍎', - 'banana' => '🍌' - ]); - - $arr->unset('apple'); - expect($arr) - ->toHaveCount(2) - ->and($arr->arr()) - ->toMatchArray([ + $this->assertIsArray($fruits->arr()); + $this->assertEquals(8, $fruits->length()); + $this->assertEquals('🥭', $fruits['mango']); + $this->assertEquals('🍍', $fruits[9]); + + $onlyFruits = $fruits->values(); + $this->assertIsArray($onlyFruits->arr()); + $this->assertEquals(8, $onlyFruits->length()); + $this->assertEquals('🥭', $onlyFruits[3]); + $this->assertEquals('🍍', $onlyFruits[7]); + $i = 0; + foreach ($fruits->values() as $value) { + $i++; + } + $this->assertEquals(8, $i); + } + + public function test_creates_entries(): void + { + $fruits = Arr::make([ + 7 => '🥝', + -1 => '🍓', + 1 => '🍋', 'mango' => '🥭', + 'apple' => '🍎', + 'banana' => '🍌', + '🍊', + '🍍', + ]); + + $entries = $fruits->entries(); + $this->assertIsArray($entries->arr()); + $this->assertEquals(8, $entries->length()); + $this->assertEquals(Arr::make([ + [7, '🥝'], + [-1, '🍓'], + [1, '🍋'], + ['mango', '🥭'], + ['apple', '🍎'], + ['banana', '🍌'], + [8, '🍊'], + [9, '🍍'], + ]), $entries); + } + + public function test_copy_within_method_with_one_parameter(): void + { + $arr = Arr::make([1, 2, 3, 4, 5]); + + $result = $arr->copyWithin(-2); + $this->assertIsArray($result); + $this->assertCount(5, $result); + $this->assertEquals([1, 2, 3, 1, 2], $result); + } + + public function test_copy_within_method_with_two_parameters(): void + { + $arr = Arr::make([1, 2, 3, 4, 5]); + + $result = $arr->copyWithin(0, 3); + $this->assertIsArray($result); + $this->assertCount(5, $result); + $this->assertEquals([4, 5, 3, 4, 5], $result); + } + + public function test_copy_within_method_with_all_the_parameters(): void + { + $arr = Arr::make([1, 2, 3, 4, 5]); + + $result = $arr->copyWithin(0, 3, 4); + $this->assertIsArray($result); + $this->assertCount(5, $result); + $this->assertEquals([4, 2, 3, 4, 5], $result); + } + + public function test_copy_within_method_with_all_the_parameters_negative(): void + { + $arr = Arr::make([1, 2, 3, 4, 5]); + + $result = $arr->copyWithin(-2, -3, -1); + $this->assertIsArray($result); + $this->assertCount(5, $result); + $this->assertEquals([1, 2, 3, 3, 4], $result); + } + + public function test_flat_map_can_handle_an_array_of_arrays(): void + { + $arr = Arr::make([ + [1, 2], + [3, 4] + ]); + + $result = $arr->flatMap(fn ($element): int|float => $element * 2); + $this->assertEquals(4, $result->length()); + $this->assertEquals([2, 4, 6, 8], $result->arr()); + } + + public function test_can_unset_array_elements_by_their_keys(): void + { + $arr = Arr::make([ + 'mango' => '🥭', + 'apple' => '🍎', 'banana' => '🍌' - ]) - ->and($arr->unset('orange')) - ->toBeFalse() - ->and($arr) - ->toHaveCount(2) - ->and($arr->arr()) - ->toMatchArray([ + ]); + + $arr->unset('apple'); + $this->assertCount(2, $arr); + $this->assertEquals([ + 'mango' => '🥭', + 'banana' => '🍌' + ], $arr->arr()); + $this->assertFalse($arr->unset('orange')); + $this->assertCount(2, $arr); + $this->assertEquals([ + 'mango' => '🥭', + 'banana' => '🍌' + ], $arr->arr()); + } + + public function test_can_set_array_key(): void + { + $arr = Arr::make([ 'mango' => '🥭', 'banana' => '🍌' ]); -}); - -it('can set array key', function (): void { - $arr = Arr::make([ - 'mango' => '🥭', - 'banana' => '🍌' - ]); - - $arr->set('apple', '🍎'); - expect($arr) - ->toHaveCount(3) - ->and($arr->arr()) - ->toMatchArray([ + + $arr->set('apple', '🍎'); + $this->assertCount(3, $arr); + $this->assertEquals([ 'mango' => '🥭', 'banana' => '🍌', 'apple' => '🍎' - ]); -}); + ], $arr->arr()); + } +} diff --git a/tests/ArrayAccessTest.php b/tests/ArrayAccessTest.php index f27c1b6..0ebff25 100644 --- a/tests/ArrayAccessTest.php +++ b/tests/ArrayAccessTest.php @@ -1,56 +1,67 @@ assertEquals(100, $arr[0]); + $this->assertEquals(101, $arr[1]); + $this->assertEquals(102, $arr[2]); + } -it('access to element', function (): void { - $arr = Arr::make([100, 101, 102]); - expect($arr[0])->toEqual(100); - expect($arr[1])->toEqual(101); - expect($arr[2])->toEqual(102); -}); + public function test_create_elements(): void + { + $arr = Arr::make(); + $arr['test01'] = 'Some'; + $arr['test02'] = 'Thing'; + $this->assertEquals(2, $arr->count()); + $this->assertEquals('Thing', $arr['test02']); + $this->assertEquals('Some', $arr['test01']); -it('create elements', function (): void { - $arr = Arr::make(); - $arr['test01'] = 'Some'; - $arr['test02'] = 'Thing'; - expect($arr->count())->toEqual(2); - expect($arr['test02'])->toEqual('Thing'); - expect($arr['test01'])->toEqual('Some'); + $arr = Arr::make(); + $arr[] = 'first value'; + $arr[] = 'second value'; + $this->assertEquals(2, $arr->count()); + $this->assertEquals('first value', $arr[0]); + $this->assertEquals('second value', $arr[1]); + $this->assertNull($arr[2]); + $this->assertEquals($arr->get(1), $arr[1]); + } - $arr = Arr::make(); - $arr[] = 'first value'; - $arr[] = 'second value'; - expect($arr->count())->toEqual(2); - expect($arr[0])->toEqual('first value'); - expect($arr[1])->toEqual('second value'); - expect($arr[2])->toBeNull(); - expect($arr[1])->toEqual($arr->get(1)); -}); -it('isset and empty', function (): void { - $arr = Arr::make(); - $arr['test01'] = 'Some'; - $arr['test02'] = 'Thing'; - expect($arr->count())->toEqual(2); - expect(isset($arr['test01']))->toBeTrue(); - expect(empty($arr['test01']))->toBeFalse(); - expect(isset($arr['not exists']))->toBeFalse(); - expect(empty($arr['not exists']))->toBeTrue(); -}); + public function test_isset_and_empty(): void + { + $arr = Arr::make(); + $arr['test01'] = 'Some'; + $arr['test02'] = 'Thing'; + $this->assertEquals(2, $arr->count()); + $this->assertTrue(isset($arr['test01'])); + $this->assertFalse(empty($arr['test01'])); + $this->assertFalse(isset($arr['not exists'])); + $this->assertTrue(empty($arr['not exists'])); + } -it('unset', function (): void { - $arr = Arr::make(); - $arr['test01'] = 'Some'; - $arr['test02'] = 'Thing'; - $arr['test03'] = '!!!'; - expect($arr->count())->toEqual(3); - expect(isset($arr['test01']))->toBeTrue(); - expect(empty($arr['test01']))->toBeFalse(); - expect(isset($arr['test02']))->toBeTrue(); - expect(empty($arr['test02']))->toBeFalse(); - unset($arr['test02']); - expect($arr->count())->toEqual(2); - expect(isset($arr['test01']))->toBeTrue(); - expect(empty($arr['test01']))->toBeFalse(); - expect(isset($arr['test02']))->toBeFalse(); - expect(empty($arr['test02']))->toBeTrue(); -}); + public function test_unset(): void + { + $arr = Arr::make(); + $arr['test01'] = 'Some'; + $arr['test02'] = 'Thing'; + $arr['test03'] = '!!!'; + $this->assertEquals(3, $arr->count()); + $this->assertTrue(isset($arr['test01'])); + $this->assertFalse(empty($arr['test01'])); + $this->assertTrue(isset($arr['test02'])); + $this->assertFalse(empty($arr['test02'])); + unset($arr['test02']); + $this->assertEquals(2, $arr->count()); + $this->assertTrue(isset($arr['test01'])); + $this->assertFalse(empty($arr['test01'])); + $this->assertFalse(isset($arr['test02'])); + $this->assertTrue(empty($arr['test02'])); + } +} diff --git a/tests/CalcTest.php b/tests/CalcTest.php index 416b2fb..301d079 100644 --- a/tests/CalcTest.php +++ b/tests/CalcTest.php @@ -1,30 +1,38 @@ sum())->toEqual(6); - - $arr = Arr::make(['3', 2, 3]); - expect($arr->sum())->toEqual(8); - $arr = Arr::fromValue(1, 100); - expect($arr->sum())->toEqual(100); -}); - -it('avg Array', function (): void { - $arr = Arr::make([1, 2, 3]); - expect($arr->avg())->toEqual(2); +namespace HiFolks\Array\Tests; - $arr = Arr::fromValue(1, 100); - expect($arr->avg())->toEqual(1); - - $arr = Arr::fromValue(1.2, 100); - expect(round($arr->avg(), 2))->toEqual(1.2); - - $arr = Arr::make([1.1, 1.5]); - expect($arr->avg())->toEqual(1.3); - - $arr = Arr::make([]); - expect($arr->avg())->toEqual(0); -}); +use HiFolks\DataType\Arr; +use PHPUnit\Framework\TestCase; + +class CalcTest extends TestCase +{ + public function test_sum_array(): void + { + $arr = Arr::make([1, 2, 3]); + $this->assertEquals(6, $arr->sum()); + + $arr = Arr::make(['3', 2, 3]); + $this->assertEquals(8, $arr->sum()); + $arr = Arr::fromValue(1, 100); + $this->assertEquals(100, $arr->sum()); + } + + public function test_avg_array(): void + { + $arr = Arr::make([1, 2, 3]); + $this->assertEquals(2, $arr->avg()); + + $arr = Arr::fromValue(1, 100); + $this->assertEquals(1, $arr->avg()); + + $arr = Arr::fromValue(1.2, 100); + $this->assertEquals(1.2, round($arr->avg(), 2)); + + $arr = Arr::make([1.1, 1.5]); + $this->assertEquals(1.3, $arr->avg()); + + $arr = Arr::make([]); + $this->assertEquals(0, $arr->avg()); + } +} diff --git a/tests/IterateTest.php b/tests/IterateTest.php index 55cf754..5b85368 100644 --- a/tests/IterateTest.php +++ b/tests/IterateTest.php @@ -1,22 +1,30 @@ toBeGreaterThanOrEqual(100); - expect($element)->toBeLessThanOrEqual(102); +class IterateTest extends TestCase +{ + public function test_iterates(): void + { + $arr = Arr::make([100, 101, 102]); + foreach ($arr as $element) { + $this->assertGreaterThanOrEqual(100, $element); + $this->assertLessThanOrEqual(102, $element); + } } -}); -it('iterates prev and next', function (): void { - $arr = Arr::make([100, 101, 102]); - $arr->next(); - $arr->next(); - $element = $arr->current(); - expect($element)->toEqual(102); - $arr->prev(); - $element = $arr->current(); - expect($element)->toEqual(101); -}); + public function test_iterates_prev_and_next(): void + { + $arr = Arr::make([100, 101, 102]); + $arr->next(); + $arr->next(); + $element = $arr->current(); + $this->assertEquals(102, $element); + $arr->prev(); + $element = $arr->current(); + $this->assertEquals(101, $element); + } +} diff --git a/tests/Pest.php b/tests/Pest.php deleted file mode 100644 index b3d9bbc..0000000 --- a/tests/Pest.php +++ /dev/null @@ -1 +0,0 @@ -dataTable = [ + ['product' => 'Desk', 'price' => 200, 'active' => true], + ['product' => 'Chair', 'price' => 100, 'active' => true], + ['product' => 'Door', 'price' => 300, 'active' => false], + ['product' => 'Bookcase', 'price' => 150, 'active' => true], + ['product' => 'Door', 'price' => 100, 'active' => true], + ]; + } -$dataTable = [ - ['product' => 'Desk', 'price' => 200, 'active' => true], - ['product' => 'Chair', 'price' => 100, 'active' => true], - ['product' => 'Door', 'price' => 300, 'active' => false], - ['product' => 'Bookcase', 'price' => 150, 'active' => true], - ['product' => 'Door', 'price' => 100, 'active' => true], -]; + public function test_multiply_by_2_a_field(): void + { + $table = Table::make($this->dataTable); + $resultTable = $table->calc("price2", Operation::double("price")); + $this->assertEquals(200, $table->getFromFirst("price")); + $this->assertEquals(400, $resultTable->getFromFirst("price2")); + $this->assertEquals(400, $resultTable->getFromFirst("price2")); + // warning the calc method changes the original data + $this->assertEquals(400, $table->first()->get("price2")); + $this->assertEquals(400, $resultTable->first()->get("price2")); + } -it('multiply by 2 a field', function () use ($dataTable): void { - $table = Table::make($dataTable); - $resultTable = $table->calc("price2", Operation::double("price")); - expect($table->getFromFirst("price"))->toEqual(200); - expect($resultTable->getFromFirst("price2"))->toEqual(400); - expect($resultTable->getFromFirst("price2"))->toEqual(400); - // warning the calc method changes the original data - expect($table->first()->get("price2"))->toEqual(400); - expect($resultTable->first()->get("price2"))->toEqual(400); -}); -it('add value to a field', function () use ($dataTable): void { - $table = Table::make($dataTable); - $resultTable = $table->calc("price2", Operation::add("price", 50)); - expect($table->getFromFirst("price"))->toEqual(200); - expect($resultTable->getFromFirst("price2"))->toEqual(250); - expect($resultTable->getFromFirst("price"))->toEqual(200); - // warning the calc method changes the original data - expect($table->first()->get("price2"))->toEqual(250); - expect($resultTable->first()->get("price2"))->toEqual(250); -}); + public function test_add_value_to_a_field(): void + { + $table = Table::make($this->dataTable); + $resultTable = $table->calc("price2", Operation::add("price", 50)); + $this->assertEquals(200, $table->getFromFirst("price")); + $this->assertEquals(250, $resultTable->getFromFirst("price2")); + $this->assertEquals(200, $resultTable->getFromFirst("price")); + // warning the calc method changes the original data + $this->assertEquals(250, $table->first()->get("price2")); + $this->assertEquals(250, $resultTable->first()->get("price2")); + } +} diff --git a/tests/TableTest.php b/tests/TableTest.php index 7f94c0e..e3f6a62 100644 --- a/tests/TableTest.php +++ b/tests/TableTest.php @@ -1,348 +1,292 @@ dataTable = [ + ['product' => 'Desk', 'price' => 200, 'active' => true], + ['product' => 'Chair', 'price' => 100, 'active' => true], + ['product' => 'Door', 'price' => 300, 'active' => false], + ['product' => 'Bookcase', 'price' => 150, 'active' => true], + ['product' => 'Door', 'price' => 100, 'active' => true], + ]; + } + + public function test_is_table(): void + { + $table = Table::make($this->dataTable); + $this->assertIsArray($table->rows()); + $this->assertInstanceOf(Arr::class, $table->first()); + } + + public function test_is_table_countable(): void + { + $table = Table::make($this->dataTable); + $this->assertCount(5, $table); + } + + public function test_is_iterable(): void + { + $table = Table::make($this->dataTable); + $this->assertInstanceOf(Iterator::class, $table); + foreach ($table as $row) { + $this->assertInstanceOf(Arr::class, $row); + } + + $table->rewind(); + $table->next(); + $table->next(); + $this->assertInstanceOf(Arr::class, $table->current()); + $this->assertEquals(['product' => 'Door', 'price' => 300, 'active' => false], $table->current()->arr()); + $table->prev(); + $this->assertInstanceOf(Arr::class, $table->current()); + $this->assertEquals(['product' => 'Chair', 'price' => 100, 'active' => true], $table->current()->arr()); + } + + public function test_can_get_first(): void + { + $table = Table::make($this->dataTable); + $this->assertIsArray($table->rows()); + $this->assertInstanceOf(Arr::class, $table->first()); + $this->assertCount(3, $table->first()); + $this->assertIsArray($table->first()?->keys()); + $this->assertCount(3, $table->first()?->keys()); + $this->assertEquals(['product', 'price', 'active'], $table->first()?->keys()); + } + + public function test_can_get_column_from_first(): void + { + $table = Table::make($this->dataTable); + $this->assertIsArray($table->rows()); + $this->assertIsInt($table->getFromFirst('price')); + $this->assertEquals(200, $table->getFromFirst('price')); + $this->assertNull($table->getFromFirst('unknown_column')); + } + + public function test_can_get_last(): void + { + $table = Table::make($this->dataTable); + $this->assertIsArray($table->rows()); + $this->assertCount(3, $table->last()); + $this->assertIsArray($table->last()?->arr()); + $this->assertEquals(['product' => 'Door', 'price' => 100, 'active' => true], $table->last()?->arr()); + $this->assertIsArray($table->last()?->keys()); + $this->assertCount(3, $table->last()?->keys()); + $this->assertEquals(['product', 'price', 'active'], $table->last()?->keys()); + } + + public function test_can_get_column_from_last(): void + { + $table = Table::make($this->dataTable); + $this->assertIsArray($table->rows()); + $this->assertIsInt($table->getFromLast('price')); + $this->assertEquals(100, $table->getFromLast('price')); + $this->assertNull($table->getFromLast('unknown_column')); + } + + public function test_can_select(): void + { + $table = Table::make($this->dataTable); + $this->assertIsArray($table->rows()); + $this->assertInstanceOf(Arr::class, $table->select('product', 'active')->last()); + $this->assertCount(2, $table->select('product', 'active')->last()); + $this->assertEquals(['product', 'active'], $table->select('product', 'active')->last()?->keys()); + $this->assertTrue($table->first()?->get('active')); + $firstArr = $table->first()?->arr(); + $this->assertEquals('Desk', $firstArr['product']); + $this->assertTrue($firstArr['active']); + } + + public function test_can_except(): void + { + $table = Table::make($this->dataTable); + $this->assertIsArray($table->rows()); + $this->assertInstanceOf(Arr::class, $table->except('price')->last()); + $this->assertCount(2, $table->except('price')->last()); + $this->assertEquals(['product', 'active'], $table->except('price')->last()?->keys()); + $this->assertTrue($table->first()?->get('active')); + $firstArr = $table->first()?->arr(); + $this->assertEquals('Desk', $firstArr['product']); + $this->assertTrue($firstArr['active']); + $this->assertCount(5, $table->rows()); + + $table = Table::make($this->dataTable); + $this->assertIsArray($table->rows()); + $this->assertInstanceOf(Arr::class, $table->except('field_not_exist')->last()); + $this->assertCount(3, $table->except('field_not_exist')->last()); + $this->assertEquals(['product', 'price', 'active'], $table->except('field_not_exists')->last()?->keys()); + $this->assertCount(5, $table->rows()); + } + + public function test_can_filter(): void + { + $table = Table::make($this->dataTable); + $this->assertIsArray($table->rows()); + $this->assertInstanceOf(Arr::class, $table->select('product', 'price')->last()); + $this->assertCount(2, $table->select('product', 'price')->last()); + $this->assertCount(2, $table->select('product', 'price')->where('price', 100)->last()); + $this->assertCount(2, $table->select('product', 'price')->where('price', 100)); + $this->assertEquals( + ['product', 'price'], + $table->select('product', 'price')->where('price', 100)->last()?->keys() + ); + $this->assertEquals( + ['product', 'price'], + $table->select('product', 'price')->where('price', "IDONTKNOW", 100)->last()?->keys() + ); + $this->assertEquals( + 200, + $table->select('product', 'price')->where('price', "IDONTKNOW", 200)->getFromLast("price") + ); + $this->assertEquals( + 100, + $table->select('product', 'price')->where('price', "IDONTKNOW", 100)->getFromLast("price") + ); + } + + public function test_can_filter_greater_than(): void + { + $table = Table::make($this->dataTable); + $this->assertCount(3, $table->select('product', 'price')->where('price', '>', 100)); + + $table = Table::make($this->dataTable); + $this->assertCount(5, $table->select('product', 'price')->where('price', '>=', 100)); + } + + public function test_can_filter_true(): void + { + $table = Table::make($this->dataTable); + $this->assertCount(4, $table->where('active')->select('product', 'price')); + } + + public function test_can_filter_smaller(): void + { + $table = Table::make($this->dataTable); + $this->assertCount(2, $table->select('product', 'price')->where('price', '<=', 100)); -$dataTable = [ - ['product' => 'Desk', 'price' => 200, 'active' => true], - ['product' => 'Chair', 'price' => 100, 'active' => true], - ['product' => 'Door', 'price' => 300, 'active' => false], - ['product' => 'Bookcase', 'price' => 150, 'active' => true], - ['product' => 'Door', 'price' => 100, 'active' => true], -]; - -it('is Table', function () use ($dataTable): void { - $table = Table::make($dataTable); - expect($table->rows()) - ->toBeArray() - ->and($table->first()) - ->toBeInstanceOf(Arr::class); -}); - -it('is Table countable', function () use ($dataTable): void { - $table = Table::make($dataTable); - expect($table)->toHaveCount(5); -}); - -it('is iterable', function () use ($dataTable): void { - $table = Table::make($dataTable); - expect($table)->toBeInstanceOf(Iterator::class); - foreach ($table as $row) { - expect($row)->toBeInstanceOf(Arr::class); + $table = Table::make($this->dataTable); + $this->assertCount(0, $table->select('product', 'price')->where('price', '<', 100)); } - $table->rewind(); - $table->next(); - $table->next(); - expect($table->current()) - ->toBeInstanceOf(Arr::class) - ->and($table->current()->arr()) - ->toMatchArray(['product' => 'Door', 'price' => 300, 'active' => false]); - $table->prev(); - expect($table->current()) - ->toBeInstanceOf(Arr::class) - ->and($table->current()->arr()) - ->toMatchArray(['product' => 'Chair', 'price' => 100, 'active' => true]); -}); - -it('can get first', function () use ($dataTable): void { - $table = Table::make($dataTable); - expect($table->rows())->toBeArray() - ->and($table->first()) - ->toBeInstanceOf(Arr::class) - ->and($table->first()) - ->toHaveCount(3) - ->and($table->first()?->keys()) - ->toBeArray() - ->toHaveCount(3) - ->toMatchArray(['product', 'price', 'active']); -}); - -it('can get column from first', function () use ($dataTable): void { - $table = Table::make($dataTable); - expect($table->rows()) - ->toBeArray() - ->and($table->getFromFirst('price')) - ->toBeInt() - ->toEqual(200) - ->and($table->getFromFirst('unknown_column')) - ->toBeNull(); -}); - -it('can get last', function () use ($dataTable): void { - $table = Table::make($dataTable); - expect($table->rows())->toBeArray() - ->and($table->last())->toHaveCount(3) - ->and($table->last()?->arr()) - ->toBeArray() - ->toMatchArray(['product' => 'Door', 'price' => 100, 'active' => true]) - ->and($table->last()?->keys()) - ->toBeArray() - ->toHaveCount(3) - ->toMatchArray(['product', 'price', 'active']); -}); - -it('can get column from last', function () use ($dataTable): void { - $table = Table::make($dataTable); - expect($table->rows()) - ->toBeArray() - ->and($table->getFromLast('price')) - ->toBeInt() - ->toEqual(100) - ->and($table->getFromLast('unknown_column')) - ->toBeNull(); -}); - -it('can select', function () use ($dataTable): void { - $table = Table::make($dataTable); - expect($table->rows())->toBeArray() - ->and( - $table->select('product', 'active') - ->last() - ) - ->toBeInstanceOf(Arr::class) - ->and($table->select('product', 'active')->last()) - ->toHaveCount(2) - ->and($table->select('product', 'active')->last()?->keys()) - ->toMatchArray(['product', 'active']) - ->and($table->first()?->get('active')) - ->toBeTrue() - ->and($table->first()?->arr()) - ->toMatchArray(['product' => 'Desk', 'active' => true]); -}); - -it('can except', function () use ($dataTable): void { - $table = Table::make($dataTable); - expect($table->rows())->toBeArray() - ->and($table->except('price')->last()) - ->toBeInstanceOf(Arr::class) - ->and($table->except('price')->last()) - ->toHaveCount(2) - ->and($table->except('price')->last()?->keys()) - ->toMatchArray(['product', 'active']) - ->and($table->first()?->get('active')) - ->toBeTrue() - ->and($table->first()?->arr()) - ->toMatchArray(['product' => 'Desk', 'active' => true]) - ->and($table->rows())->toHaveCount(5); - - $table = Table::make($dataTable); - expect($table->rows())->toBeArray() - ->and($table->except('field_not_exist')->last()) - ->toBeInstanceOf(Arr::class) - ->and($table->except('field_not_exist')->last()) - ->toHaveCount(3) - ->and($table->except('field_not_exists')->last()?->keys()) - ->toMatchArray(['product', 'price', 'active']) - ->and($table->rows())->toHaveCount(5); -}); - -it('can filter', function () use ($dataTable): void { - $table = Table::make($dataTable); - expect($table->rows())->toBeArray() - ->and($table->select('product', 'price')->last()) - ->toBeInstanceOf(Arr::class) - ->and($table->select('product', 'price')->last()) - ->toHaveCount(2) - ->and( - $table->select('product', 'price') - ->where('price', 100) - ->last() - )->toHaveCount(2) - ->and( - $table->select('product', 'price') - ->where('price', 100) - )->toHaveCount(2) - ->and( - $table->select('product', 'price') - ->where('price', 100) - ->last() - ?->keys() - )->toMatchArray(['product', 'price']) - ->and( - $table->select('product', 'price') - ->where('price', "IDONTKNOW", 100) - ->last() - ?->keys() - )->toMatchArray(['product', 'price']) - ->and( - $table->select('product', 'price') - ->where('price', "IDONTKNOW", 200) - ->getFromLast("price") - )->toEqual(200) - ->and( - $table->select('product', 'price') - ->where('price', "IDONTKNOW", 100) - ->getFromLast("price") - )->toEqual(100); -}); - -it('can filter greater than', function () use ($dataTable): void { - $table = Table::make($dataTable); - expect( - $table->select('product', 'price') - ->where('price', '>', 100) - )->toHaveCount(3); - - $table = Table::make($dataTable); - expect( - $table->select('product', 'price') - ->where('price', '>=', 100) - )->toHaveCount(5); -}); - -it('can filter true', function () use ($dataTable): void { - $table = Table::make($dataTable); - expect( - $table->where('active') - ->select('product', 'price') - )->toHaveCount(4); -}); - -it('can filter smaller', function () use ($dataTable): void { - $table = Table::make($dataTable); - - expect( - $table->select('product', 'price') - ->where('price', '<=', 100) - )->toHaveCount(2); - - $table = Table::make($dataTable); - expect( - $table->select('product', 'price') - ->where('price', '<', 100) - )->toHaveCount(0); -}); - -it('can filter not equal', function () use ($dataTable): void { - $table = Table::make($dataTable); - - expect( - $table->select('product', 'price') - ->where('price', '!=', '100') - )->toHaveCount(3); - - $table = Table::make($dataTable); - - expect( - $table->select('product', 'price') - ->where('price', '!==', 100) - )->toHaveCount(3); - - $table = Table::make($dataTable); - expect( - $table->select('product', 'price') - ->where('price', '!==', '100') - )->toHaveCount(5); -}); - -it('can create calculated field', function () use ($dataTable): void { - $table = Table::make($dataTable); - - $calculatedTable = $table - ->select('product', 'price') - ->where('price', '>', 100) - ->calc('new_field', fn ($item): int|float => $item['price'] * 2); - - expect($calculatedTable)->toHaveCount(3) - ->and($calculatedTable->first()?->get('price'))->toEqual(200) - ->and($calculatedTable->first()?->get('new_field'))->toEqual(400) - ->and($calculatedTable->last()?->get('price'))->toEqual(150) - ->and($calculatedTable->last()?->get('new_field'))->toEqual(300); -}); - -it('can group', function () use ($dataTable): void { - $table = Table::make($dataTable); - $groupedTable = $table->groupBy('product'); - - expect($groupedTable) - ->toHaveCount(4) - ->and($groupedTable->first()?->arr()) - ->toMatchArray(['product' => 'Desk', 'price' => 200, 'active' => true]) - ->and($groupedTable->last()?->arr()) - ->toMatchArray(['product' => 'Bookcase', 'price' => 150, 'active' => true]); -}); - -it('can append Arr', function () use ($dataTable): void { - $table = Table::make($dataTable); - expect($table)->toHaveCount(5); - $table->append(Arr::make([])); - expect($table)->toHaveCount(6); -}); - -it('can append array', function () use ($dataTable): void { - $table = Table::make($dataTable); - expect($table)->toHaveCount(5); - $table->append([]); - expect($table) - ->toHaveCount(6) - ->and($table->last()) - ->toBeInstanceOf(Arr::class); -}); - - -it('orders by desc', function () use ($dataTable): void { - $table = Table::make($dataTable); - $orderedTable = $table->orderBy('price'); - expect($orderedTable) - ->toHaveCount(5) - ->and($orderedTable->first()?->arr()) - ->toMatchArray(['product' => 'Door', 'price' => 300, 'active' => false]) - ->and($orderedTable->last()?->arr()) - ->toMatchArray(['product' => 'Door', 'price' => 100, 'active' => true]); -}); - -it('orders by asc', function () use ($dataTable): void { - $table = Table::make($dataTable); - $orderedTable = $table->orderBy('product', 'asc'); - expect($orderedTable) - ->toHaveCount(5) - ->and($orderedTable->first()?->arr()) - ->toMatchArray(['product' => 'Bookcase', 'price' => 150, 'active' => true]) - ->and($orderedTable->last()?->arr()) - ->toMatchArray(['product' => 'Door', 'price' => 100, 'active' => true]); -}); - -it('can get the cheapest of all products that are active', function () use ($dataTable): void { - $table = Table::make($dataTable); - $cheapestOfEachProduct = $table - ->where('active', '=', true) - ->orderBy('price', 'asc') - ->groupBy('product'); - - expect($cheapestOfEachProduct) - ->toHaveCount(4) - ->and($cheapestOfEachProduct->first()?->arr()) - ->toMatchArray(['product' => 'Chair', 'price' => 100, 'active' => true]) - ->and($cheapestOfEachProduct->last()?->arr()) - ->toMatchArray(['product' => 'Desk', 'price' => 200, 'active' => true]); -}); - -it('can transform all of the elements in a specific column', function () use ($dataTable): void { - $table = Table::make($dataTable); - $cheapestOfEachProduct = $table->transform('price', fn ($price): string => number_format($price, 2)); - - expect($cheapestOfEachProduct) - ->toHaveCount(5) - ->and($cheapestOfEachProduct->first()?->arr()) - ->toMatchArray(['product' => 'Desk', 'price' => '200.00', 'active' => true]) - ->and($cheapestOfEachProduct->last()?->arr()) - ->toMatchArray(['product' => 'Door', 'price' => '100.00', 'active' => true]); -}); - -it('can transform to native array', function () use ($dataTable): void { - $table = Table::make($dataTable); - $array = $table->toArray(); - - expect($array) - ->toBeArray() - ->toHaveCount(5); - expect($array[1]["product"])->toEqual("Chair"); - - $table = Table::make([]); - $array = $table->toArray(); - - expect($array) - ->toBeArray() - ->toHaveCount(0); -}); + public function test_can_filter_not_equal(): void + { + $table = Table::make($this->dataTable); + $this->assertCount(3, $table->select('product', 'price')->where('price', '!=', '100')); + + $table = Table::make($this->dataTable); + $this->assertCount(3, $table->select('product', 'price')->where('price', '!==', 100)); + + $table = Table::make($this->dataTable); + $this->assertCount(5, $table->select('product', 'price')->where('price', '!==', '100')); + } + + public function test_can_create_calculated_field(): void + { + $table = Table::make($this->dataTable); + + $calculatedTable = $table + ->select('product', 'price') + ->where('price', '>', 100) + ->calc('new_field', fn ($item): int|float => $item['price'] * 2); + + $this->assertCount(3, $calculatedTable); + $this->assertEquals(200, $calculatedTable->first()?->get('price')); + $this->assertEquals(400, $calculatedTable->first()?->get('new_field')); + $this->assertEquals(150, $calculatedTable->last()?->get('price')); + $this->assertEquals(300, $calculatedTable->last()?->get('new_field')); + } + + public function test_can_group(): void + { + $table = Table::make($this->dataTable); + $groupedTable = $table->groupBy('product'); + + $this->assertCount(4, $groupedTable); + $this->assertEquals(['product' => 'Desk', 'price' => 200, 'active' => true], $groupedTable->first()?->arr()); + $this->assertEquals(['product' => 'Bookcase', 'price' => 150, 'active' => true], $groupedTable->last()?->arr()); + } + + public function test_can_append_arr(): void + { + $table = Table::make($this->dataTable); + $this->assertCount(5, $table); + $table->append(Arr::make([])); + $this->assertCount(6, $table); + } + + public function test_can_append_array(): void + { + $table = Table::make($this->dataTable); + $this->assertCount(5, $table); + $table->append([]); + $this->assertCount(6, $table); + $this->assertInstanceOf(Arr::class, $table->last()); + } + + public function test_orders_by_desc(): void + { + $table = Table::make($this->dataTable); + $orderedTable = $table->orderBy('price'); + $this->assertCount(5, $orderedTable); + $this->assertEquals(['product' => 'Door', 'price' => 300, 'active' => false], $orderedTable->first()?->arr()); + $this->assertEquals(['product' => 'Door', 'price' => 100, 'active' => true], $orderedTable->last()?->arr()); + } + + public function test_orders_by_asc(): void + { + $table = Table::make($this->dataTable); + $orderedTable = $table->orderBy('product', 'asc'); + $this->assertCount(5, $orderedTable); + $this->assertEquals(['product' => 'Bookcase', 'price' => 150, 'active' => true], $orderedTable->first()?->arr()); + $this->assertEquals(['product' => 'Door', 'price' => 100, 'active' => true], $orderedTable->last()?->arr()); + } + + public function test_can_get_the_cheapest_of_all_products_that_are_active(): void + { + $table = Table::make($this->dataTable); + $cheapestOfEachProduct = $table + ->where('active', '=', true) + ->orderBy('price', 'asc') + ->groupBy('product'); + + $this->assertCount(4, $cheapestOfEachProduct); + $this->assertEquals(['product' => 'Chair', 'price' => 100, 'active' => true], $cheapestOfEachProduct->first()?->arr()); + $this->assertEquals(['product' => 'Desk', 'price' => 200, 'active' => true], $cheapestOfEachProduct->last()?->arr()); + } + + public function test_can_transform_all_of_the_elements_in_a_specific_column(): void + { + $table = Table::make($this->dataTable); + $cheapestOfEachProduct = $table->transform('price', fn ($price): string => number_format($price, 2)); + + $this->assertCount(5, $cheapestOfEachProduct); + $this->assertEquals(['product' => 'Desk', 'price' => '200.00', 'active' => true], $cheapestOfEachProduct->first()?->arr()); + $this->assertEquals(['product' => 'Door', 'price' => '100.00', 'active' => true], $cheapestOfEachProduct->last()?->arr()); + } + + public function test_can_transform_to_native_array(): void + { + $table = Table::make($this->dataTable); + $array = $table->toArray(); + + $this->assertIsArray($array); + $this->assertCount(5, $array); + $this->assertEquals("Chair", $array[1]["product"]); + + $table = Table::make([]); + $array = $table->toArray(); + + $this->assertIsArray($array); + $this->assertCount(0, $array); + } +}