Matthias Lantsch(4 months ago)
Fix tests and static analysis; CollectionTest
Browse Filesdiff --git a/f5c95406e1cf6fe15e67f77eba8593013a789ada b/d8b0941aa9db8a5d10a69c77989eff84e247ffff
index f5c9540..d8b0941 100644
--- a/f5c95406e1cf6fe15e67f77eba8593013a789ada
+++ b/d8b0941aa9db8a5d10a69c77989eff84e247ffff
@@ -11,7 +11,7 @@
"require": {
"php": ">=8.1",
"monolog/monolog": "^2.0",
- "psr/container": "2.0.2"
+ "psr/container": "^2.0.2"
},
"require-dev": {
"holonet/hdev": "~1.1.0@dev",
@@ -19,7 +19,7 @@
"spatie/phpunit-snapshot-assertions": "dev-main"
},
"provide": {
- "psr/container-implementation": "2.0.2"
+ "psr/container-implementation": "^2.0.2"
},
"repositories": [
{
@@ -60,7 +60,7 @@
"test": [
"@composer validate",
"@composer normalize --dry-run --diff",
- "@php -d memory_limit=-1 vendor/phpunit/phpunit/phpunit -c phpunit.xml",
+ "@php -d xdebug.mode=coverage -d memory_limit=-1 vendor/phpunit/phpunit/phpunit -c phpunit.xml",
"@php -d memory_limit=-1 vendor/friendsofphp/php-cs-fixer/php-cs-fixer fix --verbose --dry-run --ansi",
"@php -d memory_limit=-1 vendor/vimeo/psalm/psalm"
]
diff --git a/1143f81053f5f8ef420d7160d252fae32606b2b4 b/666402878461d1424cc03cc31a398400131fb5b7
index 1143f81..6664028 100644
--- a/1143f81053f5f8ef420d7160d252fae32606b2b4
+++ b/666402878461d1424cc03cc31a398400131fb5b7
@@ -50,16 +50,16 @@ class Collection implements Countable, IteratorAggregate {
}
/**
- * return a reference so we can change e.g. sub arrays from this call
+ * return a reference, so we can change e.g. sub arrays from this call
* => cannot use our own get() method.
*/
- public function __get(string $key): mixed {
- if (is_object($this->data[$key]) || $this->data[$key] === null) {
- //only actual variables should be returned by reference
- return $this->data[$key];
+ public function &__get(string $key): mixed {
+ if (!$this->has($key)) {
+ $null = null;
+ return $null;
}
- return $this->data[$key] ?? null;
+ return $this->data[$key];
}
public function clear(): void {
diff --git a/21ee65a51cd70364e05a7f2ea12430f60941afeb b/d6bc6a57128a2919c477cdb80941c7864713ed1d
index 21ee65a..d6bc6a5 100644
--- a/21ee65a51cd70364e05a7f2ea12430f60941afeb
+++ b/d6bc6a57128a2919c477cdb80941c7864713ed1d
@@ -75,7 +75,6 @@ class Container implements ContainerInterface {
* @template T
* @param class-string<T> $class
* @return T
- * @psalm-suppress InvalidReturnType
* @psalm-suppress InvalidReturnStatement
*/
public function byType(string $class, ?string $alias = null): object {
diff --git a/673104a5d862e8b99bf9ee18c0beba4698e5d1cc b/693d31a10cd04f72185098dd3bee63e444aa2e26
index 673104a..693d31a 100644
--- a/673104a5d862e8b99bf9ee18c0beba4698e5d1cc
+++ b/693d31a10cd04f72185098dd3bee63e444aa2e26
@@ -47,7 +47,6 @@ class ErrorDispatcher {
public function __construct() {
/**
* @psalm-suppress InvalidArgument
- * @psalm-suppress MissingClosureParamType
*/
set_error_handler(function (...$args): void {
foreach ($this->errorHandlers as $handler) {
@@ -55,10 +54,6 @@ class ErrorDispatcher {
}
});
- /**
- * @psalm-suppress InvalidArgument
- * @psalm-suppress MissingClosureParamType
- */
set_exception_handler(function (...$args): void {
foreach ($this->exceptionHandlers as $handler) {
$handler(...$args);
@@ -66,7 +61,6 @@ class ErrorDispatcher {
});
/**
- * @psalm-suppress InvalidArgument
* @psalm-suppress MissingClosureParamType
*/
register_shutdown_function(function (...$args): void {
<?php
/**
* This file is part of the hdev common library package
* (c) Matthias Lantsch.
*
* @license http://www.wtfpl.net/ Do what the fuck you want Public License
* @author Matthias Lantsch <[email protected]>
*/
namespace holonet\common\tests;
use holonet\common\collection\Collection;
use PHPUnit\Framework\TestCase;
use PHPUnit\Framework\Attributes\CoversClass;
#[CoversClass(Collection::class)]
class CollectionTest extends TestCase {
public function test_constructor_with_initial_data(): void {
$initialData = ['foo' => 'bar', 'baz' => 123];
$collection = new Collection($initialData);
$this->assertSame($initialData, $collection->all());
}
public function test_constructor_with_empty_initial_data(): void {
$collection = new Collection();
$this->assertTrue($collection->empty());
}
public function test_set_and_get(): void {
$collection = new Collection();
$collection->set('key1', 'value1');
$collection->key2 = 'value2';
$this->assertEquals('value1', $collection->key1);
$this->assertEquals('value2', $collection->get('key2'));
$this->assertNull($collection->NonsensicalKey);
}
public function test_set_with_null_key(): void {
$collection = new Collection();
$collection->set(null, 'value');
$this->assertEquals('value', $collection->get(0)); // 0 is the index when the key is null
}
public function test_set_with_null_key_adds_to_the_end(): void {
$collection = new Collection(['existingValue']);
$collection->set(null, 'newValue');
$this->assertEquals(['existingValue', 'newValue'], $collection->all());
}
public function test_get_with_default(): void {
$collection = new Collection(['existingKey' => 'value']);
$this->assertEquals('value', $collection->get('existingKey'));
$this->assertEquals('default', $collection->get('nonExistingKey', 'default'));
}
public function test_changes_to_magic_method_reads_work(): void {
$collection = new Collection(['null' => null, 'object' => new \stdClass(), 'array' => ['key' => 'value']]);
// make sure the reference to null points nowhere
$reference = $collection->null;
$reference = 'test';
$this->assertNull($collection->get('null'));
// make sure the reference to the object works as expected
$reference = $collection->object;
$reference->test = 'test';
$this->assertEquals('test', $collection->get('object')->test);
$collection->object->test = 'new value';
$this->assertEquals('new value', $collection->get('object')->test);
// make sure the reference to the array works as expected
$collection->array['key'] = 'new value';
$this->assertEquals(array('key' => 'new value'), $collection->get('array'));
$collection->array[] = 'appended';
$this->assertEquals(array('key' => 'new value', 'appended'), $collection->get('array'));
// changes to a subarray
$collection = new Collection(['key' => ['subkey' => 'value']]);
$collection->key['subkey'] = 'new value';
$this->assertEquals(['key' => ['subkey' => 'new value']], $collection->all());
}
public function test_has(): void {
$collection = new Collection(['existingKey' => 'value']);
$this->assertTrue($collection->has('existingKey'));
$this->assertTrue(isset($collection->existingKey));
$this->assertFalse($collection->has('nonExistingKey'));
$this->assertFalse(isset($collection->nonExistingKey));
$collection->set('nullKey', null);
// behave differently when the value is null
// => the key is set but the offset definitely is not "isset"
$this->assertTrue($collection->has('nullKey'));
$this->assertFalse(isset($collection->nullKey));
}
public function test_remove(): void {
$collection = new Collection(['key1' => 'value1', 'key2' => 'value2']);
$collection->remove('key1');
$this->assertEquals(['key2' => 'value2'], $collection->all());
unset($collection->key2);
$this->assertEquals([], $collection->all());
}
public function test_clear(): void {
$collection = new Collection(['key' => 'value']);
$collection->clear();
$this->assertTrue($collection->empty());
}
public function test_count(): void {
$collection = new Collection(['key1' => 'value1', 'key2' => 'value2']);
$this->assertEquals(2, $collection->count());
}
public function test_empty(): void {
$collection = new Collection();
$this->assertTrue($collection->empty());
$collection->set('key', 'value');
$this->assertFalse($collection->empty());
}
public function test_iterator(): void {
$collection = new Collection(['key1' => 'value1', 'key2' => 'value2']);
$iterator = $collection->getIterator();
$this->assertEquals(['key1' => 'value1', 'key2' => 'value2'], iterator_to_array($iterator));
}
public function test_merge(): void {
$collection = new Collection(['key1' => 'value1', 'key2' => 'value2']);
$collection->merge(['key2' => 'newValue2', 'key3' => 'value3']);
$this->assertEquals(['key1' => 'value1', 'key2' => 'newValue2', 'key3' => 'value3'], $collection->all());
}
public function test_replace(): void {
$collection = new Collection(['key1' => 'value1', 'key2' => 'value2']);
$collection->replace(['key3' => 'value3']);
$this->assertEquals(['key3' => 'value3'], $collection->all());
}
public function test_all(): void {
$collection = new Collection(['key' => 'value']);
$this->assertEquals(['key' => 'value'], $collection->all());
}
public function test_filter_param_can_be_used_to_filter_keys(): void {
$collection = new Collection(['key1' => 'value1', 'key2' => 'value2', 'key3' => 'value3']);
$this->assertEquals(['key1' => 'value1', 'key3' => 'value3'], $collection->all(['key1', 'key3']));
}
}
diff --git a/c8f6b5cb9102a780e073d81b93c3d49b423508bc b/7af8d219d10448638ea998ec46f742b23c21be41
index c8f6b5c..7af8d21 100644
--- a/c8f6b5cb9102a780e073d81b93c3d49b423508bc
+++ b/7af8d219d10448638ea998ec46f742b23c21be41
@@ -33,7 +33,7 @@ class ConfigRegistryTest extends TestCase {
putenv('ENV_VALUE_2=');
}
- public function testEnvPlaceholderReplacement(): void {
+ public function test_env_placeholder_gets_replaced(): void {
$registry = new ConfigRegistry();
$registry->setAll(array(
'test' => '%env(ENV_VALUE)%',
@@ -44,7 +44,7 @@ class ConfigRegistryTest extends TestCase {
$this->assertSame('test value', $registry->get('test2'));
}
- public function testNormalPlaceholdersStillWork(): void {
+ public function test_normal_placeholders_still_work(): void {
$registry = new ConfigRegistry();
$registry->setAll(array(
'test' => '%test_prop%',
@@ -54,7 +54,7 @@ class ConfigRegistryTest extends TestCase {
$this->assertSame('cool', $registry->get('test'));
}
- public function testVerifiedDto(): void {
+ public function test_config_data_can_be_fetched_as_a_verified_dto_object(): void {
$this->expectException(BadEnvironmentException::class);
$this->expectExceptionMessage('Faulty config with key \'test.testProp\': testProp must be exactly 11 characters long');
@@ -72,7 +72,7 @@ class ConfigRegistryTest extends TestCase {
$registry->verifiedDto('test', $dto);
}
- public function testVerifiedDtoTypeError(): void {
+ public function test_faulty_config_data_fetch_with_dto_object_throws_type_error(): void {
$this->expectException(BadEnvironmentException::class);
$this->expectExceptionMessage('Faulty config with key \'test\': TypeError: Cannot assign array to property class@anonymous::$testProp of type string');
@@ -90,16 +90,34 @@ class ConfigRegistryTest extends TestCase {
$registry->verifiedDto('test', $dto);
}
- public function testVerifiedDtoUsingClass(): void {
+ public function test_config_data_can_be_fetched_using_an_actual_dto_object_class(): void {
$registry = new ConfigRegistry();
$registry->set('test', 'amazing value');
- $dto = $registry->verifiedDto('test', TestDto::class);
+ $dto = $registry->verifiedDto('test', holonet_common_tests_ConfigRegistryTest_TestDto::class);
$this->assertSame('amazing value', $dto->value);
}
+
+ public function test_accessing_a_non_existing_key_will_throw_a_helpful_exception(): void {
+ $this->expectException(BadEnvironmentException::class);
+ $this->expectExceptionMessage('Faulty config with key \'test\': Config item doesn\'t exist');
+
+ $registry = new ConfigRegistry();
+ $registry->asDto('test', holonet_common_tests_ConfigRegistryTest_TestDto::class);
+ }
+
+ public function test_having_an_unset_environment_placeholder_in_a_value_defaults_to_empty_string(): void {
+ $registry = new ConfigRegistry();
+ $registry->setAll(array(
+ 'test' => '%env(ENV_VALUE_3)%',
+ ));
+
+ $this->assertSame('', $registry->get('test'));
+ }
+
}
-class TestDto {
+class holonet_common_tests_ConfigRegistryTest_TestDto {
public function __construct(
#[MinLength(4)]
public string $value