diff --git a/src/Attributes/Personal/HasGenderTrait.php b/src/Attributes/Personal/HasGenderTrait.php index 2fe3e17..4e21023 100644 --- a/src/Attributes/Personal/HasGenderTrait.php +++ b/src/Attributes/Personal/HasGenderTrait.php @@ -35,7 +35,7 @@ protected function castGender(string $gender): void $genderValue->equals('Female') || $genderValue->equals('Other') )) { - throw new UnexpectedEntityValueException('$gender'); + throw UnexpectedEntityValueException::withName('$gender'); } $this->gender = $genderValue; diff --git a/src/Datetime/Datetime.php b/src/Datetime/Datetime.php index 38789ad..ae58f5c 100644 --- a/src/Datetime/Datetime.php +++ b/src/Datetime/Datetime.php @@ -197,6 +197,16 @@ public function toDatetimeString(): Str return $this->toFormatInternal('Y-m-d H:i:s'); } + /** + * Returns Str instance with value in format "Y-m-d". + * + * @return Str + */ + public function toDateString(): Str + { + return $this->toFormatInternal('Y-m-d'); + } + /** * Returns Str instance with value in format "H:i:s". * diff --git a/src/ValueObjects/Traits/CanProcessEntityStateTrait.php b/src/ValueObjects/Traits/CanProcessEntityStateTrait.php index 169b021..64d9df5 100644 --- a/src/ValueObjects/Traits/CanProcessEntityStateTrait.php +++ b/src/ValueObjects/Traits/CanProcessEntityStateTrait.php @@ -73,6 +73,8 @@ final public function getDirty(bool $withTimestamps = false): array if (\is_object($this->{$field}) && \method_exists($this->{$field}, '__toString')) { $hasChanged = ((string) $value) !== ((string) $this->{$field}); + } elseif (\is_object($this->{$field})) { + $hasChanged = $value !== ((array) $this->{$field}); } else { $hasChanged = $value !== $this->{$field}; } diff --git a/tests/Unit/Attributes/GeneralTraitsVOTest.php b/tests/Unit/Attributes/GeneralTraitsVOTest.php index e7a2cc1..55dd44d 100644 --- a/tests/Unit/Attributes/GeneralTraitsVOTest.php +++ b/tests/Unit/Attributes/GeneralTraitsVOTest.php @@ -145,6 +145,16 @@ public function testBreaksIfAliasIsEmpty(): void new GeneralTraitsVO($data); } + public function testBreaksIfSurnameIsEmpty(): void + { + $this->expectException(NonEmptyStringException::class); + + $data = self::DATA; + $data['surname'] = ''; + + new GeneralTraitsVO($data); + } + public function testBreaksIfHitsIsNegative(): void { $this->expectException(NonNegativeNumberException::class); diff --git a/tests/Unit/Attributes/PersonalTraitsVOTest.php b/tests/Unit/Attributes/PersonalTraitsVOTest.php index d3409db..e7d1522 100644 --- a/tests/Unit/Attributes/PersonalTraitsVOTest.php +++ b/tests/Unit/Attributes/PersonalTraitsVOTest.php @@ -5,6 +5,7 @@ namespace HraDigital\Tests\Datatypes\Unit\Attributes; use HraDigital\Datatypes\Exceptions\Datatypes\NonEmptyStringException; +use HraDigital\Datatypes\Exceptions\Entities\UnexpectedEntityValueException; use HraDigital\Tests\Datatypes\AbstractBaseTestCase; /** @@ -36,6 +37,24 @@ public function testLoadsSuccessfully(): void $this->assertTrue($object->hasPhoto()); } + public function testLoadsSuccessfullyWithDifferentGender(): void + { + $data = self::DATA; + $data['gender'] = 'Female'; + $object = new PersonalTraitsVO($data); + + $this->assertEquals($data['gender'], (string) $object->getGender()); + } + + public function testBreaksIfGenderIsNotSupported(): void + { + $this->expectException(UnexpectedEntityValueException::class); + + $data = self::DATA; + $data['gender'] = 'Unsupported'; + new PersonalTraitsVO($data); + } + public function testBreaksWithEmptyCoutryOfBirth(): void { $data = self::DATA; diff --git a/tests/Unit/Datetime/DatetimeTest.php b/tests/Unit/Datetime/DatetimeTest.php index 1589fb2..ab33ce8 100644 --- a/tests/Unit/Datetime/DatetimeTest.php +++ b/tests/Unit/Datetime/DatetimeTest.php @@ -19,7 +19,7 @@ class DatetimeTest extends AbstractBaseTestCase { const DATETIME = '2021-05-06 10:11:12'; - public function testCanInstanciateSuccessfully(): void + public function testCanInstanciateSuccessfullyFromString(): void { $dt = Datetime::fromString(self::DATETIME); @@ -34,6 +34,109 @@ public function testCanInstanciateSuccessfully(): void $this->assertEquals($dt->jsonSerialize(), self::DATETIME); } + public function testCanInstantiateSuccessfullyFromNow(): void + { + $datetime = Datetime::now(); + $native = new \DateTime('now'); + + $this->assertEquals( + $datetime->toDateString(), + $native->format('Y-m-d') + ); + } + + public function testCanInstantiateSuccessfullyFromToday(): void + { + $datetime = Datetime::today(); + $native = new \DateTime('now'); + + $this->assertEquals( + $datetime->toDateString(), + $native->format('Y-m-d') + ); + $this->assertEquals(0, $datetime->getHour()); + $this->assertEquals(0, $datetime->getMinute()); + $this->assertEquals(0, $datetime->getSecond()); + } + + public function testCanInstantiateSuccessfullyFromTomorrow(): void + { + $datetime = Datetime::tomorrow(); + $native = new \DateTime('now'); + + $this->assertEquals( + $datetime->addDays(-1)->toDateString(), + $native->format('Y-m-d') + ); + $this->assertEquals(0, $datetime->getHour()); + $this->assertEquals(0, $datetime->getMinute()); + $this->assertEquals(0, $datetime->getSecond()); + } + + public function testCanInstantiateSuccessfullyFromYesterday(): void + { + $datetime = Datetime::yesterday(); + $native = new \DateTime('now'); + + $this->assertEquals( + $datetime->addDays(1)->toDateString(), + $native->format('Y-m-d') + ); + $this->assertEquals(0, $datetime->getHour()); + $this->assertEquals(0, $datetime->getMinute()); + $this->assertEquals(0, $datetime->getSecond()); + } + + public function testCanInstantiateSuccessfullyFromTimestamp(): void + { + $original = Datetime::now(); + $timestamp = $original->getTimestamp(); + + $fromTimestamp = Datetime::fromTimestamp($timestamp); + + $this->assertFalse($original === $fromTimestamp); + $this->assertEquals( + $original->toDatetimeString(), + $fromTimestamp->toDatetimeString() + ); + } + + public function testCanInstantiateSuccessfullyFromUnits(): void + { + $years = 2020; + $months = 11; + $days = 10; + $hours = 9; + $minutes = 30; + $seconds = 0; + $dt = Datetime::fromUnits($years, $months, $days, $hours, $minutes, $seconds); + + $this->assertEquals( + $years, + $dt->getYear() + ); + $this->assertEquals( + $months, + $dt->getMonth() + ); + $this->assertEquals( + $days, + $dt->getDay() + ); + $this->assertEquals( + $hours, + $dt->getHour() + ); + $this->assertEquals( + $minutes, + $dt->getMinute() + ); + $this->assertEquals( + $seconds, + $dt->getSecond() + ); + } + public function testCanAddInterval(): void { $dt = Datetime::fromString(self::DATETIME); diff --git a/tests/Unit/ValueObjects/AbstractValueObjectTest.php b/tests/Unit/ValueObjects/AbstractValueObjectTest.php index 429fcfd..b8fd680 100644 --- a/tests/Unit/ValueObjects/AbstractValueObjectTest.php +++ b/tests/Unit/ValueObjects/AbstractValueObjectTest.php @@ -75,6 +75,7 @@ public function testCanConvertToJsonWhileGuardingCertainAttributes(): void $this->assertArrayNotHasKey('email', $json); $this->assertArrayHasKey('title', $json); $this->assertArrayHasKey('inner', $json); + $this->assertArrayHasKey('native', $json); $this->assertArrayHasKey('title', $json['inner']); $this->assertArrayNotHasKey('active', $json['inner']); @@ -91,6 +92,7 @@ public function testCanConvertToArray(): void $this->assertArrayHasKey('email', $array); $this->assertArrayHasKey('title', $array); $this->assertArrayHasKey('inner', $array); + $this->assertArrayHasKey('native', $array); $this->assertArrayHasKey('title', $array['inner']); $this->assertArrayHasKey('active', $array['inner']); @@ -128,6 +130,7 @@ public function testCanCallDebugInfoInValueObject(): void $this->assertArrayHasKey('email', $array); $this->assertArrayHasKey('title', $array); $this->assertArrayHasKey('inner', $array); + $this->assertArrayHasKey('native', $array); $this->assertArrayHasKey('title', $array['inner']); $this->assertArrayHasKey('active', $array['inner']); @@ -160,6 +163,7 @@ public function testCanChangeAndTrackState(): void $this->assertArrayNotHasKey('email', $dirty); $this->assertArrayHasKey('title', $dirty); $this->assertArrayHasKey('inner', $dirty); + $this->assertArrayNotHasKey('native', $dirty); $this->assertArrayHasKey('title', $dirty['inner']); $this->assertArrayNotHasKey('active', $dirty['inner']); @@ -212,6 +216,7 @@ public function testCanResetState(): void $this->assertArrayNotHasKey('email', $dirty); $this->assertArrayNotHasKey('title', $dirty); $this->assertArrayNotHasKey('inner', $dirty); + $this->assertArrayNotHasKey('native', $dirty); $this->assertCount(0, $dirty); } diff --git a/tests/Unit/ValueObjects/TestingValueObject.php b/tests/Unit/ValueObjects/TestingValueObject.php index 8d62a64..b4969b9 100644 --- a/tests/Unit/ValueObjects/TestingValueObject.php +++ b/tests/Unit/ValueObjects/TestingValueObject.php @@ -34,6 +34,10 @@ class TestingValueObject extends AbstractValueObject 'active' => false, 'title' => 'My Inner Title', ], + 'native' => [ + 'active' => false, + 'title' => 'Some random native object', + ], ]; use HasPositiveIntegerIDTrait, @@ -58,12 +62,18 @@ class TestingValueObject extends AbstractValueObject ]; protected TestingNestedValueObject $inner; + protected \stdClass $native; protected function castInner(array $inner): void { $this->inner = new TestingNestedValueObject($inner); } + protected function castNative(array $native): void + { + $this->native = (object) $native; + } + public function getInner(): TestingNestedValueObject { return $this->inner;