From 22c2e925161b0736e6ae10fcb68a0e71f983050a Mon Sep 17 00:00:00 2001 From: Wilmer Arambula Date: Fri, 27 Jun 2025 12:56:13 -0400 Subject: [PATCH 1/8] Better namespace, add tests for `PHPStan` config and enhanced tests. --- composer.json | 14 +- phpstan.neon | 1 + src/NestedSetsBehavior.php | 7 +- src/NestedSetsQueryBehavior.php | 7 +- tests/NestedSetsBehaviorTest.php | 1214 +++++++++++++---- tests/NestedSetsQueryBehaviorTest.php | 39 +- tests/Support/Model/MultipleTreeQuery.php | 17 - tests/Support/Model/TreeQuery.php | 17 - tests/TestCase.php | 75 +- tests/config/phpstan-config.php | 19 - tests/phpstan-config.php | 15 +- tests/{Support => support}/data/clean.xml | 0 .../test-append-to-exists-another-tree.xml | 0 .../data/test-append-to-exists-down.xml | 0 .../data/test-append-to-exists-up.xml | 0 .../data/test-append-to-new.xml | 0 ...test-children-multiple-tree-with-depth.php | 0 .../data/test-children-multiple-tree.php | 0 .../data/test-children-with-depth.php | 0 .../data/test-children.php | 0 .../data/test-delete-with-children.xml | 0 .../{Support => support}/data/test-delete.xml | 0 .../test-insert-after-exists-another-tree.xml | 0 .../data/test-insert-after-exists-down.xml | 0 .../data/test-insert-after-exists-up.xml | 0 .../data/test-insert-after-new.xml | 0 ...test-insert-before-exists-another-tree.xml | 0 .../data/test-insert-before-exists-down.xml | 0 .../data/test-insert-before-exists-up.xml | 0 .../data/test-insert-before-new.xml | 0 .../data/test-leaves-multiple-tree-query.php | 0 .../data/test-leaves-multiple-tree.php | 0 .../data/test-leaves-query.php | 0 .../{Support => support}/data/test-leaves.php | 0 .../data/test-make-root-exists.xml | 0 .../data/test-make-root-new.xml | 0 .../data/test-next-multiple-tree.php | 0 tests/{Support => support}/data/test-next.php | 0 .../test-parents-multiple-tree-with-depth.php | 0 .../data/test-parents-multiple-tree.php | 0 .../data/test-parents-with-depth.php | 0 .../data/test-parents.php | 0 .../test-prepend-to-exists-another-tree.xml | 0 .../data/test-prepend-to-exists-down.xml | 0 .../data/test-prepend-to-exists-up.xml | 0 .../data/test-prepend-to-new.xml | 0 .../data/test-prev-multiple-tree.php | 0 tests/{Support => support}/data/test-prev.php | 0 .../data/test-roots-multiple-tree-query.php | 0 .../data/test-roots-query.php | 0 tests/{Support => support}/data/test.xml | 0 .../Model => support/model}/MultipleTree.php | 25 +- tests/support/model/MultipleTreeQuery.php | 22 + .../{Support/Model => support/model}/Tree.php | 23 +- tests/support/model/TreeQuery.php | 22 + 55 files changed, 1156 insertions(+), 361 deletions(-) delete mode 100644 tests/Support/Model/MultipleTreeQuery.php delete mode 100644 tests/Support/Model/TreeQuery.php delete mode 100644 tests/config/phpstan-config.php rename tests/{Support => support}/data/clean.xml (100%) rename tests/{Support => support}/data/test-append-to-exists-another-tree.xml (100%) rename tests/{Support => support}/data/test-append-to-exists-down.xml (100%) rename tests/{Support => support}/data/test-append-to-exists-up.xml (100%) rename tests/{Support => support}/data/test-append-to-new.xml (100%) rename tests/{Support => support}/data/test-children-multiple-tree-with-depth.php (100%) rename tests/{Support => support}/data/test-children-multiple-tree.php (100%) rename tests/{Support => support}/data/test-children-with-depth.php (100%) rename tests/{Support => support}/data/test-children.php (100%) rename tests/{Support => support}/data/test-delete-with-children.xml (100%) rename tests/{Support => support}/data/test-delete.xml (100%) rename tests/{Support => support}/data/test-insert-after-exists-another-tree.xml (100%) rename tests/{Support => support}/data/test-insert-after-exists-down.xml (100%) rename tests/{Support => support}/data/test-insert-after-exists-up.xml (100%) rename tests/{Support => support}/data/test-insert-after-new.xml (100%) rename tests/{Support => support}/data/test-insert-before-exists-another-tree.xml (100%) rename tests/{Support => support}/data/test-insert-before-exists-down.xml (100%) rename tests/{Support => support}/data/test-insert-before-exists-up.xml (100%) rename tests/{Support => support}/data/test-insert-before-new.xml (100%) rename tests/{Support => support}/data/test-leaves-multiple-tree-query.php (100%) rename tests/{Support => support}/data/test-leaves-multiple-tree.php (100%) rename tests/{Support => support}/data/test-leaves-query.php (100%) rename tests/{Support => support}/data/test-leaves.php (100%) rename tests/{Support => support}/data/test-make-root-exists.xml (100%) rename tests/{Support => support}/data/test-make-root-new.xml (100%) rename tests/{Support => support}/data/test-next-multiple-tree.php (100%) rename tests/{Support => support}/data/test-next.php (100%) rename tests/{Support => support}/data/test-parents-multiple-tree-with-depth.php (100%) rename tests/{Support => support}/data/test-parents-multiple-tree.php (100%) rename tests/{Support => support}/data/test-parents-with-depth.php (100%) rename tests/{Support => support}/data/test-parents.php (100%) rename tests/{Support => support}/data/test-prepend-to-exists-another-tree.xml (100%) rename tests/{Support => support}/data/test-prepend-to-exists-down.xml (100%) rename tests/{Support => support}/data/test-prepend-to-exists-up.xml (100%) rename tests/{Support => support}/data/test-prepend-to-new.xml (100%) rename tests/{Support => support}/data/test-prev-multiple-tree.php (100%) rename tests/{Support => support}/data/test-prev.php (100%) rename tests/{Support => support}/data/test-roots-multiple-tree-query.php (100%) rename tests/{Support => support}/data/test-roots-query.php (100%) rename tests/{Support => support}/data/test.xml (100%) rename tests/{Support/Model => support/model}/MultipleTree.php (58%) create mode 100644 tests/support/model/MultipleTreeQuery.php rename tests/{Support/Model => support/model}/Tree.php (50%) create mode 100644 tests/support/model/TreeQuery.php diff --git a/composer.json b/composer.json index ffd8815..1e68d12 100644 --- a/composer.json +++ b/composer.json @@ -9,11 +9,9 @@ "behavior" ], "license": "BSD-3-Clause", - "minimum-stability": "dev", - "prefer-stable": true, "require": { "php": ">=8.1", - "yiisoft/yii2": "dev-master|^22" + "yiisoft/yii2": "^2.0.53|^22" }, "require-dev": { "maglnet/composer-require-checker": "^4.1", @@ -22,21 +20,21 @@ "phpunit/phpunit": "^10.2", "rector/rector": "^2.0", "symplify/easy-coding-standard": "^12.3", - "yii2-extensions/phpstan": "dev-main" + "yii2-extensions/phpstan": "^0.3.0" }, "autoload": { "psr-4": { - "Yii2\\Extensions\\NestedSets\\": "src" + "yii2\\extensions\\nestedsets\\": "src" } }, "autoload-dev": { "psr-4": { - "Yii2\\Extensions\\NestedSets\\Tests\\": "tests" + "yii2\\extensions\\nestedsets\\tests\\": "tests" } }, "extra": { "branch-alias": { - "dev-main": "1.0.x-dev" + "dev-main": "0.1.x-dev" } }, "config": { @@ -50,7 +48,7 @@ "check-dependencies": "./vendor/bin/composer-require-checker check", "ecs": "./vendor/bin/ecs --fix", "rector": "./vendor/bin/rector process src", - "static": "./vendor/bin/phpstan analyse src --memory-limit=512M", + "static": "./vendor/bin/phpstan --memory-limit=512M", "tests": "./vendor/bin/phpunit" }, "repositories": [ diff --git a/phpstan.neon b/phpstan.neon index 0a3906f..7adfced 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -9,6 +9,7 @@ parameters: paths: - src + - tests tmpDir: %currentWorkingDirectory%/runtime diff --git a/src/NestedSetsBehavior.php b/src/NestedSetsBehavior.php index 3db204b..86aa536 100644 --- a/src/NestedSetsBehavior.php +++ b/src/NestedSetsBehavior.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Yii2\Extensions\NestedSets; +namespace yii2\extensions\nestedsets; use LogicException; use yii\base\{Behavior, NotSupportedException}; @@ -30,9 +30,8 @@ * - Query for parents, children, leaves, previous and next siblings. * - Supports custom attribute names for left, right, depth, and tree columns. * - * @template T of ActiveRecord - * - * @extends Behavior + * @phpstan-template T of ActiveRecord + * @phpstan-extends Behavior * * @property int $depth * @property int $lft diff --git a/src/NestedSetsQueryBehavior.php b/src/NestedSetsQueryBehavior.php index 52acc40..da87964 100644 --- a/src/NestedSetsQueryBehavior.php +++ b/src/NestedSetsQueryBehavior.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Yii2\Extensions\NestedSets; +namespace yii2\extensions\nestedsets; use LogicException; use yii\base\Behavior; @@ -26,9 +26,8 @@ * - Query for root nodes in a nested set. * - Supports custom left, right, and tree attribute names as defined in the model. * - * @template T of ActiveQuery - * - * @extends Behavior + * @phpstan-template T of ActiveQuery + * @phpstan-extends Behavior * * @copyright Copyright (C) 2023 Terabytesoftw. * @license https://opensource.org/license/bsd-3-clause BSD 3-Clause License. diff --git a/tests/NestedSetsBehaviorTest.php b/tests/NestedSetsBehaviorTest.php index 22e8814..775e029 100644 --- a/tests/NestedSetsBehaviorTest.php +++ b/tests/NestedSetsBehaviorTest.php @@ -2,742 +2,1492 @@ declare(strict_types=1); -namespace Yii2\Extensions\NestedSets\Tests; +namespace yii2\extensions\nestedsets\tests; use yii\base\NotSupportedException; use yii\db\Exception; use yii\helpers\ArrayHelper; -use Yii2\Extensions\NestedSets\Tests\Support\Model\MultipleTree; -use Yii2\Extensions\NestedSets\Tests\Support\Model\Tree; +use yii2\extensions\nestedsets\tests\support\model\{MultipleTree, Tree}; + +use function simplexml_load_file; final class NestedSetsBehaviorTest extends TestCase { - public function testMakeRootNewNew(): void + public function testReturnTrueAndMatchXmlAfterMakeRootNewForTreeAndMultipleTree(): void { $this->createDatabase(); $nodeTree = new Tree(['name' => 'Root']); - $this->assertTrue($nodeTree->makeRoot()); + + self::assertTrue( + $nodeTree->makeRoot(), + '\'makeRoot()\' should return \'true\' when creating a new root node in \'Tree\'.', + ); $nodeMultipleTree = new MultipleTree(['name' => 'Root 1']); - $this->assertTrue($nodeMultipleTree->makeRoot()); + + self::assertTrue( + $nodeMultipleTree->makeRoot(), + '\'makeRoot()\' should return \'true\' when creating the first root node in \'MultipleTree\'.', + ); $nodeMultipleTree = new MultipleTree(['name' => 'Root 2']); - $this->assertTrue($nodeMultipleTree->makeRoot()); - $this->assertEquals( + self::assertTrue( + $nodeMultipleTree->makeRoot(), + '\'makeRoot()\' should return \'true\' when creating a second root node in \'MultipleTree\'.', + ); + + $fileXML = simplexml_load_file("{$this->fixtureDirectory}/test-make-root-new.xml"); + + self::assertNotFalse( + $fileXML, + 'XML file \'test-make-root-new.xml\' should be loaded successfully for result comparison.', + ); + self::assertSame( $this->buildFlatXMLDataSet($this->getDataSet()), - simplexml_load_file(__DIR__ . '/Support/data/test-make-root-new.xml')->asXML(), + $fileXML->asXML(), + 'Resulting dataset after \'makeRoot()\' must match the expected XML structure.', ); } - public function testMakeRootNewExceptionIsRaisedWhenTreeAttributeIsFalseAndRootIsExists(): void + public function testThrowExceptionWhenMakeRootWithTreeAttributeFalseAndRootExists(): void { - $this->expectException(Exception::class); - $this->expectExceptionMessage('Can not create more than one root when "treeAttribute" is false.'); - $this->generateFixtureTree(); $node = new Tree(['name' => 'Root']); + + $this->expectException(Exception::class); + $this->expectExceptionMessage('Can not create more than one root when "treeAttribute" is false.'); + $node->makeRoot(); } - public function testPrependToNew(): void + public function testReturnTrueAndMatchXmlAfterPrependToNewNodeForTreeAndMultipleTree(): void { $this->generateFixtureTree(); $node = new Tree(['name' => 'New node']); - $this->assertTrue($node->prependTo(Tree::findOne(9))); + + $childOfNode = Tree::findOne(9); + + self::assertNotNull( + $childOfNode, + 'Node with ID \'9\' must exist before calling \'prependTo()\' on it in \'Tree\'.', + ); + self::assertTrue( + $node->prependTo($childOfNode), + '\'prependTo()\' should return \'true\' when prepending a new node to node \'9\' in \'Tree\'.', + ); $node = new MultipleTree(['name' => 'New node']); - $this->assertTrue($node->prependTo(MultipleTree::findOne(31))); - $this->assertEquals( + $childOfNode = MultipleTree::findOne(31); + + self::assertNotNull( + $childOfNode, + 'Node with ID \'31\' must exist before calling \'prependTo()\' on it in \'MultipleTree\'.', + ); + self::assertTrue( + $node->prependTo($childOfNode), + '\'prependTo()\' should return \'true\' when prepending a new node to node \'31\' in \'MultipleTree\'.', + ); + + $fileXML = simplexml_load_file("{$this->fixtureDirectory}/test-prepend-to-new.xml"); + + self::assertNotFalse( + $fileXML, + 'XML file \'test-prepend-to-new.xml\' should be loaded successfully for result comparison.', + ); + self::assertSame( $this->buildFlatXMLDataSet($this->getDataSet()), - simplexml_load_file(__DIR__ . '/Support/data/test-prepend-to-new.xml')->asXML(), + $fileXML->asXML(), + 'Resulting dataset after \'prependTo()\' must match the expected XML structure.', ); } - public function testAppendNewToExceptionIsRaisedWhenTargetIsNewRecord(): void + public function testThrowExceptionWhenAppendToNewNodeTargetIsNewRecord(): void { $this->generateFixtureTree(); + $node = new Tree(['name' => 'New node']); + $this->expectException(Exception::class); $this->expectExceptionMessage('Can not create a node when the target node is new record.'); - $node = new Tree(['name' => 'New node']); $node->appendTo(new Tree()); } - public function testInsertBeforeNew(): void + public function testReturnTrueAndMatchXmlAfterInsertBeforeNewForTreeAndMultipleTree(): void { $this->generateFixtureTree(); $node = new Tree(['name' => 'New node']); - $this->assertTrue($node->insertBefore(Tree::findOne(9))); + + $childOfNode = Tree::findOne(9); + + self::assertNotNull( + $childOfNode, + 'Node with ID \'9\' should exist before calling \'insertBefore()\' on it in \'Tree\'.', + ); + self::assertTrue( + $node->insertBefore($childOfNode), + '\'insertBefore()\' should return \'true\' when inserting a new node before node \'9\' in \'Tree\'.', + ); $node = new MultipleTree(['name' => 'New node']); - $this->assertTrue($node->insertBefore(MultipleTree::findOne(31))); - $this->assertEquals( + $childOfNode = MultipleTree::findOne(31); + + self::assertNotNull( + $childOfNode, + 'Node with ID \'31\' should exist before calling \'insertBefore()\' on it in \'MultipleTree\'.', + ); + self::assertTrue( + $node->insertBefore($childOfNode), + '\'insertBefore()\' should return \'true\' when inserting a new node before node \'31\' in \'MultipleTree\'.', + ); + + $fileXML = simplexml_load_file("{$this->fixtureDirectory}/test-insert-before-new.xml"); + + self::assertNotFalse( + $fileXML, + 'XML file \'test-insert-before-new.xml\' should be loaded successfully for result comparison.', + ); + self::assertEquals( $this->buildFlatXMLDataSet($this->getDataSet()), - simplexml_load_file(__DIR__ . '/Support/data/test-insert-before-new.xml')->asXML(), + $fileXML->asXML(), + 'Resulting dataset after \'insertBefore()\' must match the expected XML structure.', ); } - public function testInsertBeforeNewExceptionIsRaisedWhenTargetIsNewRecord(): void + public function testThrowExceptionWhenInsertBeforeNewNodeTargetIsNewRecord(): void { $this->generateFixtureTree(); + $node = new Tree(['name' => 'New node']); + $this->expectException(Exception::class); $this->expectExceptionMessage('Can not create a node when the target node is new record.'); - $node = new Tree(['name' => 'New node']); $node->insertBefore(new Tree()); } - public function testInsertBeforeNewExceptionIsRaisedWhenTargetIsRoot(): void + public function testThrowExceptionWhenInsertBeforeNewNodeTargetIsRoot(): void { $this->generateFixtureTree(); + $node = new Tree(['name' => 'New node']); + $rootNode = Tree::findOne(1); + + self::assertNotNull( + $rootNode, + 'Root node with ID \'1\' should exist before calling \'insertBefore()\' on it in \'Tree\'.', + ); + $this->expectException(Exception::class); $this->expectExceptionMessage('Can not create a node when the target node is root.'); - $node = new Tree(['name' => 'New node']); - $node->insertBefore(Tree::findOne(1)); + $node->insertBefore($rootNode); } - public function testInsertAfterNew(): void + public function testReturnTrueAndMatchXmlAfterInsertAfterNewForTreeAndMultipleTree(): void { $this->generateFixtureTree(); $node = new Tree(['name' => 'New node']); - $this->assertTrue($node->insertAfter(Tree::findOne(9))); + + $childOfNode = Tree::findOne(9); + + self::assertNotNull( + $childOfNode, + 'Node with ID \'9\' must exist before calling \'insertAfter()\' on it in \'Tree\'.', + ); + + self::assertTrue( + $node->insertAfter($childOfNode), + '\'insertAfter()\' should return \'true\' when inserting a new node after node \'9\' in \'Tree\'.', + ); $node = new MultipleTree(['name' => 'New node']); - $this->assertTrue($node->insertAfter(MultipleTree::findOne(31))); - $this->assertEquals( + $childOfNode = MultipleTree::findOne(31); + + self::assertNotNull( + $childOfNode, + 'Node with ID \'31\' must exist before calling \'insertAfter()\' on it in \'MultipleTree\'.', + ); + self::assertTrue( + $node->insertAfter($childOfNode), + '\'insertAfter()\' should return \'true\' when inserting a new node after node \'31\' in \'MultipleTree\'.', + ); + + $fileXML = simplexml_load_file("{$this->fixtureDirectory}/test-insert-after-new.xml"); + + self::assertNotFalse( + $fileXML, + 'XML file \'test-insert-after-new.xml\' must be loaded successfully for result comparison.', + ); + self::assertEquals( $this->buildFlatXMLDataSet($this->getDataSet()), - simplexml_load_file(__DIR__ . '/Support/data/test-insert-after-new.xml')->asXML(), + $fileXML->asXML(), + 'Resulting dataset after \'insertAfter()\' must match the expected XML structure.', ); } - public function testInsertAfterNewExceptionIsRaisedWhenTargetIsNewRecord(): void + public function testThrowExceptionWhenInsertAfterNewNodeTargetIsNewRecord(): void { $this->generateFixtureTree(); + $node = new Tree(['name' => 'New node']); + $this->expectException(Exception::class); $this->expectExceptionMessage('Can not create a node when the target node is new record.'); - $node = new Tree(['name' => 'New node']); $node->insertAfter(new Tree()); } - public function testInsertAfterNewExceptionIsRaisedWhenTargetIsRoot() + public function testThrowExceptionWhenInsertAfterNewNodeTargetIsRoot(): void { $this->generateFixtureTree(); + $node = new Tree(['name' => 'New node']); + + $rootNode = Tree::findOne(1); + + self::assertNotNull( + $rootNode, + 'Root node with ID \'1\' should exist before calling \'insertAfter()\' on it in \'Tree\'.', + ); + $this->expectException(Exception::class); $this->expectExceptionMessage('Can not create a node when the target node is root.'); - $node = new Tree(['name' => 'New node']); - $node->insertAfter(Tree::findOne(1)); + $node->insertAfter($rootNode); } - public function testMakeRootExists() + public function testReturnTrueAndMatchXmlAfterMakeRootOnExistingMultipleTreeNode(): void { $this->generateFixtureTree(); $node = MultipleTree::findOne(31); + + self::assertNotNull( + $node, + 'Node with ID \'31\' must exist before calling \'makeRoot()\' on it in \'MultipleTree\'.', + ); + $node->name = 'Updated node 2'; - $this->assertTrue($node->makeRoot()); - $this->assertEquals( + self::assertTrue( + $node->makeRoot(), + '\'makeRoot()\' should return \'true\' when called on node \'31\' in \'MultipleTree\'.', + ); + + $fileXML = simplexml_load_file("{$this->fixtureDirectory}/test-make-root-exists.xml"); + + self::assertNotFalse( + $fileXML, + 'XML file \'test-make-root-exists.xml\' must be loaded successfully for result comparison.', + ); + self::assertEquals( $this->buildFlatXMLDataSet($this->getDataSetMultipleTree()), - simplexml_load_file(__DIR__ . '/Support/data/test-make-root-exists.xml')->asXML(), + $fileXML->asXML(), + 'Resulting dataset after \'makeRoot()\' must match the expected XML structure for \'MultipleTree\'.', ); } - public function testMakeRootExistsExceptionIsRaisedWhenTreeAttributeIsFalse(): void + public function testThrowExceptionWhenMakeRootOnNonRootNodeWithTreeAttributeFalse(): void { $this->generateFixtureTree(); + $node = Tree::findOne(9); + + self::assertNotNull($node, 'Node with ID \'9\' should exist before calling \'makeRoot()\' on it in \'Tree\'.'); + $this->expectException(Exception::class); $this->expectExceptionMessage('Can not move a node as the root when "treeAttribute" is false.'); - $node = Tree::findOne(9); $node->makeRoot(); } - public function testMakeRootExistsExceptionIsRaisedWhenItsRoot(): void + public function testThrowExceptionWhenMakeRootOnRootNodeInMultipleTree(): void { $this->generateFixtureTree(); + $node = MultipleTree::findOne(23); + + self::assertNotNull( + $node, + 'Node with ID \'23\' should exist before calling \'makeRoot()\' on it in \'MultipleTree\'.', + ); + $this->expectException(Exception::class); $this->expectExceptionMessage('Can not move the root node as the root.'); - $node = MultipleTree::findOne(23); $node->makeRoot(); } - public function testPrependToExistsUp(): void + public function testReturnTrueAndMatchXmlAfterPrependToUpForTreeAndMultipleTree(): void { $this->generateFixtureTree(); $node = Tree::findOne(9); + + self::assertNotNull( + $node, + 'Node with ID \'9\' must exist before calling \'prependTo()\' on another node in \'Tree\'.', + ); + $node->name = 'Updated node 2'; - $this->assertTrue($node->prependTo(Tree::findOne(2))); + + $childOfNode = Tree::findOne(2); + + self::assertNotNull( + $childOfNode, + 'Target node with ID \'2\' must exist before calling \'prependTo()\' on it in \'Tree\'.', + ); + self::assertTrue( + $node->prependTo($childOfNode), + '\'prependTo()\' should return \'true\' when moving node \'9\' as child of node \'2\' in \'Tree\'.', + ); $node = MultipleTree::findOne(31); + + self::assertNotNull( + $node, + 'Node with ID \'31\' must exist before calling \'prependTo()\' on another node in \'MultipleTree\'.', + ); + $node->name = 'Updated node 2'; - $this->assertTrue($node->prependTo(MultipleTree::findOne(24))); - $this->assertEquals( + $childOfNode = MultipleTree::findOne(24); + + self::assertNotNull( + $childOfNode, + 'Target node with ID \'24\' must exist before calling \'prependTo()\' on it in \'MultipleTree\'.', + ); + self::assertTrue( + $node->prependTo($childOfNode), + '\'prependTo()\' should return \'true\' when moving node \'31\' as child of node \'24\' in \'MultipleTree\'.', + ); + + $fileXML = simplexml_load_file("{$this->fixtureDirectory}/test-prepend-to-exists-up.xml"); + + self::assertNotFalse( + $fileXML, + 'XML file \'test-prepend-to-exists-up.xml\' must be loaded successfully for result comparison.', + ); + self::assertEquals( $this->buildFlatXMLDataSet($this->getDataSet()), - simplexml_load_file(__DIR__ . '/Support/data/test-prepend-to-exists-up.xml')->asXML(), + $fileXML->asXML(), + 'Resulting dataset after \'prependTo()\' must match the expected XML structure.', ); } - public function testPrependToExistsDown(): void + public function testReturnTrueAndMatchXmlAfterPrependToDownForTreeAndMultipleTree(): void { $this->generateFixtureTree(); $node = Tree::findOne(9); + + self::assertNotNull( + $node, + 'Node with ID \'9\' should exist before calling \'prependTo()\' on another node.', + ); + $node->name = 'Updated node 2'; - $this->assertTrue($node->prependTo(Tree::findOne(16))); + + $childOfNode = Tree::findOne(16); + + self::assertNotNull( + $childOfNode, + 'Target node with ID \'16\' should exist before calling \'prependTo()\' on it.', + ); + self::assertTrue( + $node->prependTo($childOfNode), + '\'prependTo()\' should return \'true\' when moving node \'9\' as child of node \'16\' in \'Tree\'.', + ); $node = MultipleTree::findOne(31); + + self::assertNotNull( + $node, + 'Node with ID \'31\' should exist before calling \'prependTo()\' on another node.', + ); + $node->name = 'Updated node 2'; - $this->assertTrue($node->prependTo(MultipleTree::findOne(38))); - $this->assertEquals( + $childOfNode = MultipleTree::findOne(38); + + self::assertNotNull( + $childOfNode, + 'Target node with ID \'38\' should exist before calling \'prependTo()\' on it.', + ); + self::assertTrue( + $node->prependTo($childOfNode), + '\'prependTo()\' should return \'true\' when moving node \'31\' as child of node \'38\' in \'MultipleTree\'.', + ); + + $fileXML = simplexml_load_file("{$this->fixtureDirectory}/test-prepend-to-exists-down.xml"); + + self::assertNotFalse( + $fileXML, + 'XML file \'test-prepend-to-exists-down.xml\' should be loaded successfully for result comparison.', + ); + self::assertEquals( $this->buildFlatXMLDataSet($this->getDataSet()), - simplexml_load_file(__DIR__ . '/Support/data/test-prepend-to-exists-down.xml')->asXML(), + $fileXML->asXML(), + 'Resulting dataset after \'prependTo()\' must match the expected XML structure.', ); } - public function testPrependToExistsAnotherTree(): void + public function testReturnTrueAndMatchXmlAfterPrependToMultipleTreeWhenTargetIsInAnotherTree(): void { $this->generateFixtureTree(); $node = MultipleTree::findOne(9); + + self::assertNotNull( + $node, + 'Node with ID \'9\' must exist before attempting to prepend to a node in another tree.', + ); + $node->name = 'Updated node 2'; - $this->assertTrue($node->prependTo(MultipleTree::findOne(53))); - $this->assertEquals( + $childOfNode = MultipleTree::findOne(53); + + self::assertNotNull( + $childOfNode, + 'Target node with ID \'53\' must exist before attempting to prepend to it.', + ); + self::assertTrue( + $node->prependTo($childOfNode), + '\'prependTo()\' should return \'true\' when moving node \'9\' as child of node \'53\' in another \'tree\'.', + ); + + $fileXML = simplexml_load_file("{$this->fixtureDirectory}/test-prepend-to-exists-another-tree.xml"); + + self::assertNotFalse( + $fileXML, + 'XML file \'test-prepend-to-exists-another-tree.xml\' must be loaded successfully for result comparison.', + ); + self::assertEquals( $this->buildFlatXMLDataSet($this->getDataSetMultipleTree()), - simplexml_load_file(__DIR__ . '/Support/data/test-prepend-to-exists-another-tree.xml')->asXML(), + $fileXML->asXML(), + 'Resulting dataset after \'prependTo()\' must match the expected XML structure for \'MultipleTree\'.', ); } - public function testPrependToExistsExceptionIsRaisedWhenTargetIsNewRecord(): void + public function testThrowExceptionWhenPrependToTargetIsNewRecord(): void { $this->generateFixtureTree(); + $node = Tree::findOne(9); + + self::assertNotNull($node, 'Node with ID \'9\' must exist before calling \'prependTo()\' on another node.'); + $this->expectException(Exception::class); $this->expectExceptionMessage('Can not move a node when the target node is new record.'); - $node = Tree::findOne(9); $node->prependTo(new Tree()); } - public function testPrependToExistsExceptionIsRaisedWhenTargetIsSame(): void + public function testThrowExceptionWhenPrependToTargetIsSame(): void { $this->generateFixtureTree(); + $node = Tree::findOne(9); + + self::assertNotNull($node, 'Node with ID \'9\' should exist before calling \'prependTo()\' on itself.'); + $this->expectException(Exception::class); $this->expectExceptionMessage('Can not move a node when the target node is same.'); - $node = Tree::findOne(9); - $node->prependTo(Tree::findOne(9)); + $node->prependTo($node); } - public function testPrependToExistsExceptionIsRaisedWhenTargetIsChild(): void + public function testThrowExceptionWhenPrependToTargetIsChild(): void { $this->generateFixtureTree(); + $node = Tree::findOne(9); + + self::assertNotNull( + $node, + 'Node with ID \'9\' must exist before calling \'prependTo()\' on another node.', + ); + + $childOfNode = Tree::findOne(11); + + self::assertNotNull( + $childOfNode, + 'Target node with ID \'11\' must exist before calling \'prependTo()\' on it.', + ); + $this->expectException(Exception::class); $this->expectExceptionMessage('Can not move a node when the target node is child.'); - $node = Tree::findOne(9); - $node->prependTo(Tree::findOne(11)); + $node->prependTo($childOfNode); } - public function testAppendToExistsUp(): void + public function testReturnTrueAndMatchXmlAfterAppendToUpForTreeAndMultipleTree(): void { $this->generateFixtureTree(); $node = Tree::findOne(9); + + self::assertNotNull( + $node, + 'Node with ID \'9\' must exist before calling \'appendTo()\' on another node.', + ); + $node->name = 'Updated node 2'; - $this->assertTrue($node->appendTo(Tree::findOne(2))); + + $childOfNode = Tree::findOne(2); + + self::assertNotNull( + $childOfNode, + 'Target node with ID \'2\' must exist before calling \'appendTo()\' on it.', + ); + self::assertTrue( + $node->appendTo($childOfNode), + '\'appendTo()\' should return \'true\' when moving node \'9\' as child of node \'2\' in \'Tree\'.', + ); $node = MultipleTree::findOne(31); + + self::assertNotNull( + $node, + 'Node with ID \'31\' must exist before calling \'appendTo()\' on another node.', + ); + $node->name = 'Updated node 2'; - $this->assertTrue($node->appendTo(MultipleTree::findOne(24))); - $this->assertEquals( + $childOfNode = MultipleTree::findOne(24); + + self::assertNotNull( + $childOfNode, + 'Target node with ID \'24\' must exist before calling \'appendTo()\' on it.', + ); + self::assertTrue( + $node->appendTo($childOfNode), + '\'appendTo()\' should return \'true\' when moving node \'31\' as child of node \'24\' in \'MultipleTree\'.', + ); + + $fileXML = simplexml_load_file("{$this->fixtureDirectory}/test-append-to-exists-up.xml"); + + self::assertNotFalse( + $fileXML, + 'XML file \'test-append-to-exists-up.xml\' must be loaded successfully for result comparison.', + ); + self::assertEquals( $this->buildFlatXMLDataSet($this->getDataSet()), - simplexml_load_file(__DIR__ . '/Support/data/test-append-to-exists-up.xml')->asXML(), + $fileXML->asXML(), + 'Resulting dataset after \'appendTo()\' must match the expected XML structure.', ); } - public function testAppendToExistsDown(): void + public function testReturnTrueAndMatchXmlAfterAppendToDownForTreeAndMultipleTree(): void { $this->generateFixtureTree(); $node = Tree::findOne(9); + + self::assertNotNull( + $node, + 'Node with ID \'9\' should exist before calling \'appendTo()\' on another node.', + ); + $node->name = 'Updated node 2'; - $this->assertTrue($node->appendTo(Tree::findOne(16))); + + $childOfNode = Tree::findOne(16); + + self::assertNotNull( + $childOfNode, + 'Target node with ID \'16\' should exist before calling \'appendTo()\' on it.', + ); + self::assertTrue( + $node->appendTo($childOfNode), + '\'appendTo()\' should return \'true\' when moving node \'9\' as child of node \'16\' in \'Tree\'.', + ); $node = MultipleTree::findOne(31); + + self::assertNotNull( + $node, + 'Node with ID \'31\' should exist before calling \'appendTo()\' on another node.', + ); + $node->name = 'Updated node 2'; - $this->assertTrue($node->appendTo(MultipleTree::findOne(38))); - $this->assertEquals( + $childOfNode = MultipleTree::findOne(38); + + self::assertNotNull( + $childOfNode, + 'Target node with ID \'38\' should exist before calling \'appendTo()\' on it.', + ); + self::assertTrue( + $node->appendTo($childOfNode), + '\'appendTo()\' should return \'true\' when moving node \'31\' as child of node \'38\' in \'MultipleTree\'.', + ); + + $fileXML = simplexml_load_file("{$this->fixtureDirectory}/test-append-to-exists-down.xml"); + + self::assertNotFalse( + $fileXML, + 'XML file \'test-append-to-exists-down.xml\' should be loaded successfully for result comparison.', + ); + self::assertEquals( $this->buildFlatXMLDataSet($this->getDataSet()), - simplexml_load_file(__DIR__ . '/Support/data/test-append-to-exists-down.xml')->asXML(), + $fileXML->asXML(), + 'Resulting dataset after \'appendTo()\' must match the expected XML structure.', ); } - public function testAppendToExistsAnotherTree(): void + public function testReturnTrueAndMatchXmlAfterAppendToMultipleTreeWhenTargetIsInAnotherTree(): void { $this->generateFixtureTree(); $node = MultipleTree::findOne(9); + + self::assertNotNull( + $node, + 'Node with ID \'9\' must exist before attempting to append to a node in another tree.', + ); + $node->name = 'Updated node 2'; - $this->assertTrue($node->appendTo(MultipleTree::findOne(53))); - $this->assertEquals( + $childOfNode = MultipleTree::findOne(53); + + self::assertNotNull( + $childOfNode, + 'Target node with ID \'53\' must exist before attempting to append to it.', + ); + + self::assertTrue( + $node->appendTo($childOfNode), + '\'appendTo()\' should return \'true\' when moving node \'9\' as child of node \'53\' in another tree.', + ); + + $fileXML = simplexml_load_file("{$this->fixtureDirectory}/test-append-to-exists-another-tree.xml"); + + self::assertNotFalse( + $fileXML, + 'XML file \'test-append-to-exists-another-tree.xml\' must be loaded successfully for result comparison.', + ); + self::assertEquals( $this->buildFlatXMLDataSet($this->getDataSetMultipleTree()), - simplexml_load_file(__DIR__ . '/Support/data/test-append-to-exists-another-tree.xml')->asXML(), + $fileXML->asXML(), + 'Resulting dataset after \'appendTo()\' must match the expected XML structure for \'MultipleTree\'.', ); } - public function testAppendToExistsExceptionIsRaisedWhenTargetIsNewRecord(): void + public function testThrowExceptionWhenAppendToTargetIsNewRecord(): void { $this->generateFixtureTree(); + $node = Tree::findOne(9); + + self::assertNotNull($node, 'Node with ID \'9\' must exist before calling \'appendTo()\' on another node.'); + $this->expectException(Exception::class); $this->expectExceptionMessage('Can not move a node when the target node is new record.'); - $node = Tree::findOne(9); $node->appendTo(new Tree()); } - public function testAppendToExistsExceptionIsRaisedWhenTargetIsSame(): void + public function testThrowExceptionWhenAppendToTargetIsSame(): void { $this->generateFixtureTree(); + $node = Tree::findOne(9); + + self::assertNotNull( + $node, + 'Node with ID \'9\' should exist before calling \'appendTo()\' on another node.', + ); + + $childOfNode = Tree::findOne(9); + + self::assertNotNull( + $childOfNode, + 'Target node with ID \'9\' should exist before calling \'appendTo()\' on it.', + ); + $this->expectException(Exception::class); $this->expectExceptionMessage('Can not move a node when the target node is same.'); - $node = Tree::findOne(9); - $node->appendTo(Tree::findOne(9)); + $node->appendTo($childOfNode); } - public function testAppendToExistsExceptionIsRaisedWhenTargetIsChild(): void + public function testThrowExceptionWhenAppendToTargetIsChild(): void { $this->generateFixtureTree(); + $node = Tree::findOne(9); + + self::assertNotNull( + $node, + 'Expected node with ID \'9\' to exist before calling \'appendTo()\' on another node.', + ); + + $childOfNode = Tree::findOne(11); + + self::assertNotNull( + $childOfNode, + 'Expected target child node with ID \'11\' to exist before calling \'appendTo()\' on it.', + ); + $this->expectException(Exception::class); $this->expectExceptionMessage('Can not move a node when the target node is child.'); - $node = Tree::findOne(9); - $node->appendTo(Tree::findOne(11)); + $node->appendTo($childOfNode); } - public function testInsertBeforeExistsUp(): void + public function testReturnTrueAndMatchXmlAfterInsertBeforeUpForTreeAndMultipleTree(): void { $this->generateFixtureTree(); $node = Tree::findOne(9); + + self::assertNotNull( + $node, + 'Node with ID \'9\' must exist before calling insertBefore() on another node.', + ); + $node->name = 'Updated node 2'; - $this->assertTrue($node->insertBefore(Tree::findOne(2))); + + $childOfNode = Tree::findOne(2); + + self::assertNotNull( + $childOfNode, + 'Target node with ID \'2\' must exist before calling insertBefore() on it.', + ); + self::assertTrue( + $node->insertBefore($childOfNode), + 'insertBefore() should return true when moving node \'9\' before node \'2\' in Tree.', + ); $node = MultipleTree::findOne(31); + + self::assertNotNull( + $node, + 'Node with ID \'31\' must exist before calling insertBefore() on another node.', + ); + $node->name = 'Updated node 2'; - $this->assertTrue($node->insertBefore(MultipleTree::findOne(24))); - $this->assertEquals( + $childOfNode = MultipleTree::findOne(24); + + self::assertNotNull( + $childOfNode, + 'Target node with ID \'24\' must exist before calling insertBefore() on it.', + ); + self::assertTrue( + $node->insertBefore($childOfNode), + 'insertBefore() should return true when moving node \'31\' before node \'24\' in MultipleTree.', + ); + + $fileXML = simplexml_load_file("{$this->fixtureDirectory}/test-insert-before-exists-up.xml"); + + self::assertNotFalse( + $fileXML, + 'XML file \'test-insert-before-exists-up.xml\' must be loaded successfully for result comparison.', + ); + self::assertEquals( $this->buildFlatXMLDataSet($this->getDataSet()), - simplexml_load_file(__DIR__ . '/Support/data/test-insert-before-exists-up.xml')->asXML(), + $fileXML->asXML(), + 'Resulting dataset after insertBefore() must match the expected XML structure.', ); } - public function testInsertBeforeExistsDown(): void + public function testReturnTrueAndMatchXmlAfterInsertBeforeDownForTreeAndMultipleTree(): void { $this->generateFixtureTree(); $node = Tree::findOne(9); + + self::assertNotNull( + $node, + 'Node with ID \'9\' should exist before calling insertBefore() on another node.', + ); + $node->name = 'Updated node 2'; - $this->assertTrue($node->insertBefore(Tree::findOne(16))); + + $childOfNode = Tree::findOne(16); + + self::assertNotNull( + $childOfNode, + 'Target node with ID \'16\' should exist before calling insertBefore() on it.', + ); + self::assertTrue( + $node->insertBefore($childOfNode), + 'insertBefore() should return true when moving node \'9\' before node \'16\' in Tree.', + ); $node = MultipleTree::findOne(31); + + self::assertNotNull( + $node, + 'Node with ID \'31\' should exist before calling insertBefore() on another node.', + ); + $node->name = 'Updated node 2'; - $this->assertTrue($node->insertBefore(MultipleTree::findOne(38))); - $this->assertEquals( + $childOfNode = MultipleTree::findOne(38); + + self::assertNotNull( + $childOfNode, + 'Target node with ID \'38\' should exist before calling insertBefore() on it.', + ); + self::assertTrue( + $node->insertBefore($childOfNode), + 'insertBefore() should return true when moving node \'31\' before node \'38\' in MultipleTree.', + ); + + $fileXML = simplexml_load_file("{$this->fixtureDirectory}/test-insert-before-exists-down.xml"); + + self::assertNotFalse( + $fileXML, + 'XML file \'test-insert-before-exists-down.xml\' should be loaded successfully for result comparison.', + ); + self::assertEquals( $this->buildFlatXMLDataSet($this->getDataSet()), - simplexml_load_file(__DIR__ . '/Support/data/test-insert-before-exists-down.xml')->asXML(), + $fileXML->asXML(), + 'Resulting dataset after insertBefore() must match the expected XML structure.', ); } - public function testInsertBeforeExistsAnotherTree(): void + public function testReturnTrueAndMatchXmlAfterInsertBeforeMultipleTreeWhenTargetIsInAnotherTree(): void { $this->generateFixtureTree(); $node = MultipleTree::findOne(9); + + self::assertNotNull( + $node, + 'Node with ID \'9\' must exist before attempting to insert before a node in another tree.', + ); + $node->name = 'Updated node 2'; - $this->assertTrue($node->insertBefore(MultipleTree::findOne(53))); - $this->assertEquals( + $childOfNode = MultipleTree::findOne(53); + + self::assertNotNull( + $childOfNode, + 'Target node with ID \'53\' must exist before attempting to insert before it.', + ); + self::assertTrue( + $node->insertBefore($childOfNode), + '\'insertBefore()\' should return \'true\' when moving node \'9\' before node \'53\' in another tree.', + ); + + $fileXML = simplexml_load_file("{$this->fixtureDirectory}/test-insert-before-exists-another-tree.xml"); + + self::assertNotFalse( + $fileXML, + 'XML file \'test-insert-before-exists-another-tree.xml\' must be loaded successfully for result comparison.', + ); + self::assertEquals( $this->buildFlatXMLDataSet($this->getDataSetMultipleTree()), - simplexml_load_file(__DIR__ . '/Support/data/test-insert-before-exists-another-tree.xml')->asXML(), + $fileXML->asXML(), + 'Resulting dataset after \'insertBefore()\' must match the expected XML structure for \'MultipleTree\'.', ); } - public function testInsertBeforeExistsExceptionIsRaisedWhenTargetIsNewRecord(): void + public function testThrowExceptionWhenInsertBeforeTargetIsNewRecord(): void { $this->generateFixtureTree(); + $node = Tree::findOne(9); + + self::assertNotNull( + $node, + 'Node with ID \'9\' should exist before calling \'insertBefore()\' on a new record.', + ); + $this->expectException(Exception::class); $this->expectExceptionMessage('Can not move a node when the target node is new record.'); - $node = Tree::findOne(9); $node->insertBefore(new Tree()); } - public function testInsertBeforeExistsExceptionIsRaisedWhenTargetIsSame(): void + public function testThrowExceptionWhenInsertBeforeTargetIsSame(): void { $this->generateFixtureTree(); + $node = Tree::findOne(9); + + self::assertNotNull($node, 'Node with ID \'9\' should exist before calling \'insertBefore()\' on itself.'); + $this->expectException(Exception::class); $this->expectExceptionMessage('Can not move a node when the target node is same.'); - $node = Tree::findOne(9); - $node->insertBefore(Tree::findOne(9)); + $node->insertBefore($node); } - public function testInsertBeforeExistsExceptionIsRaisedWhenTargetIsChild(): void + public function testThrowExceptionWhenInsertBeforeTargetIsChild(): void { $this->generateFixtureTree(); + $node = Tree::findOne(9); + + self::assertNotNull( + $node, + 'Node with ID \'9\' must exist before calling \'insertBefore()\' on another node.', + ); + + $childOfNode = Tree::findOne(11); + + self::assertNotNull( + $childOfNode, + 'Target child node with ID \'11\' must exist before calling \'insertBefore()\' on it.', + ); + $this->expectException(Exception::class); $this->expectExceptionMessage('Can not move a node when the target node is child.'); - $node = Tree::findOne(9); - $node->insertBefore(Tree::findOne(11)); + $node->insertBefore($childOfNode); } - public function testInsertBeforeExistsExceptionIsRaisedWhenTargetIsRoot(): void + public function testThrowExceptionWhenInsertBeforeTargetIsRoot(): void { $this->generateFixtureTree(); + $node = Tree::findOne(9); + + self::assertNotNull( + $node, + 'Node with ID \'9\' should exist before calling \'insertBefore()\' on another node.', + ); + + $rootNode = Tree::findOne(1); + + self::assertNotNull( + $rootNode, + 'Root node with ID \'1\' should exist before calling \'insertBefore()\' on it.', + ); + $this->expectException(Exception::class); $this->expectExceptionMessage('Can not move a node when the target node is root.'); - $node = Tree::findOne(9); - $node->insertBefore(Tree::findOne(1)); + $node->insertBefore($rootNode); } - public function testInsertAfterExistsUp(): void + public function testReturnTrueAndMatchXmlAfterInsertAfterUpForTreeAndMultipleTree(): void { $this->generateFixtureTree(); $node = Tree::findOne(9); + + self::assertNotNull( + $node, + 'Node with ID \'9\' must exist before calling \'insertAfter()\' on another node.', + ); + $node->name = 'Updated node 2'; - $this->assertTrue($node->insertAfter(Tree::findOne(2))); + + $childOfNode = Tree::findOne(2); + + self::assertNotNull( + $childOfNode, + 'Target node with ID \'2\' must exist before calling \'insertAfter()\' on it.', + ); + self::assertTrue( + $node->insertAfter($childOfNode), + '\'insertAfter()\' should return \'true\' when moving node \'9\' after node \'2\' in \'Tree\'.', + ); $node = MultipleTree::findOne(31); + + self::assertNotNull( + $node, + 'Node with ID \'31\' must exist before calling \'insertAfter()\' on another node.', + ); + $node->name = 'Updated node 2'; - $this->assertTrue($node->insertAfter(MultipleTree::findOne(24))); - $this->assertEquals( + $childOfNode = MultipleTree::findOne(24); + + self::assertNotNull( + $childOfNode, + 'Target node with ID \'24\' must exist before calling \'insertAfter()\' on it.', + ); + self::assertTrue( + $node->insertAfter($childOfNode), + '\'insertAfter()\' should return \'true\' when moving node \'31\' after node \'24\' in \'MultipleTree\'.', + ); + + $fileXML = simplexml_load_file("{$this->fixtureDirectory}/test-insert-after-exists-up.xml"); + + self::assertNotFalse( + $fileXML, + 'XML file \'test-insert-after-exists-up.xml\' must be loaded successfully for result comparison.', + ); + self::assertEquals( $this->buildFlatXMLDataSet($this->getDataSet()), - simplexml_load_file(__DIR__ . '/Support/data/test-insert-after-exists-up.xml')->asXML(), + $fileXML->asXML(), + 'Resulting dataset after \'insertAfter()\' must match the expected XML structure.', ); } - public function testInsertAfterExistsDown(): void + public function testReturnTrueAndMatchXmlAfterInsertAfterDownForTreeAndMultipleTree(): void { $this->generateFixtureTree(); $node = Tree::findOne(9); + + self::assertNotNull( + $node, + 'Node with ID \'9\' should exist before calling \'insertAfter()\' on another node.', + ); + $node->name = 'Updated node 2'; - $this->assertTrue($node->insertAfter(Tree::findOne(16))); + + $childOfNode = Tree::findOne(16); + + self::assertNotNull( + $childOfNode, + 'Target node with ID \'16\' should exist before calling \'insertAfter()\' on it.', + ); + self::assertTrue( + $node->insertAfter($childOfNode), + '\'insertAfter()\' should return \'true\' when moving node \'9\' after node \'16\' in Tree.', + ); $node = MultipleTree::findOne(31); + + self::assertNotNull( + $node, + 'Node with ID \'31\' should exist before calling \'insertAfter()\' on another node.', + ); + $node->name = 'Updated node 2'; - $this->assertTrue($node->insertAfter(MultipleTree::findOne(38))); - $this->assertEquals( + $childOfNode = MultipleTree::findOne(38); + + self::assertNotNull( + $childOfNode, + 'Target node with ID \'38\' should exist before calling \'insertAfter()\' on it.', + ); + self::assertTrue( + $node->insertAfter($childOfNode), + '\'insertAfter()\' should return \'true\' when moving node \'31\' after node \'38\' in \'MultipleTree\'.', + ); + + $fileXML = simplexml_load_file("{$this->fixtureDirectory}/test-insert-after-exists-down.xml"); + + self::assertNotFalse( + $fileXML, + 'XML file \'test-insert-after-exists-down.xml\' should be loaded successfully for result comparison.', + ); + self::assertEquals( $this->buildFlatXMLDataSet($this->getDataSet()), - simplexml_load_file(__DIR__ . '/Support/data/test-insert-after-exists-down.xml')->asXML(), + $fileXML->asXML(), + 'Resulting dataset after \'insertAfter()\' must match the expected XML structure.', ); } - public function testInsertAfterExistsAnotherTree(): void + public function testReturnTrueAndMatchXmlAfterInsertAfterMultipleTreeWhenTargetIsInAnotherTree(): void { $this->generateFixtureTree(); $node = MultipleTree::findOne(9); + + self::assertNotNull( + $node, + 'Node with ID \'9\' must exist before attempting to insert after a node in another tree.', + ); + $node->name = 'Updated node 2'; - $this->assertTrue($node->insertAfter(MultipleTree::findOne(53))); - $this->assertEquals( + $childOfNode = MultipleTree::findOne(53); + + self::assertNotNull( + $childOfNode, + 'Target node with ID \'53\' must exist before attempting to insert after it.', + ); + self::assertTrue( + $node->insertAfter($childOfNode), + '\'insertAfter()\' should return \'true\' when moving node \'9\' after node \'53\' in another tree.', + ); + + $fileXML = simplexml_load_file("{$this->fixtureDirectory}/test-insert-after-exists-another-tree.xml"); + + self::assertNotFalse( + $fileXML, + 'XML file \'test-insert-after-exists-another-tree.xml\' must be loaded successfully for result comparison.', + ); + self::assertEquals( $this->buildFlatXMLDataSet($this->getDataSetMultipleTree()), - simplexml_load_file(__DIR__ . '/Support/data/test-insert-after-exists-another-tree.xml')->asXML(), + $fileXML->asXML(), + 'Resulting dataset after \'insertAfter()\' must match the expected XML structure for \'MultipleTree\'.', ); } - public function testInsertAfterExistsExceptionIsRaisedWhenTargetIsNewRecord(): void + public function testThrowExceptionWhenInsertAfterTargetIsNewRecord(): void { $this->generateFixtureTree(); + $node = Tree::findOne(9); + + self::assertNotNull($node, 'Node with ID \'9\' must exist before attempting to insert after a new record.'); + $this->expectException(Exception::class); $this->expectExceptionMessage('Can not move a node when the target node is new record.'); - $node = Tree::findOne(9); $node->insertAfter(new Tree()); } - public function testInsertAfterExistsExceptionIsRaisedWhenTargetIsSame(): void + public function testThrowExceptionWhenInsertAfterTargetIsSame(): void { $this->generateFixtureTree(); + $node = Tree::findOne(9); + + self::assertNotNull( + $node, + 'Node with ID \'9\' must exist before attempting to insert after itself.', + ); + $this->expectException(Exception::class); $this->expectExceptionMessage('Can not move a node when the target node is same.'); - $node = Tree::findOne(9); - $node->insertAfter(Tree::findOne(9)); + $node->insertAfter($node); } - public function testInsertAfterExistsExceptionIsRaisedWhenTargetIsChild(): void + public function testThrowExceptionWhenInsertAfterTargetIsChild(): void { $this->generateFixtureTree(); + $node = Tree::findOne(9); + + self::assertNotNull( + $node, + 'Node with ID \'9\' must exist before attempting to insert after its child node.', + ); + + $childOfNode = Tree::findOne(11); + + self::assertNotNull( + $childOfNode, + 'Child node with ID \'11\' must exist before attempting to insert after it.', + ); + $this->expectException(Exception::class); $this->expectExceptionMessage('Can not move a node when the target node is child.'); - $node = Tree::findOne(9); - $node->insertAfter(Tree::findOne(11)); + $node->insertAfter($childOfNode); } - public function testInsertAfterExistsExceptionIsRaisedWhenTargetIsRoot(): void + public function testThrowExceptionWhenInsertAfterTargetIsRoot(): void { $this->generateFixtureTree(); + $node = Tree::findOne(9); + + self::assertNotNull($node, 'Node with ID \'9\' should exist before attempting to insert after the root node.'); + + $rootNode = Tree::findOne(1); + + self::assertNotNull($rootNode, 'Root node with ID \'1\' should exist before attempting to insert after it.'); + $this->expectException(Exception::class); $this->expectExceptionMessage('Can not move a node when the target node is root.'); - $node = Tree::findOne(9); - $node->insertAfter(Tree::findOne(1)); + $node->insertAfter($rootNode); } - public function testDeleteWithChildren(): void + public function testReturnAffectedRowsAndMatchXmlAfterDeleteWithChildrenForTreeAndMultipleTree(): void { $this->generateFixtureTree(); - $this->assertEquals(7, Tree::findOne(9)->deleteWithChildren()); - $this->assertEquals(7, MultipleTree::findOne(31)->deleteWithChildren()); + self::assertEquals( + 7, + Tree::findOne(9)?->deleteWithChildren(), + 'Deleting node with ID \'9\' and its children from \'Tree\' should affect exactly seven rows.', + ); + self::assertEquals( + 7, + MultipleTree::findOne(31)?->deleteWithChildren(), + 'Deleting node with ID \'31\' and its children from \'MultipleTree\' should affect exactly seven rows.', + ); + + $fileXML = simplexml_load_file("{$this->fixtureDirectory}/test-delete-with-children.xml"); - $this->assertEquals( + self::assertNotFalse( + $fileXML, + 'XML file \'test-delete-with-children.xml\' should be loaded successfully.', + ); + self::assertEquals( $this->buildFlatXMLDataSet($this->getDataSet()), - simplexml_load_file(__DIR__ . '/Support/data/test-delete-with-children.xml')->asXML(), + $fileXML->asXML(), + 'The XML dataset after deleting nodes with children should match the expected result.', ); } - public function testDeleteWithChildrenExceptionIsRaisedWhenNodeIsNewRecord(): void + public function testThrowExceptionWhenDeleteWithChildrenIsCalledOnNewRecordNode(): void { $this->generateFixtureTree(); + $node = new Tree(); + $this->expectException(Exception::class); $this->expectExceptionMessage('Can not delete a node when it is new record.'); - $node = new Tree(); $node->deleteWithChildren(); } - public function testDelete(): void + public function testReturnOneWhenDeleteNodeForTreeAndMultipleTree(): void { $this->generateFixtureTree(); - $this->assertEquals(1, Tree::findOne(9)->delete()); - $this->assertEquals(1, MultipleTree::findOne(31)->delete()); + self::assertEquals( + 1, + Tree::findOne(9)?->delete(), + 'Deleting node with ID \'9\' from \'Tree\' should affect exactly one row.', + ); + self::assertEquals( + 1, + MultipleTree::findOne(31)?->delete(), + 'Deleting node with ID \'31\' from \'MultipleTree\' should affect exactly one row.', + ); + + $fileXML = simplexml_load_file("{$this->fixtureDirectory}/test-delete.xml"); - $this->assertEquals( + self::assertNotFalse( + $fileXML, + 'XML file \'test-delete.xml\' should be loaded successfully.', + ); + self::assertEquals( $this->buildFlatXMLDataSet($this->getDataSet()), - simplexml_load_file(__DIR__ . '/Support/data/test-delete.xml')->asXML(), + $fileXML->asXML(), + 'The XML dataset after deleting nodes should match the expected result.', ); } - public function testDeleteExceptionIsRaisedWhenNodeIsNewRecord(): void + public function testThrowExceptionWhenDeleteNodeIsNewRecord(): void { $this->generateFixtureTree(); + $node = new Tree(); + $this->expectException(Exception::class); $this->expectExceptionMessage('Can not delete a node when it is new record.'); - $node = new Tree(); $node->delete(); } - public function testDeleteExceptionIsRaisedWhenNodeIsRoot(): void + public function testThrowNotSupportedExceptionWhenDeleteIsCalledOnRootNode(): void { $this->generateFixtureTree(); + $node = Tree::findOne(1); + + self::assertNotNull( + $node, + 'Node with ID \'1\' should exist before attempting deletion.', + ); + $this->expectException(NotSupportedException::class); $this->expectExceptionMessage( - 'Method "Yii2\Extensions\NestedSets\Tests\Support\Model\Tree::delete" is not supported for deleting root nodes.', + 'Method "yii2\extensions\nestedsets\tests\support\model\Tree::delete" is not supported for deleting root nodes.', ); - $node = Tree::findOne(1); $node->delete(); } - public function testExceptionIsRaisedWhenInsertIsCalled(): void + public function testThrowNotSupportedExceptionWhenInsertIsCalledOnTree(): void { $this->generateFixtureTree(); + $node = new Tree(['name' => 'Node']); + $this->expectException(NotSupportedException::class); $this->expectExceptionMessage( - 'Method "Yii2\Extensions\NestedSets\Tests\Support\Model\Tree::insert" is not supported for inserting new nodes.', + 'Method "yii2\extensions\nestedsets\tests\support\model\Tree::insert" is not supported for inserting new nodes.', ); - $node = new Tree(['name' => 'Node']); $node->insert(); } - public function testUpdate(): void + public function testReturnOneWhenUpdateNodeName(): void { $this->generateFixtureTree(); $node = Tree::findOne(9); - $node->name = 'Updated node 2'; - $this->assertEquals(1, $node->update()); + + self::assertNotNull($node, 'Node with ID \'9\' should exist before attempting update.'); + + $node->name = 'Updated node'; + + self::assertEquals(1, $node->update(), 'Updating the node name should affect exactly one row.'); } - public function testParents(): void + public function testReturnParentsForTreeAndMultipleTreeWithAndWithoutDepth(): void { $this->generateFixtureTree(); - $this->assertEquals( - require(__DIR__ . '/Support/data/test-parents.php'), - ArrayHelper::toArray(Tree::findOne(11)->parents()->all()), + self::assertEquals( + require "{$this->fixtureDirectory}/test-parents.php", + ArrayHelper::toArray(Tree::findOne(11)?->parents()->all() ?? []), + 'Parents for \'Tree\' node with ID \'11\' do not match the expected result.', ); - - $this->assertEquals( - require(__DIR__ . '/Support/data/test-parents-multiple-tree.php'), - ArrayHelper::toArray(MultipleTree::findOne(33)->parents()->all()), + self::assertEquals( + require "{$this->fixtureDirectory}/test-parents-multiple-tree.php", + ArrayHelper::toArray(MultipleTree::findOne(33)?->parents()->all() ?? []), + 'Parents for \'MultipleTree\' node with ID \'33\' do not match the expected result.', ); - - $this->assertEquals( - require(__DIR__ . '/Support/data/test-parents-with-depth.php'), - ArrayHelper::toArray(Tree::findOne(11)->parents(1)->all()), + self::assertEquals( + require "{$this->fixtureDirectory}/test-parents-with-depth.php", + ArrayHelper::toArray(Tree::findOne(11)?->parents(1)->all() ?? []), + 'Parents with \'depth=1\' for \'Tree\' node with ID \'11\' do not match the expected result.', ); - - $this->assertEquals( - require(__DIR__ . '/Support/data/test-parents-multiple-tree-with-depth.php'), - ArrayHelper::toArray(MultipleTree::findOne(33)->parents(1)->all()), + self::assertEquals( + require "{$this->fixtureDirectory}/test-parents-multiple-tree-with-depth.php", + ArrayHelper::toArray(MultipleTree::findOne(33)?->parents(1)->all() ?? []), + 'Parents with \'depth=1\' for \'MultipleTree\' node with ID \'33\' do not match the expected result.', ); } - public function testChildren(): void + public function testReturnChildrenForTreeAndMultipleTreeWithAndWithoutDepth(): void { $this->generateFixtureTree(); - $this->assertEquals( - require(__DIR__ . '/Support/data/test-children.php'), - ArrayHelper::toArray(Tree::findOne(9)->children()->all()), + self::assertEquals( + require "{$this->fixtureDirectory}/test-children.php", + ArrayHelper::toArray(Tree::findOne(9)?->children()->all() ?? []), + 'Children for \'Tree\' node with ID \'9\' do not match the expected result.', ); - - $this->assertEquals( - require(__DIR__ . '/Support/data/test-children-multiple-tree.php'), - ArrayHelper::toArray(MultipleTree::findOne(31)->children()->all()), + self::assertEquals( + require "{$this->fixtureDirectory}/test-children-multiple-tree.php", + ArrayHelper::toArray(MultipleTree::findOne(31)?->children()->all() ?? []), + 'Children for \'MultipleTree\' node with ID \'31\' do not match the expected result.', ); - - $this->assertEquals( - require(__DIR__ . '/Support/data/test-children-with-depth.php'), - ArrayHelper::toArray(Tree::findOne(9)->children(1)->all()), + self::assertEquals( + require "{$this->fixtureDirectory}/test-children-with-depth.php", + ArrayHelper::toArray(Tree::findOne(9)?->children(1)->all() ?? []), + 'Children with \'depth=1\' for \'Tree\' node with ID \'9\' do not match the expected result.', ); - - $this->assertEquals( - require(__DIR__ . '/Support/data/test-children-multiple-tree-with-depth.php'), - ArrayHelper::toArray(MultipleTree::findOne(31)->children(1)->all()), + self::assertEquals( + require "{$this->fixtureDirectory}/test-children-multiple-tree-with-depth.php", + ArrayHelper::toArray(MultipleTree::findOne(31)?->children(1)->all() ?? []), + 'Children with \'depth=1\' for \'MultipleTree\' node with ID \'31\' do not match the expected result.', ); } - public function testLeaves(): void + public function testReturnLeavesForTreeAndMultipleTree(): void { $this->generateFixtureTree(); - $this->assertEquals( - require(__DIR__ . '/Support/data/test-leaves.php'), - ArrayHelper::toArray(Tree::findOne(9)->leaves()->all()), + self::assertEquals( + require "{$this->fixtureDirectory}/test-leaves.php", + ArrayHelper::toArray(Tree::findOne(9)?->leaves()->all() ?? []), + 'Leaves for \'Tree\' node with ID \'9\' do not match the expected result.', ); - - $this->assertEquals( - require(__DIR__ . '/Support/data/test-leaves-multiple-tree.php'), - ArrayHelper::toArray(MultipleTree::findOne(31)->leaves()->all()), + self::assertEquals( + require "{$this->fixtureDirectory}/test-leaves-multiple-tree.php", + ArrayHelper::toArray(MultipleTree::findOne(31)?->leaves()->all() ?? []), + 'Leaves for \'MultipleTree\' node with ID \'31\' do not match the expected result.', ); } - public function testPrev(): void + public function testReturnPrevNodesForTreeAndMultipleTree(): void { $this->generateFixtureTree(); - $this->assertEquals( - require(__DIR__ . '/Support/data/test-prev.php'), - ArrayHelper::toArray(Tree::findOne(9)->prev()->all()), + self::assertEquals( + require "{$this->fixtureDirectory}/test-prev.php", + ArrayHelper::toArray(Tree::findOne(9)?->prev()->all() ?? []), + 'Previous nodes for \'Tree\' node with ID \'9\' do not match the expected result.', ); - - $this->assertEquals( - require(__DIR__ . '/Support/data/test-prev-multiple-tree.php'), - ArrayHelper::toArray(MultipleTree::findOne(31)->prev()->all()), + self::assertEquals( + require "{$this->fixtureDirectory}/test-prev-multiple-tree.php", + ArrayHelper::toArray(MultipleTree::findOne(31)?->prev()->all() ?? []), + 'Previous nodes for \'MultipleTree\' node with ID \'31\' do not match the expected result.', ); } - public function testNext(): void + public function testReturnNextNodesForTreeAndMultipleTree(): void { $this->generateFixtureTree(); - $this->assertEquals( - require(__DIR__ . '/Support/data/test-next.php'), - ArrayHelper::toArray(Tree::findOne(9)->next()->all()), + self::assertEquals( + require "{$this->fixtureDirectory}/test-next.php", + ArrayHelper::toArray(Tree::findOne(9)?->next()->all() ?? []), + 'Next nodes for \'Tree\' node with ID \'9\' do not match the expected result.', ); - - $this->assertEquals( - require(__DIR__ . '/Support/data/test-next-multiple-tree.php'), - ArrayHelper::toArray(MultipleTree::findOne(31)->next()->all()), + self::assertEquals( + require "{$this->fixtureDirectory}/test-next-multiple-tree.php", + ArrayHelper::toArray(MultipleTree::findOne(31)?->next()->all() ?? []), + 'Next nodes for \'MultipleTree\' node with ID \'31\' do not match the expected result.', ); } - public function testIsRoot(): void + public function testReturnIsRootForRootAndNonRootNode(): void { $this->generateFixtureTree(); - $this->assertTrue(Tree::findOne(1)->isRoot()); - $this->assertFalse(Tree::findOne(2)->isRoot()); + self::assertTrue(Tree::findOne(1)?->isRoot(), 'Node with ID \'1\' should be identified as root.'); + self::assertFalse(Tree::findOne(2)?->isRoot(), 'Node with ID \'2\' should not be identified as root.'); } - public function testIsChildOf(): void + public function testReturnIsChildOfForMultipleTreeNodeUnderVariousAncestors(): void { $this->generateFixtureTree(); $node = MultipleTree::findOne(26); - $this->assertTrue($node->isChildOf(MultipleTree::findOne(25))); - $this->assertTrue($node->isChildOf(MultipleTree::findOne(23))); - $this->assertFalse($node->isChildOf(MultipleTree::findOne(3))); - $this->assertFalse($node->isChildOf(MultipleTree::findOne(1))); + self::assertNotNull( + $node, + 'Node with ID \'26\' should exist in the database.', + ); + self::assertNotNull( + $childOfNode = MultipleTree::findOne(25), + 'Node with ID \'25\' should exist in the database.', + ); + self::assertTrue( + $node->isChildOf($childOfNode), + 'Node with ID \'26\' should be a child of node with ID \'25\'.', + ); + self::assertNotNull( + $childOfNode = MultipleTree::findOne(23), + 'Node with ID \'23\' should exist in the database.', + ); + self::assertTrue( + $node->isChildOf($childOfNode), + 'Node with ID \'26\' should be a child of node with ID \'23\'.', + ); + self::assertNotNull( + $childOfNode = MultipleTree::findOne(3), + 'Node with ID \'3\' should exist in the database.', + ); + self::assertFalse( + $node->isChildOf($childOfNode), + 'Node with ID \'26\' should not be a child of node with ID \'3\'.', + ); + self::assertNotNull( + $childOfNode = MultipleTree::findOne(1), + 'Node with ID \'1\' should exist in the database.', + ); + self::assertFalse( + $node->isChildOf($childOfNode), + 'Node with ID \'26\' should not be a child of node with ID \'1\'.', + ); } - public function testIsLeaf(): void + public function testIsLeafReturnsTrueForLeafAndFalseForRoot(): void { $this->generateFixtureTree(); - $this->assertTrue(Tree::findOne(4)->isLeaf()); - $this->assertFalse(Tree::findOne(1)->isLeaf()); + self::assertTrue( + Tree::findOne(4)?->isLeaf(), + 'Node with ID \'4\' should be a leaf node (no children).', + ); + self::assertFalse( + Tree::findOne(1)?->isLeaf(), + 'Node with ID \'1\' should not be a leaf node (has children or is root).', + ); } } diff --git a/tests/NestedSetsQueryBehaviorTest.php b/tests/NestedSetsQueryBehaviorTest.php index 59b5245..d1808e1 100644 --- a/tests/NestedSetsQueryBehaviorTest.php +++ b/tests/NestedSetsQueryBehaviorTest.php @@ -2,41 +2,42 @@ declare(strict_types=1); -namespace Yii2\Extensions\NestedSets\Tests; +namespace yii2\extensions\nestedsets\tests; use yii\helpers\ArrayHelper; -use Yii2\Extensions\NestedSets\Tests\Support\Model\MultipleTree; -use Yii2\Extensions\NestedSets\Tests\Support\Model\Tree; +use yii2\extensions\nestedsets\tests\support\model\{MultipleTree, Tree}; final class NestedSetsQueryBehaviorTest extends TestCase { - public function testRoots(): void + public function testReturnLeavesForSingleAndMultipleTreeModels(): void { $this->generateFixtureTree(); - $this->assertEquals( - require(__DIR__ . '/Support/data/test-roots-query.php'), - ArrayHelper::toArray(Tree::find()->roots()->all()), + self::assertEquals( + require "{$this->fixtureDirectory}/test-leaves-query.php", + ArrayHelper::toArray(Tree::find()->leaves()->all()), + 'Should return correct leaf nodes for \'Tree\' model.', ); - - $this->assertEquals( - require(__DIR__ . '/Support/data/test-roots-multiple-tree-query.php'), - ArrayHelper::toArray(MultipleTree::find()->roots()->all()), + self::assertEquals( + require "{$this->fixtureDirectory}/test-leaves-multiple-tree-query.php", + ArrayHelper::toArray(MultipleTree::find()->leaves()->all()), + 'Should return correct leaf nodes for \'MultipleTree\' model.', ); } - public function testLeaves(): void + public function testReturnRootsForSingleAndMultipleTreeModels(): void { $this->generateFixtureTree(); - $this->assertEquals( - require(__DIR__ . '/Support/data/test-leaves-query.php'), - ArrayHelper::toArray(Tree::find()->leaves()->all()), + self::assertEquals( + require "{$this->fixtureDirectory}/test-roots-query.php", + ArrayHelper::toArray(Tree::find()->roots()->all()), + 'Should return correct root nodes for \'Tree\' model.', ); - - $this->assertEquals( - require(__DIR__ . '/Support/data/test-leaves-multiple-tree-query.php'), - ArrayHelper::toArray(MultipleTree::find()->leaves()->all()), + self::assertEquals( + require "{$this->fixtureDirectory}//test-roots-multiple-tree-query.php", + ArrayHelper::toArray(MultipleTree::find()->roots()->all()), + 'Should return correct root nodes for \'MultipleTree\' model.', ); } } diff --git a/tests/Support/Model/MultipleTreeQuery.php b/tests/Support/Model/MultipleTreeQuery.php deleted file mode 100644 index bb59aea..0000000 --- a/tests/Support/Model/MultipleTreeQuery.php +++ /dev/null @@ -1,17 +0,0 @@ -getDb(); } + /** + * @phpstan-param array< + * array{id: int, name: string, tree: int, type: string, lft: int, rgt: int, depth: int, name: string} + * > $dataSet + */ protected function buildFlatXMLDataSet(array $dataSet): string { $xml = new SimpleXMLElement(''); foreach ($dataSet as $item) { $treeElement = $xml->addChild($item['type']); - $treeElement->addAttribute('id', $item['id']); + $treeElement?->addAttribute('id', (string) $item['id']); if ($item['type'] === 'multiple_tree') { - $treeElement->addAttribute('tree', $item['tree']); + $treeElement?->addAttribute('tree', (string) $item['tree']); } - $treeElement->addAttribute('lft', $item['lft']); - $treeElement->addAttribute('rgt', $item['rgt']); - $treeElement->addAttribute('depth', $item['depth']); - $treeElement->addAttribute('name', $item['name']); + $treeElement?->addAttribute('lft', (string) $item['lft']); + $treeElement?->addAttribute('rgt', (string) $item['rgt']); + $treeElement?->addAttribute('depth', (string) $item['depth']); + $treeElement?->addAttribute('name', $item['name']); } $dom = dom_import_simplexml($xml)->ownerDocument; + + assert($dom !== null, 'Failed to create DOM from SimpleXMLElement.'); + $dom->formatOutput = true; $formattedXml = $dom->saveXML(); + assert($formattedXml !== false, 'Failed to save XML from DOM.'); + // Replace the tags with 4 spaces return str_replace(['execute(); } - protected function destroyApplication() - { - Yii::$app = null; - Yii::$container = new Container(); - } - + /** + * @phpstan-return list< + * array{ + * id: int, + * name: string, + * tree: int, + * type: string, + * lft: int, + * rgt: int, + * depth: int + * } + * > + */ protected function getDataSet(): array { $dataSetTree = Tree::find()->asArray()->all(); foreach ($dataSetTree as $key => $value) { $dataSetTree[$key]['type'] = 'tree'; + $dataSetTree[$key]['tree'] = 0; } $dataSetMultipleTree = MultipleTree::find()->asArray()->all(); @@ -107,6 +122,19 @@ protected function getDataSet(): array return array_merge($dataSetTree, $dataSetMultipleTree); } + /** + * @phpstan-return list< + * array{ + * id: int, + * name: string, + * tree: int, + * type: 'multiple_tree', + * lft: int, + * rgt: int, + * depth: int, + * } + * > + */ protected function getDataSetMultipleTree(): array { $dataSetMultipleTree = MultipleTree::find()->asArray()->all(); @@ -115,7 +143,7 @@ protected function getDataSetMultipleTree(): array $dataSetMultipleTree[$key]['type'] = 'multiple_tree'; } - return $dataSetMultipleTree; + return array_values($dataSetMultipleTree); } protected function generateFixtureTree(): void @@ -127,7 +155,9 @@ protected function generateFixtureTree(): void // Carga el XML en la tabla `tree` $xml = new SimpleXMLElement(__DIR__ . '/Support/data/test.xml', 0, true); - foreach ($xml->children() as $element => $treeElement) { + $children = $xml->children() ?? []; + + foreach ($children as $element => $treeElement) { match ($element === 'tree') { true => $command->insert( 'tree', @@ -168,7 +198,7 @@ protected function mockConsoleApplication(): void ); } - protected function setup(): void + protected function setUp(): void { parent::setUp(); $this->mockConsoleApplication(); @@ -177,6 +207,5 @@ protected function setup(): void protected function tearDown(): void { parent::tearDown(); - $this->destroyApplication(); } } diff --git a/tests/config/phpstan-config.php b/tests/config/phpstan-config.php deleted file mode 100644 index 6de3e1d..0000000 --- a/tests/config/phpstan-config.php +++ /dev/null @@ -1,19 +0,0 @@ - [ - ActiveRecord::class => [ - NestedSetsBehavior::class, - ], - ActiveQuery::class => [ - NestedSetsQueryBehavior::class, - ], - ], -]; diff --git a/tests/phpstan-config.php b/tests/phpstan-config.php index 53614ab..80f2b65 100644 --- a/tests/phpstan-config.php +++ b/tests/phpstan-config.php @@ -3,7 +3,8 @@ declare(strict_types=1); use yii\db\{ActiveQuery, ActiveRecord}; -use Yii2\Extensions\NestedSets\{NestedSetsBehavior, NestedSetsQueryBehavior}; +use yii2\extensions\nestedsets\{NestedSetsBehavior, NestedSetsQueryBehavior}; +use yii2\extensions\nestedsets\tests\support\model\{MultipleTree, MultipleTreeQuery, Tree, TreeQuery}; return [ 'behaviors' => [ @@ -13,5 +14,17 @@ ActiveQuery::class => [ NestedSetsQueryBehavior::class, ], + MultipleTree::class => [ + NestedSetsBehavior::class, + ], + MultipleTreeQuery::class => [ + NestedSetsQueryBehavior::class, + ], + Tree::class => [ + NestedSetsBehavior::class, + ], + TreeQuery::class => [ + NestedSetsQueryBehavior::class, + ], ], ]; diff --git a/tests/Support/data/clean.xml b/tests/support/data/clean.xml similarity index 100% rename from tests/Support/data/clean.xml rename to tests/support/data/clean.xml diff --git a/tests/Support/data/test-append-to-exists-another-tree.xml b/tests/support/data/test-append-to-exists-another-tree.xml similarity index 100% rename from tests/Support/data/test-append-to-exists-another-tree.xml rename to tests/support/data/test-append-to-exists-another-tree.xml diff --git a/tests/Support/data/test-append-to-exists-down.xml b/tests/support/data/test-append-to-exists-down.xml similarity index 100% rename from tests/Support/data/test-append-to-exists-down.xml rename to tests/support/data/test-append-to-exists-down.xml diff --git a/tests/Support/data/test-append-to-exists-up.xml b/tests/support/data/test-append-to-exists-up.xml similarity index 100% rename from tests/Support/data/test-append-to-exists-up.xml rename to tests/support/data/test-append-to-exists-up.xml diff --git a/tests/Support/data/test-append-to-new.xml b/tests/support/data/test-append-to-new.xml similarity index 100% rename from tests/Support/data/test-append-to-new.xml rename to tests/support/data/test-append-to-new.xml diff --git a/tests/Support/data/test-children-multiple-tree-with-depth.php b/tests/support/data/test-children-multiple-tree-with-depth.php similarity index 100% rename from tests/Support/data/test-children-multiple-tree-with-depth.php rename to tests/support/data/test-children-multiple-tree-with-depth.php diff --git a/tests/Support/data/test-children-multiple-tree.php b/tests/support/data/test-children-multiple-tree.php similarity index 100% rename from tests/Support/data/test-children-multiple-tree.php rename to tests/support/data/test-children-multiple-tree.php diff --git a/tests/Support/data/test-children-with-depth.php b/tests/support/data/test-children-with-depth.php similarity index 100% rename from tests/Support/data/test-children-with-depth.php rename to tests/support/data/test-children-with-depth.php diff --git a/tests/Support/data/test-children.php b/tests/support/data/test-children.php similarity index 100% rename from tests/Support/data/test-children.php rename to tests/support/data/test-children.php diff --git a/tests/Support/data/test-delete-with-children.xml b/tests/support/data/test-delete-with-children.xml similarity index 100% rename from tests/Support/data/test-delete-with-children.xml rename to tests/support/data/test-delete-with-children.xml diff --git a/tests/Support/data/test-delete.xml b/tests/support/data/test-delete.xml similarity index 100% rename from tests/Support/data/test-delete.xml rename to tests/support/data/test-delete.xml diff --git a/tests/Support/data/test-insert-after-exists-another-tree.xml b/tests/support/data/test-insert-after-exists-another-tree.xml similarity index 100% rename from tests/Support/data/test-insert-after-exists-another-tree.xml rename to tests/support/data/test-insert-after-exists-another-tree.xml diff --git a/tests/Support/data/test-insert-after-exists-down.xml b/tests/support/data/test-insert-after-exists-down.xml similarity index 100% rename from tests/Support/data/test-insert-after-exists-down.xml rename to tests/support/data/test-insert-after-exists-down.xml diff --git a/tests/Support/data/test-insert-after-exists-up.xml b/tests/support/data/test-insert-after-exists-up.xml similarity index 100% rename from tests/Support/data/test-insert-after-exists-up.xml rename to tests/support/data/test-insert-after-exists-up.xml diff --git a/tests/Support/data/test-insert-after-new.xml b/tests/support/data/test-insert-after-new.xml similarity index 100% rename from tests/Support/data/test-insert-after-new.xml rename to tests/support/data/test-insert-after-new.xml diff --git a/tests/Support/data/test-insert-before-exists-another-tree.xml b/tests/support/data/test-insert-before-exists-another-tree.xml similarity index 100% rename from tests/Support/data/test-insert-before-exists-another-tree.xml rename to tests/support/data/test-insert-before-exists-another-tree.xml diff --git a/tests/Support/data/test-insert-before-exists-down.xml b/tests/support/data/test-insert-before-exists-down.xml similarity index 100% rename from tests/Support/data/test-insert-before-exists-down.xml rename to tests/support/data/test-insert-before-exists-down.xml diff --git a/tests/Support/data/test-insert-before-exists-up.xml b/tests/support/data/test-insert-before-exists-up.xml similarity index 100% rename from tests/Support/data/test-insert-before-exists-up.xml rename to tests/support/data/test-insert-before-exists-up.xml diff --git a/tests/Support/data/test-insert-before-new.xml b/tests/support/data/test-insert-before-new.xml similarity index 100% rename from tests/Support/data/test-insert-before-new.xml rename to tests/support/data/test-insert-before-new.xml diff --git a/tests/Support/data/test-leaves-multiple-tree-query.php b/tests/support/data/test-leaves-multiple-tree-query.php similarity index 100% rename from tests/Support/data/test-leaves-multiple-tree-query.php rename to tests/support/data/test-leaves-multiple-tree-query.php diff --git a/tests/Support/data/test-leaves-multiple-tree.php b/tests/support/data/test-leaves-multiple-tree.php similarity index 100% rename from tests/Support/data/test-leaves-multiple-tree.php rename to tests/support/data/test-leaves-multiple-tree.php diff --git a/tests/Support/data/test-leaves-query.php b/tests/support/data/test-leaves-query.php similarity index 100% rename from tests/Support/data/test-leaves-query.php rename to tests/support/data/test-leaves-query.php diff --git a/tests/Support/data/test-leaves.php b/tests/support/data/test-leaves.php similarity index 100% rename from tests/Support/data/test-leaves.php rename to tests/support/data/test-leaves.php diff --git a/tests/Support/data/test-make-root-exists.xml b/tests/support/data/test-make-root-exists.xml similarity index 100% rename from tests/Support/data/test-make-root-exists.xml rename to tests/support/data/test-make-root-exists.xml diff --git a/tests/Support/data/test-make-root-new.xml b/tests/support/data/test-make-root-new.xml similarity index 100% rename from tests/Support/data/test-make-root-new.xml rename to tests/support/data/test-make-root-new.xml diff --git a/tests/Support/data/test-next-multiple-tree.php b/tests/support/data/test-next-multiple-tree.php similarity index 100% rename from tests/Support/data/test-next-multiple-tree.php rename to tests/support/data/test-next-multiple-tree.php diff --git a/tests/Support/data/test-next.php b/tests/support/data/test-next.php similarity index 100% rename from tests/Support/data/test-next.php rename to tests/support/data/test-next.php diff --git a/tests/Support/data/test-parents-multiple-tree-with-depth.php b/tests/support/data/test-parents-multiple-tree-with-depth.php similarity index 100% rename from tests/Support/data/test-parents-multiple-tree-with-depth.php rename to tests/support/data/test-parents-multiple-tree-with-depth.php diff --git a/tests/Support/data/test-parents-multiple-tree.php b/tests/support/data/test-parents-multiple-tree.php similarity index 100% rename from tests/Support/data/test-parents-multiple-tree.php rename to tests/support/data/test-parents-multiple-tree.php diff --git a/tests/Support/data/test-parents-with-depth.php b/tests/support/data/test-parents-with-depth.php similarity index 100% rename from tests/Support/data/test-parents-with-depth.php rename to tests/support/data/test-parents-with-depth.php diff --git a/tests/Support/data/test-parents.php b/tests/support/data/test-parents.php similarity index 100% rename from tests/Support/data/test-parents.php rename to tests/support/data/test-parents.php diff --git a/tests/Support/data/test-prepend-to-exists-another-tree.xml b/tests/support/data/test-prepend-to-exists-another-tree.xml similarity index 100% rename from tests/Support/data/test-prepend-to-exists-another-tree.xml rename to tests/support/data/test-prepend-to-exists-another-tree.xml diff --git a/tests/Support/data/test-prepend-to-exists-down.xml b/tests/support/data/test-prepend-to-exists-down.xml similarity index 100% rename from tests/Support/data/test-prepend-to-exists-down.xml rename to tests/support/data/test-prepend-to-exists-down.xml diff --git a/tests/Support/data/test-prepend-to-exists-up.xml b/tests/support/data/test-prepend-to-exists-up.xml similarity index 100% rename from tests/Support/data/test-prepend-to-exists-up.xml rename to tests/support/data/test-prepend-to-exists-up.xml diff --git a/tests/Support/data/test-prepend-to-new.xml b/tests/support/data/test-prepend-to-new.xml similarity index 100% rename from tests/Support/data/test-prepend-to-new.xml rename to tests/support/data/test-prepend-to-new.xml diff --git a/tests/Support/data/test-prev-multiple-tree.php b/tests/support/data/test-prev-multiple-tree.php similarity index 100% rename from tests/Support/data/test-prev-multiple-tree.php rename to tests/support/data/test-prev-multiple-tree.php diff --git a/tests/Support/data/test-prev.php b/tests/support/data/test-prev.php similarity index 100% rename from tests/Support/data/test-prev.php rename to tests/support/data/test-prev.php diff --git a/tests/Support/data/test-roots-multiple-tree-query.php b/tests/support/data/test-roots-multiple-tree-query.php similarity index 100% rename from tests/Support/data/test-roots-multiple-tree-query.php rename to tests/support/data/test-roots-multiple-tree-query.php diff --git a/tests/Support/data/test-roots-query.php b/tests/support/data/test-roots-query.php similarity index 100% rename from tests/Support/data/test-roots-query.php rename to tests/support/data/test-roots-query.php diff --git a/tests/Support/data/test.xml b/tests/support/data/test.xml similarity index 100% rename from tests/Support/data/test.xml rename to tests/support/data/test.xml diff --git a/tests/Support/Model/MultipleTree.php b/tests/support/model/MultipleTree.php similarity index 58% rename from tests/Support/Model/MultipleTree.php rename to tests/support/model/MultipleTree.php index 930798c..23a876c 100644 --- a/tests/Support/Model/MultipleTree.php +++ b/tests/support/model/MultipleTree.php @@ -2,26 +2,27 @@ declare(strict_types=1); -namespace Yii2\Extensions\NestedSets\Tests\Support\Model; +namespace yii2\extensions\nestedsets\tests\support\model; -use Yii2\Extensions\NestedSets\NestedSetsBehavior; +use yii\db\ActiveRecord; +use yii2\extensions\nestedsets\NestedSetsBehavior; /** * @property int $id - * @property int $tree + * @property int $depth * @property int $lft * @property int $rgt - * @property int $depth + * @property int $tree * @property string $name */ -final class MultipleTree extends \yii\db\ActiveRecord +final class MultipleTree extends ActiveRecord { public static function tableName() { return '{{%multiple_tree}}'; } - public function behaviors() + public function behaviors(): array { return [ [ @@ -31,21 +32,27 @@ public function behaviors() ]; } - public function rules() + public function rules(): array { return [ ['name', 'required'], ]; } - public function transactions() + /** + * @phpstan-return array + */ + public function transactions(): array { return [ self::SCENARIO_DEFAULT => self::OP_ALL, ]; } - public static function find() + /** + * @phpstan-return MultipleTreeQuery + */ + public static function find(): MultipleTreeQuery { return new MultipleTreeQuery(self::class); } diff --git a/tests/support/model/MultipleTreeQuery.php b/tests/support/model/MultipleTreeQuery.php new file mode 100644 index 0000000..bdc79bf --- /dev/null +++ b/tests/support/model/MultipleTreeQuery.php @@ -0,0 +1,22 @@ + + */ +final class MultipleTreeQuery extends ActiveQuery +{ + public function behaviors(): array + { + return [ + NestedSetsQueryBehavior::class, + ]; + } +} diff --git a/tests/Support/Model/Tree.php b/tests/support/model/Tree.php similarity index 50% rename from tests/Support/Model/Tree.php rename to tests/support/model/Tree.php index e5bb7f6..cc078ff 100644 --- a/tests/Support/Model/Tree.php +++ b/tests/support/model/Tree.php @@ -2,9 +2,10 @@ declare(strict_types=1); -namespace Yii2\Extensions\NestedSets\Tests\Support\Model; +namespace yii2\extensions\nestedsets\tests\support\model; -use Yii2\Extensions\NestedSets\NestedSetsBehavior; +use yii\db\ActiveRecord; +use yii2\extensions\nestedsets\NestedSetsBehavior; /** * @property int $id @@ -13,35 +14,41 @@ * @property int $depth * @property string $name */ -final class Tree extends \yii\db\ActiveRecord +final class Tree extends ActiveRecord { - public static function tableName() + public static function tableName(): string { return '{{%tree}}'; } - public function behaviors() + public function behaviors(): array { return [ NestedSetsBehavior::class, ]; } - public function rules() + public function rules(): array { return [ ['name', 'required'], ]; } - public function transactions() + /** + * @phpstan-return array + */ + public function transactions(): array { return [ self::SCENARIO_DEFAULT => self::OP_ALL, ]; } - public static function find() + /** + * @phpstan-return TreeQuery + */ + public static function find(): TreeQuery { return new TreeQuery(self::class); } diff --git a/tests/support/model/TreeQuery.php b/tests/support/model/TreeQuery.php new file mode 100644 index 0000000..df4b219 --- /dev/null +++ b/tests/support/model/TreeQuery.php @@ -0,0 +1,22 @@ + + */ +final class TreeQuery extends ActiveQuery +{ + public function behaviors(): array + { + return [ + NestedSetsQueryBehavior::class, + ]; + } +} From 6e7f527778bf0fdc5fa362e7e9f24329303ae893 Mon Sep 17 00:00:00 2001 From: StyleCI Bot Date: Fri, 27 Jun 2025 16:56:40 +0000 Subject: [PATCH 2/8] Apply fixes from StyleCI --- src/NestedSetsBehavior.php | 1 + src/NestedSetsQueryBehavior.php | 1 + tests/TestCase.php | 1 + tests/support/model/MultipleTreeQuery.php | 1 + tests/support/model/TreeQuery.php | 1 + 5 files changed, 5 insertions(+) diff --git a/src/NestedSetsBehavior.php b/src/NestedSetsBehavior.php index 86aa536..fd25857 100644 --- a/src/NestedSetsBehavior.php +++ b/src/NestedSetsBehavior.php @@ -31,6 +31,7 @@ * - Supports custom attribute names for left, right, depth, and tree columns. * * @phpstan-template T of ActiveRecord + * * @phpstan-extends Behavior * * @property int $depth diff --git a/src/NestedSetsQueryBehavior.php b/src/NestedSetsQueryBehavior.php index da87964..30f49cd 100644 --- a/src/NestedSetsQueryBehavior.php +++ b/src/NestedSetsQueryBehavior.php @@ -27,6 +27,7 @@ * - Supports custom left, right, and tree attribute names as defined in the model. * * @phpstan-template T of ActiveQuery + * * @phpstan-extends Behavior * * @copyright Copyright (C) 2023 Terabytesoftw. diff --git a/tests/TestCase.php b/tests/TestCase.php index fa48b1a..b050724 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -14,6 +14,7 @@ class TestCase extends \PHPUnit\Framework\TestCase { use SchemaBuilderTrait; protected string $fixtureDirectory = __DIR__ . '/support/data/'; + public function getDb(): Connection { return Yii::$app->getDb(); diff --git a/tests/support/model/MultipleTreeQuery.php b/tests/support/model/MultipleTreeQuery.php index bdc79bf..18602fc 100644 --- a/tests/support/model/MultipleTreeQuery.php +++ b/tests/support/model/MultipleTreeQuery.php @@ -9,6 +9,7 @@ /** * @template T of MultipleTree + * * @extends ActiveQuery */ final class MultipleTreeQuery extends ActiveQuery diff --git a/tests/support/model/TreeQuery.php b/tests/support/model/TreeQuery.php index df4b219..b2c529a 100644 --- a/tests/support/model/TreeQuery.php +++ b/tests/support/model/TreeQuery.php @@ -9,6 +9,7 @@ /** * @template T of Tree + * * @extends ActiveQuery */ final class TreeQuery extends ActiveQuery From a2910d08959f636c69b38fcd4b72aa53d370c250 Mon Sep 17 00:00:00 2001 From: Wilmer Arambula Date: Fri, 27 Jun 2025 12:59:37 -0400 Subject: [PATCH 3/8] fix: Update XML file path in TestCase to use fixture directory. --- tests/TestCase.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/TestCase.php b/tests/TestCase.php index b050724..c8aa159 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -154,7 +154,7 @@ protected function generateFixtureTree(): void $command = $this->getDb()->createCommand(); // Carga el XML en la tabla `tree` - $xml = new SimpleXMLElement(__DIR__ . '/Support/data/test.xml', 0, true); + $xml = new SimpleXMLElement("{$this->fixtureDirectory}/test.xml", 0, true); $children = $xml->children() ?? []; From 595f70fd594b1019495ade9cc71a65940aac4318 Mon Sep 17 00:00:00 2001 From: Wilmer Arambula Date: Fri, 27 Jun 2025 13:03:08 -0400 Subject: [PATCH 4/8] fix: Correct file path in `NestedSetsQueryBehaviorTest` for multiple tree roots query. --- tests/NestedSetsQueryBehaviorTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/NestedSetsQueryBehaviorTest.php b/tests/NestedSetsQueryBehaviorTest.php index d1808e1..a3f3fcf 100644 --- a/tests/NestedSetsQueryBehaviorTest.php +++ b/tests/NestedSetsQueryBehaviorTest.php @@ -35,7 +35,7 @@ public function testReturnRootsForSingleAndMultipleTreeModels(): void 'Should return correct root nodes for \'Tree\' model.', ); self::assertEquals( - require "{$this->fixtureDirectory}//test-roots-multiple-tree-query.php", + require "{$this->fixtureDirectory}/test-roots-multiple-tree-query.php", ArrayHelper::toArray(MultipleTree::find()->roots()->all()), 'Should return correct root nodes for \'MultipleTree\' model.', ); From dbaf0c8cb2490dc5cd23bda33d0b9daec41f919a Mon Sep 17 00:00:00 2001 From: Wilmer Arambula Date: Fri, 27 Jun 2025 16:44:41 -0400 Subject: [PATCH 5/8] fix: Refactor XML dataset handling in `TestCase` for improved error handling and code clarity. --- tests/TestCase.php | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/tests/TestCase.php b/tests/TestCase.php index c8aa159..88db333 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -4,12 +4,18 @@ namespace yii2\extensions\nestedsets\tests; +use RuntimeException; use SimpleXMLElement; use Yii; use yii\console\Application; use yii\db\{Connection, SchemaBuilderTrait}; use yii2\extensions\nestedsets\tests\support\model\{MultipleTree, Tree}; +use function array_merge; +use function array_values; +use function dom_import_simplexml; +use function str_replace; + class TestCase extends \PHPUnit\Framework\TestCase { use SchemaBuilderTrait; @@ -22,7 +28,7 @@ public function getDb(): Connection /** * @phpstan-param array< - * array{id: int, name: string, tree: int, type: string, lft: int, rgt: int, depth: int, name: string} + * array{id: int, name: string, tree: int, type: string, lft: int, rgt: int, depth: int} * > $dataSet */ protected function buildFlatXMLDataSet(array $dataSet): string @@ -45,15 +51,26 @@ protected function buildFlatXMLDataSet(array $dataSet): string $dom = dom_import_simplexml($xml)->ownerDocument; - assert($dom !== null, 'Failed to create DOM from SimpleXMLElement.'); + if ($dom === null) { + throw new RuntimeException('Failed to create DOM from SimpleXMLElement.'); + } $dom->formatOutput = true; $formattedXml = $dom->saveXML(); - assert($formattedXml !== false, 'Failed to save XML from DOM.'); + if ($formattedXml === false) { + throw new RuntimeException('Failed to save XML from DOM.'); + } // Replace the tags with 4 spaces - return str_replace(['mockConsoleApplication(); - } - protected function tearDown(): void - { - parent::tearDown(); + $this->mockConsoleApplication(); } } From 7b4b3902097845f18a89185cc54747552c77026d Mon Sep 17 00:00:00 2001 From: StyleCI Bot Date: Fri, 27 Jun 2025 20:45:18 +0000 Subject: [PATCH 6/8] Apply fixes from StyleCI --- tests/TestCase.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/TestCase.php b/tests/TestCase.php index 88db333..c1bb246 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -63,8 +63,9 @@ protected function buildFlatXMLDataSet(array $dataSet): string } // Replace the tags with 4 spaces - return str_replace([ - ' Date: Fri, 27 Jun 2025 16:50:38 -0400 Subject: [PATCH 7/8] fix: Add return type declaration to `tableName` method in `MultipleTree` class. --- tests/support/model/MultipleTree.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/support/model/MultipleTree.php b/tests/support/model/MultipleTree.php index 23a876c..6e1f84f 100644 --- a/tests/support/model/MultipleTree.php +++ b/tests/support/model/MultipleTree.php @@ -17,7 +17,7 @@ */ final class MultipleTree extends ActiveRecord { - public static function tableName() + public static function tableName(): string { return '{{%multiple_tree}}'; } From 867e39c57a122b07807f06f8f45d40eb54b50783 Mon Sep 17 00:00:00 2001 From: Wilmer Arambula Date: Fri, 27 Jun 2025 17:00:17 -0400 Subject: [PATCH 8/8] fix: Update `PHPStan` type annotations in `TestCase` for improved type safety and clarity. --- tests/TestCase.php | 48 ++++++++++++++++++++++------------------------ 1 file changed, 23 insertions(+), 25 deletions(-) diff --git a/tests/TestCase.php b/tests/TestCase.php index c1bb246..06f85d7 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -16,9 +16,23 @@ use function dom_import_simplexml; use function str_replace; +/** + * @phpstan-type DataSetType = list< + * array{ + * id: int, + * name: string, + * tree: int, + * type: 'multiple_tree'|'tree', + * lft: int, + * rgt: int, + * depth: int, + * } + * > + */ class TestCase extends \PHPUnit\Framework\TestCase { use SchemaBuilderTrait; + protected string $fixtureDirectory = __DIR__ . '/support/data/'; public function getDb(): Connection @@ -27,9 +41,9 @@ public function getDb(): Connection } /** - * @phpstan-param array< - * array{id: int, name: string, tree: int, type: string, lft: int, rgt: int, depth: int} - * > $dataSet + * @phpstan-import-type DataSetType from TestCase + * + * @phpstan-param DataSetType $dataSet */ protected function buildFlatXMLDataSet(array $dataSet): string { @@ -111,17 +125,9 @@ protected function createDatabase(): void } /** - * @phpstan-return list< - * array{ - * id: int, - * name: string, - * tree: int, - * type: string, - * lft: int, - * rgt: int, - * depth: int - * } - * > + * @phpstan-import-type DataSetType from TestCase + * + * @phpstan-return DataSetType */ protected function getDataSet(): array { @@ -142,17 +148,9 @@ protected function getDataSet(): array } /** - * @phpstan-return list< - * array{ - * id: int, - * name: string, - * tree: int, - * type: 'multiple_tree', - * lft: int, - * rgt: int, - * depth: int, - * } - * > + * @phpstan-import-type DataSetType from TestCase + * + * @phpstan-return DataSetType */ protected function getDataSetMultipleTree(): array {