|
27 | 27 | </a> |
28 | 28 | </p> |
29 | 29 |
|
30 | | -## Installation |
| 30 | +## Features |
31 | 31 |
|
32 | | -The preferred way to install this extension is through [composer](https://getcomposer.org/download/). |
| 32 | +✅ **Advanced Reflection Utilities** |
| 33 | +- Access and modify private/protected properties via reflection. |
| 34 | +- Invoke inaccessible methods for comprehensive testing coverage. |
33 | 35 |
|
34 | | -Either run |
| 36 | +✅ **Cross-Platform String Assertions** |
| 37 | +- Eliminate false negatives from Windows/Unix line ending differences. |
| 38 | +- Normalize line endings for consistent string comparisons across platforms. |
35 | 39 |
|
36 | | -```shell |
| 40 | +✅ **File System Test Management** |
| 41 | +- Recursive file and directory cleanup for isolated test environments. |
| 42 | +- Safe removal operations preserving Git tracking files. |
| 43 | + |
| 44 | +## Quick start |
| 45 | + |
| 46 | +### System requirements |
| 47 | + |
| 48 | +- [`PHP`](https://www.php.net/downloads) 8.1 or higher. |
| 49 | +- [`Composer`](https://getcomposer.org/download/) for dependency management. |
| 50 | +- [`PHPUnit`](https://phpunit.de/) for testing framework integration. |
| 51 | + |
| 52 | +### Installation |
| 53 | + |
| 54 | +#### Method 1: Using [Composer](https://getcomposer.org/download/) (recommended) |
| 55 | + |
| 56 | +Install the extension. |
| 57 | + |
| 58 | +```bash |
37 | 59 | composer require --prefer-dist php-forge/support |
38 | 60 | ``` |
39 | 61 |
|
40 | | -or add |
| 62 | +#### Method 2: Manual installation |
| 63 | + |
| 64 | +Add to your `composer.json`. |
41 | 65 |
|
42 | 66 | ```json |
43 | | -"php-forge/support": "^0.1" |
| 67 | +{ |
| 68 | + "require-dev": { |
| 69 | + "php-forge/support": "^0.1" |
| 70 | + } |
| 71 | +} |
44 | 72 | ``` |
45 | 73 |
|
46 | | -to the require-dev section of your `composer.json` file. |
| 74 | +Then run. |
47 | 75 |
|
48 | | -## Usage |
| 76 | +```bash |
| 77 | +composer update |
| 78 | +``` |
49 | 79 |
|
50 | | -### Equals without line ending |
| 80 | +## Basic Usage |
| 81 | + |
| 82 | +### Cross-platform string equality |
51 | 83 |
|
52 | 84 | ```php |
53 | 85 | <?php |
54 | 86 |
|
55 | 87 | declare(strict_types=1); |
56 | 88 |
|
57 | | -namespace PHPForge\Support\Tests; |
58 | | - |
59 | 89 | use PHPForge\Support\Assert; |
60 | 90 |
|
| 91 | +// Normalize line endings for consistent comparisons |
61 | 92 | Assert::equalsWithoutLE( |
62 | | - <<<Text |
63 | | - Foo |
64 | | - Bar |
65 | | - Text, |
66 | | - "Foo\nBar" |
| 93 | + "Foo\r\nBar", |
| 94 | + "Foo\nBar", |
| 95 | + "Should match regardless of line ending style" |
67 | 96 | ); |
68 | 97 | ``` |
69 | 98 |
|
70 | | -### Inaccessible property |
| 99 | +### Accessing private properties |
71 | 100 |
|
72 | 101 | ```php |
73 | 102 | <?php |
74 | 103 |
|
75 | 104 | declare(strict_types=1); |
76 | 105 |
|
77 | | -namespace PHPForge\Support\Tests; |
78 | | - |
79 | 106 | use PHPForge\Support\Assert; |
80 | 107 |
|
81 | 108 | $object = new class () { |
82 | | - private string $foo = 'bar'; |
| 109 | + private string $secretValue = 'hidden'; |
83 | 110 | }; |
84 | 111 |
|
85 | | -$this->assertSame('bar', Assert::inaccessibleProperty($object, 'foo')); |
| 112 | +// Access private properties for testing |
| 113 | +$value = Assert::inaccessibleProperty($object, 'secretValue'); |
| 114 | +$this->assertSame('hidden', $value); |
86 | 115 | ``` |
87 | 116 |
|
88 | | -### Invoke method |
| 117 | +### Invoking protected methods |
89 | 118 |
|
90 | 119 | ```php |
91 | 120 | <?php |
92 | 121 |
|
93 | 122 | declare(strict_types=1); |
94 | 123 |
|
95 | | -namespace PHPForge\Support\Tests; |
96 | | - |
97 | 124 | use PHPForge\Support\Assert; |
98 | 125 |
|
99 | 126 | $object = new class () { |
100 | | - protected function foo(): string |
| 127 | + protected function calculate(int $a, int $b): int |
101 | 128 | { |
102 | | - return 'foo'; |
| 129 | + return $a + $b; |
103 | 130 | } |
104 | 131 | }; |
105 | 132 |
|
106 | | -$this->assertSame('foo', Assert::invokeMethod($object, 'foo')); |
| 133 | +// Test protected method behavior |
| 134 | +$result = Assert::invokeMethod($object, 'calculate', [5, 3]); |
| 135 | +$this->assertSame(8, $result); |
107 | 136 | ``` |
108 | 137 |
|
109 | | -### Set inaccessible property |
| 138 | +### Modifying inaccessible properties |
110 | 139 |
|
111 | 140 | ```php |
112 | 141 | <?php |
113 | 142 |
|
114 | 143 | declare(strict_types=1); |
115 | 144 |
|
116 | | -namespace PHPForge\Support\Tests; |
117 | | - |
118 | 145 | use PHPForge\Support\Assert; |
119 | 146 |
|
120 | 147 | $object = new class () { |
121 | | - private string $foo = 'bar'; |
| 148 | + private string $config = 'default'; |
122 | 149 | }; |
123 | 150 |
|
124 | | -Assert::setInaccessibleProperty($object, 'foo', 'baz'); |
| 151 | +// Set private property for testing scenarios |
| 152 | +Assert::setInaccessibleProperty($object, 'config', 'test-mode'); |
125 | 153 |
|
126 | | -$this->assertSame('baz', Assert::inaccessibleProperty($object, 'foo')); |
| 154 | +$newValue = Assert::inaccessibleProperty($object, 'config'); |
| 155 | +$this->assertSame('test-mode', $newValue); |
127 | 156 | ``` |
128 | 157 |
|
129 | | -### Remove files from directory |
| 158 | +### Test environment cleanup |
130 | 159 |
|
131 | 160 | ```php |
132 | 161 | <?php |
133 | 162 |
|
134 | 163 | declare(strict_types=1); |
135 | 164 |
|
136 | | -namespace PHPForge\Support\Tests; |
137 | | - |
138 | 165 | use PHPForge\Support\Assert; |
139 | 166 |
|
140 | | -$dir = __DIR__ . '/runtime'; |
141 | | - |
142 | | -mkdir($dir); |
143 | | -mkdir($dir . '/subdir'); |
144 | | -touch($dir . '/test.txt'); |
145 | | -touch($dir . '/subdir/test.txt'); |
| 167 | +$testDir = __DIR__ . '/runtime'; |
146 | 168 |
|
147 | | -Assert::removeFilesFromDirectory($dir); |
| 169 | +// Create test files and directories |
| 170 | +mkdir($testDir . '/subdir', 0755, true); |
| 171 | +touch($testDir . '/test.txt'); |
| 172 | +touch($testDir . '/subdir/nested.txt'); |
148 | 173 |
|
149 | | -$this->assertFileDoesNotExist($dir . '/test.txt'); |
| 174 | +// Clean up test artifacts (preserves .gitignore and .gitkeep) |
| 175 | +Assert::removeFilesFromDirectory($testDir); |
150 | 176 |
|
151 | | -rmdir(__DIR__ . '/runtime'); |
| 177 | +$this->assertFileDoesNotExist($testDir . '/test.txt'); |
| 178 | +$this->assertDirectoryDoesNotExist($testDir . '/subdir'); |
152 | 179 | ``` |
153 | 180 |
|
154 | | -## Support versions |
| 181 | +## Documentation |
155 | 182 |
|
156 | | -[](https://www.php.net/releases/8.1/en.php) |
157 | | -[](https://yiiframework.com) |
| 183 | +For comprehensive testing guidance, see: |
158 | 184 |
|
159 | | -## Testing |
160 | | - |
161 | | -[Check the documentation testing](/docs/testing.md) to learn about testing. |
| 185 | +- 🧪 [Testing Guide](docs/testing.md) |
162 | 186 |
|
163 | 187 | ## Our social networks |
164 | 188 |
|
165 | | -[](https://twitter.com/Terabytesoftw) |
| 189 | +[](https://x.com/Terabytesoftw) |
166 | 190 |
|
167 | 191 | ## License |
168 | 192 |
|
| 193 | +[](LICENSE.md) |
| 194 | + |
169 | 195 | The MIT License. Please see [License File](LICENSE.md) for more information. |
0 commit comments