Skip to content

Commit bab0185

Browse files
feat: Update composer.json to require ext-dom and enhance TestCase.php with improved documentation and structure. (#78)
1 parent c1ca443 commit bab0185

File tree

2 files changed

+119
-22
lines changed

2 files changed

+119
-22
lines changed

composer.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
"yiisoft/yii2": "^2.0.53|^22"
1515
},
1616
"require-dev": {
17+
"ext-dom": "*",
1718
"ext-simplexml": "*",
1819
"infection/infection": "^0.27|^0.30",
1920
"maglnet/composer-require-checker": "^4.1",

tests/TestCase.php

Lines changed: 118 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -7,21 +7,47 @@
77
use RuntimeException;
88
use SimpleXMLElement;
99
use Yii;
10-
use yii\base\InvalidArgumentException;
10+
use yii\base\{InvalidArgumentException, InvalidConfigException};
1111
use yii\console\Application;
12-
use yii\db\{ActiveQuery, ActiveRecord, Connection, Query, SchemaBuilderTrait};
12+
use yii\db\{ActiveQuery, ActiveRecord, Connection, Exception, SchemaBuilderTrait};
1313
use yii2\extensions\nestedsets\tests\support\model\{MultipleTree, Tree};
1414
use yii2\extensions\nestedsets\tests\support\stub\EchoMigrateController;
1515

1616
use function array_merge;
1717
use function array_values;
18+
use function dirname;
1819
use function dom_import_simplexml;
1920
use function file_get_contents;
21+
use function is_int;
22+
use function is_string;
23+
use function ob_get_clean;
24+
use function ob_implicit_flush;
25+
use function ob_start;
2026
use function preg_replace;
2127
use function simplexml_load_string;
2228
use function str_replace;
2329

2430
/**
31+
* Base test case for nested sets behavior test suites.
32+
*
33+
* Provides common setup, database management, fixture loading, and assertion utilities for all nested sets tests.
34+
*
35+
* This class centralizes logic for initializing the test environment, managing database state, and verifying tree
36+
* structures, ensuring consistency and reducing duplication across test cases for different database drivers and
37+
* scenarios.
38+
*
39+
* Key features.
40+
* - Assertion helpers for validating node order and query structure.
41+
* - Integration with custom migration and schema management.
42+
* - Shared database connection and fixture directory configuration.
43+
* - Support for both single-tree and multi-tree models.
44+
* - Utilities for creating, resetting, and populating test databases.
45+
* - XML fixture generation and loading for reproducible test data.
46+
*
47+
* @see EchoMigrateController for migration handling.
48+
* @see MultipleTree for multi-tree model.
49+
* @see Tree for single-tree model.
50+
*
2551
* @phpstan-type DataSetType = list<
2652
* array{
2753
* id: int,
@@ -36,35 +62,42 @@
3662
* @phpstan-type NodeChildren array<string|array{name: string, children?: array<mixed>}>
3763
* @phpstan-type TreeStructure array<array<mixed>>
3864
* @phpstan-type UpdateData array<array{name: string, lft?: int, rgt?: int, depth?: int}>
65+
*
66+
* @copyright Copyright (C) 2023 Terabytesoftw.
67+
* @license https://opensource.org/license/bsd-3-clause BSD 3-Clause License.
3968
*/
40-
class TestCase extends \PHPUnit\Framework\TestCase
69+
abstract class TestCase extends \PHPUnit\Framework\TestCase
4170
{
4271
use SchemaBuilderTrait;
4372

4473
/**
74+
* Database connection configuration.
75+
*
4576
* @phpstan-var string[]
4677
*/
4778
protected array $connection = [];
79+
80+
/**
81+
* Directory where fixture XML files are stored.
82+
*/
4883
protected string $fixtureDirectory = __DIR__ . '/support/data/';
4984

85+
/**
86+
* @throws InvalidConfigException if the configuration is invalid or incomplete.
87+
*/
5088
protected function setUp(): void
5189
{
5290
parent::setUp();
5391

5492
$this->mockConsoleApplication();
5593
}
5694

57-
public function getDb(): Connection
58-
{
59-
return Yii::$app->getDb();
60-
}
61-
6295
/**
6396
* Asserts that a list of tree nodes matches the expected order.
6497
*
65-
* @param array $nodesList List of tree nodes to validate
66-
* @param array $expectedOrder Expected order of node names
67-
* @param string $nodeType Type of nodes being tested (for error messages)
98+
* @param array $nodesList List of tree nodes to validate.
99+
* @param array $expectedOrder Expected order of node names.
100+
* @param string $nodeType Type of nodes being tested (for error messages).
68101
*
69102
* @phpstan-param array<ActiveRecord> $nodesList
70103
* @phpstan-param array<string> $expectedOrder
@@ -97,8 +130,8 @@ protected function assertNodesInCorrectOrder(array $nodesList, array $expectedOr
97130
/**
98131
* Asserts that a query contains ORDER BY clause with 'lft' column.
99132
*
100-
* @param ActiveQuery $query The query to check
101-
* @param string $methodName Name of the method being tested
133+
* @param ActiveQuery $query Query to check.
134+
* @param string $methodName Name of the method being tested.
102135
*
103136
* @phpstan-param ActiveQuery<ActiveRecord> $query
104137
*/
@@ -120,6 +153,10 @@ protected function assertQueryHasOrderBy(ActiveQuery $query, string $methodName)
120153
}
121154

122155
/**
156+
* Builds a flat XML dataset from a given data set array.
157+
*
158+
* @return string Formatted XML string.
159+
*
123160
* @phpstan-import-type DataSetType from TestCase
124161
*
125162
* @phpstan-param DataSetType $dataSet
@@ -155,7 +192,8 @@ protected function buildFlatXMLDataSet(array $dataSet): string
155192
throw new RuntimeException('Failed to save XML from DOM.');
156193
}
157194

158-
// Replace the tags with 4 spaces
195+
// Manually indent child elements with 4 spaces for consistent fixture formatting.
196+
// DOM's formatOutput doesn't provide control over indentation depth.
159197
return str_replace(
160198
[
161199
'<tree', '<multiple_tree'],
@@ -167,6 +205,14 @@ protected function buildFlatXMLDataSet(array $dataSet): string
167205
);
168206
}
169207

208+
/**
209+
* Creates the database schema and resets the tables for testing.
210+
*
211+
* This method drops existing tables and runs migrations to ensure a clean state.
212+
*
213+
* @throws Exception if an unexpected error occurs during execution.
214+
* @throws RuntimeException if a runtime error prevents the operation from completing successfully.
215+
*/
170216
protected function createDatabase(): void
171217
{
172218
$command = $this->getDb()->createCommand();
@@ -179,6 +225,7 @@ protected function createDatabase(): void
179225
try {
180226
$this->runMigrate('down', ['all']);
181227
} catch (RuntimeException) {
228+
// Ignore errors when rolling back migrations on a potentially fresh database
182229
}
183230

184231
foreach ($dropTables as $table) {
@@ -193,13 +240,14 @@ protected function createDatabase(): void
193240
/**
194241
* Creates a tree structure based on a hierarchical definition.
195242
*
196-
* @param array $structure Hierarchical tree structure definition
197-
* @param array $updates Database updates to apply after creation
198-
* @param string $modelClass The model class to use (Tree::class or MultipleTree::class)
243+
* @param array $structure Hierarchical tree structure definition.
244+
* @param array $updates Database updates to apply after creation.
245+
* @param string $modelClass Model class to use ({@see Tree::class} or {@see MultipleTree::class}.
199246
*
200-
* @throws InvalidArgumentException if the structure array is empty.
247+
* @throws Exception if an unexpected error occurs during execution.
248+
* @throws InvalidArgumentException if one or more arguments are invalid, of incorrect type or format.
201249
*
202-
* @return MultipleTree|Tree The root node
250+
* @return MultipleTree|Tree Root node.
203251
*
204252
* @phpstan-param TreeStructure $structure
205253
* @phpstan-param UpdateData $updates
@@ -240,14 +288,24 @@ protected function createTreeStructure(
240288
return $rootNode;
241289
}
242290

291+
/**
292+
* Generates fixture data for testing tree structures.
293+
*
294+
* This method creates a database schema and populates it with predefined XML fixture data.
295+
*
296+
* It is used to set up the initial state of the database for tests that require specific tree structures.
297+
*
298+
* @throws Exception if an unexpected error occurs during execution.
299+
* @throws RuntimeException if a runtime error prevents the operation from completing successfully.
300+
*/
243301
protected function generateFixtureTree(): void
244302
{
245303
$this->createDatabase();
246304

247305
$command = $this->getDb()->createCommand();
248306

249307
// Load XML fixture data into database tables
250-
$xml = new SimpleXMLElement("{$this->fixtureDirectory}/test.xml", 0, true);
308+
$xml = $this->loadFixtureXML('test.xml');
251309

252310
$children = $xml->children() ?? [];
253311

@@ -277,6 +335,10 @@ protected function generateFixtureTree(): void
277335
}
278336

279337
/**
338+
* Returns a dataset containing all tree nodes from both {@see Tree} and {@see MultipleTree} models.
339+
*
340+
* @return array Dataset containing all tree nodes.
341+
*
280342
* @phpstan-import-type DataSetType from TestCase
281343
*
282344
* @phpstan-return DataSetType
@@ -300,6 +362,10 @@ protected function getDataSet(): array
300362
}
301363

302364
/**
365+
* Returns a dataset containing only {@see MultipleTree} nodes.
366+
*
367+
* @return array Dataset containing only {@see MultipleTree} nodes.
368+
*
303369
* @phpstan-import-type DataSetType from TestCase
304370
*
305371
* @phpstan-return DataSetType
@@ -315,6 +381,21 @@ protected function getDataSetMultipleTree(): array
315381
return array_values($dataSetMultipleTree);
316382
}
317383

384+
/**
385+
* Returns the database connection used for tests.
386+
*/
387+
protected function getDb(): Connection
388+
{
389+
return Yii::$app->getDb();
390+
}
391+
392+
/**
393+
* Returns a dataset containing only {@see Tree} nodes.
394+
*
395+
* @throws RuntimeException if a runtime error prevents the operation from completing successfully.
396+
*
397+
* @return SimpleXMLElement Dataset containing only {@see Tree} nodes.
398+
*/
318399
protected function loadFixtureXML(string $fileName): SimpleXMLElement
319400
{
320401
$filePath = "{$this->fixtureDirectory}/{$fileName}";
@@ -334,6 +415,15 @@ protected function loadFixtureXML(string $fileName): SimpleXMLElement
334415
return $simpleXML;
335416
}
336417

418+
/**
419+
* Mocks the console application for testing purposes.
420+
*
421+
* This method initializes a new console application instance with a database connection.
422+
*
423+
* It is used to set up the environment for running console commands in tests.
424+
*
425+
* @throws InvalidConfigException if the configuration is invalid or incomplete.
426+
*/
337427
protected function mockConsoleApplication(): void
338428
{
339429
new Application(
@@ -382,6 +472,10 @@ protected function replaceQuotes(string $sql): string
382472
}
383473

384474
/**
475+
* Runs a migration action with the specified parameters.
476+
*
477+
* @return mixed Result of the migration action.
478+
*
385479
* @phpstan-param array<array-key, mixed> $params
386480
*/
387481
protected function runMigrate(string $action, array $params = []): mixed
@@ -415,6 +509,8 @@ protected function runMigrate(string $action, array $params = []): mixed
415509
* @param array $updates Array of updates to apply.
416510
* @param string $tableName Name of the table to apply updates to.
417511
*
512+
* @throws Exception if an unexpected error occurs during execution.
513+
*
418514
* @phpstan-param UpdateData $updates
419515
*/
420516
private function applyUpdates(array $updates, string $tableName): void
@@ -437,8 +533,8 @@ private function applyUpdates(array $updates, string $tableName): void
437533
/**
438534
* Recursively creates children for a given parent node.
439535
*
440-
* @param MultipleTree|Tree $parent The parent node
441-
* @param array $nodes Children definition (can be strings or arrays)
536+
* @param MultipleTree|Tree $parent Parent node.
537+
* @param array $nodes Children definition (can be strings or arrays).
442538
*
443539
* @phpstan-param NodeChildren $nodes
444540
*/

0 commit comments

Comments
 (0)