From 766625bb91a38a4f303c045f09ce9121e4ba341b Mon Sep 17 00:00:00 2001 From: Billy VILLENA Date: Wed, 8 May 2024 16:39:54 +0200 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20DateTimeCollection?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * ✅ **Tested!** upon `\DateTime` * ✅ **Tested!** upon `\DateTimeImmutable` ✨ Features ========== * Define `containsDateTimeValue()` function for all `DateTimeInterfaceCollection` - Verify upon "date time + timezone" rather than object hash - Same for nullable `\DateTimeInterface` --- .../ContainsDateTimeNullableValueTrait.php | 28 +++++++ .../DateTime/ContainsDateTimeValueTrait.php | 27 ++++++ src/ObjectCollection/DateTimeCollection.php | 4 + .../DateTimeImmutableCollection.php | 4 + .../DateTimeImmutableNullableCollection.php | 4 + .../DateTimeInterfaceCollection.php | 4 + .../DateTimeInterfaceNullableCollection.php | 4 + .../DateTimeNullableCollection.php | 4 + .../ContainsDateTimeValue/TraitUsageTest.php | 83 +++++++++++++++++++ .../ContainsDateTimeValueTest.php | 75 +++++++++++++++++ .../DateTimeCollection/ContainsTest.php | 54 ++++++++++++ .../DateTimeCollection/TypeTest.php | 71 ++++++++++++++++ .../ContainsDateTimeValueTest.php | 75 +++++++++++++++++ .../ContainsTest.php | 54 ++++++++++++ .../DateTimeImmutableCollection/TypeTest.php | 71 ++++++++++++++++ .../ContainsDateTimeValueTest.php | 75 +++++++++++++++++ .../ContainsTest.php | 55 ++++++++++++ .../TypeTest.php | 76 +++++++++++++++++ .../ContainsDateTimeValueTest.php | 75 +++++++++++++++++ .../ContainsTest.php | 55 ++++++++++++ .../DateTimeNullableCollection/TypeTest.php | 76 +++++++++++++++++ 21 files changed, 974 insertions(+) create mode 100644 src/ObjectCollection/DateTime/ContainsDateTimeNullableValueTrait.php create mode 100644 src/ObjectCollection/DateTime/ContainsDateTimeValueTrait.php create mode 100644 tests/Unit/ObjectCollection/DateTime/ContainsDateTimeValue/TraitUsageTest.php create mode 100644 tests/Unit/ObjectCollection/DateTimeCollection/ContainsDateTimeValueTest.php create mode 100644 tests/Unit/ObjectCollection/DateTimeCollection/ContainsTest.php create mode 100644 tests/Unit/ObjectCollection/DateTimeCollection/TypeTest.php create mode 100644 tests/Unit/ObjectCollection/DateTimeImmutableCollection/ContainsDateTimeValueTest.php create mode 100644 tests/Unit/ObjectCollection/DateTimeImmutableCollection/ContainsTest.php create mode 100644 tests/Unit/ObjectCollection/DateTimeImmutableCollection/TypeTest.php create mode 100644 tests/Unit/ObjectCollection/DateTimeImmutableNullableCollection/ContainsDateTimeValueTest.php create mode 100644 tests/Unit/ObjectCollection/DateTimeImmutableNullableCollection/ContainsTest.php create mode 100644 tests/Unit/ObjectCollection/DateTimeImmutableNullableCollection/TypeTest.php create mode 100644 tests/Unit/ObjectCollection/DateTimeNullableCollection/ContainsDateTimeValueTest.php create mode 100644 tests/Unit/ObjectCollection/DateTimeNullableCollection/ContainsTest.php create mode 100644 tests/Unit/ObjectCollection/DateTimeNullableCollection/TypeTest.php diff --git a/src/ObjectCollection/DateTime/ContainsDateTimeNullableValueTrait.php b/src/ObjectCollection/DateTime/ContainsDateTimeNullableValueTrait.php new file mode 100644 index 0000000..bcbecef --- /dev/null +++ b/src/ObjectCollection/DateTime/ContainsDateTimeNullableValueTrait.php @@ -0,0 +1,28 @@ +toArray() as $value) { + if ( + $value === null + || ($dateTime->getTimestamp() + $dateTime->getOffset()) + !== ($value->getTimestamp() + $value->getOffset()) + ) { + continue; + } + + return true; + } + + return false; + } + + /** @return array */ + abstract protected function toArray(): array; +} diff --git a/src/ObjectCollection/DateTime/ContainsDateTimeValueTrait.php b/src/ObjectCollection/DateTime/ContainsDateTimeValueTrait.php new file mode 100644 index 0000000..f779983 --- /dev/null +++ b/src/ObjectCollection/DateTime/ContainsDateTimeValueTrait.php @@ -0,0 +1,27 @@ +toArray() as $value) { + if ( + ($dateTime->getTimestamp() + $dateTime->getOffset()) + !== ($value->getTimestamp() + $value->getOffset()) + ) { + continue; + } + + return true; + } + + return false; + } + + /** @return array<\DateTimeInterface> */ + abstract protected function toArray(): array; +} diff --git a/src/ObjectCollection/DateTimeCollection.php b/src/ObjectCollection/DateTimeCollection.php index 9012f97..7e284dc 100644 --- a/src/ObjectCollection/DateTimeCollection.php +++ b/src/ObjectCollection/DateTimeCollection.php @@ -4,9 +4,13 @@ namespace Steevanb\PhpCollection\ObjectCollection; +use Steevanb\PhpCollection\ObjectCollection\DateTime\ContainsDateTimeValueTrait; + /** @extends AbstractObjectCollection<\DateTime> */ class DateTimeCollection extends AbstractObjectCollection { + use ContainsDateTimeValueTrait; + /** @codeCoverageIgnore */ public static function getValueFqcn(): string { diff --git a/src/ObjectCollection/DateTimeImmutableCollection.php b/src/ObjectCollection/DateTimeImmutableCollection.php index bc99cd8..48fca97 100644 --- a/src/ObjectCollection/DateTimeImmutableCollection.php +++ b/src/ObjectCollection/DateTimeImmutableCollection.php @@ -4,9 +4,13 @@ namespace Steevanb\PhpCollection\ObjectCollection; +use Steevanb\PhpCollection\ObjectCollection\DateTime\ContainsDateTimeValueTrait; + /** @extends AbstractObjectCollection<\DateTimeImmutable> */ class DateTimeImmutableCollection extends AbstractObjectCollection { + use ContainsDateTimeValueTrait; + /** @codeCoverageIgnore */ public static function getValueFqcn(): string { diff --git a/src/ObjectCollection/DateTimeImmutableNullableCollection.php b/src/ObjectCollection/DateTimeImmutableNullableCollection.php index 3d0553d..9fe52c7 100644 --- a/src/ObjectCollection/DateTimeImmutableNullableCollection.php +++ b/src/ObjectCollection/DateTimeImmutableNullableCollection.php @@ -4,9 +4,13 @@ namespace Steevanb\PhpCollection\ObjectCollection; +use Steevanb\PhpCollection\ObjectCollection\DateTime\ContainsDateTimeNullableValueTrait; + /** @extends AbstractObjectNullableCollection<\DateTimeImmutable|null> */ class DateTimeImmutableNullableCollection extends AbstractObjectNullableCollection { + use ContainsDateTimeNullableValueTrait; + /** @codeCoverageIgnore */ public static function getValueFqcn(): string { diff --git a/src/ObjectCollection/DateTimeInterfaceCollection.php b/src/ObjectCollection/DateTimeInterfaceCollection.php index 6e47b58..58cd13c 100644 --- a/src/ObjectCollection/DateTimeInterfaceCollection.php +++ b/src/ObjectCollection/DateTimeInterfaceCollection.php @@ -4,9 +4,13 @@ namespace Steevanb\PhpCollection\ObjectCollection; +use Steevanb\PhpCollection\ObjectCollection\DateTime\ContainsDateTimeValueTrait; + /** @extends AbstractObjectCollection<\DateTimeInterface> */ class DateTimeInterfaceCollection extends AbstractObjectCollection { + use ContainsDateTimeValueTrait; + /** @codeCoverageIgnore */ public static function getValueFqcn(): string { diff --git a/src/ObjectCollection/DateTimeInterfaceNullableCollection.php b/src/ObjectCollection/DateTimeInterfaceNullableCollection.php index 4a1b07b..ff41aea 100644 --- a/src/ObjectCollection/DateTimeInterfaceNullableCollection.php +++ b/src/ObjectCollection/DateTimeInterfaceNullableCollection.php @@ -4,9 +4,13 @@ namespace Steevanb\PhpCollection\ObjectCollection; +use Steevanb\PhpCollection\ObjectCollection\DateTime\ContainsDateTimeNullableValueTrait; + /** @extends AbstractObjectNullableCollection<\DateTimeInterface|null> */ class DateTimeInterfaceNullableCollection extends AbstractObjectNullableCollection { + use ContainsDateTimeNullableValueTrait; + /** @codeCoverageIgnore */ public static function getValueFqcn(): string { diff --git a/src/ObjectCollection/DateTimeNullableCollection.php b/src/ObjectCollection/DateTimeNullableCollection.php index c56979d..68eec31 100644 --- a/src/ObjectCollection/DateTimeNullableCollection.php +++ b/src/ObjectCollection/DateTimeNullableCollection.php @@ -4,9 +4,13 @@ namespace Steevanb\PhpCollection\ObjectCollection; +use Steevanb\PhpCollection\ObjectCollection\DateTime\ContainsDateTimeNullableValueTrait; + /** @extends AbstractObjectNullableCollection<\DateTime|null> */ class DateTimeNullableCollection extends AbstractObjectNullableCollection { + use ContainsDateTimeNullableValueTrait; + /** @codeCoverageIgnore */ public static function getValueFqcn(): string { diff --git a/tests/Unit/ObjectCollection/DateTime/ContainsDateTimeValue/TraitUsageTest.php b/tests/Unit/ObjectCollection/DateTime/ContainsDateTimeValue/TraitUsageTest.php new file mode 100644 index 0000000..9fff658 --- /dev/null +++ b/tests/Unit/ObjectCollection/DateTime/ContainsDateTimeValue/TraitUsageTest.php @@ -0,0 +1,83 @@ + $reflectionTrait->getName(), + $reflectionCollection->getTraits() + ) + ); + } + + /** + * @dataProvider provideCollectionUsingNullableTrait + * @param class-string $class + */ + public function testUsingNullableTrait(string $class): void + { + $reflectionCollection = new \ReflectionClass($class); + static::assertContains( + needle: ContainsDateTimeNullableValueTrait::class, + haystack: array_map( + static fn (\ReflectionClass $reflectionTrait): string => $reflectionTrait->getName(), + $reflectionCollection->getTraits() + ) + ); + } + + /** @return iterable */ + public static function provideCollectionUsingTrait(): iterable + { + yield 'ContainsDateTimeValueTrait_is_used_by_DateTimeCollection' => [ + 'class' => DateTimeCollection::class, + ]; + yield 'ContainsDateTimeValueTrait_is_used_by_DateTimeImmutableCollection' => [ + 'class' => DateTimeImmutableCollection::class, + ]; + yield 'ContainsDateTimeValueTrait_is_used_by_DateTimeInterfaceCollection' => [ + 'class' => DateTimeInterfaceCollection::class, + ]; + } + + /** @return iterable */ + public static function provideCollectionUsingNullableTrait(): iterable + { + yield 'ContainsDateTimeNullableValueTrait_is_used_by_DateTimeNullableCollection' => [ + 'class' => DateTimeNullableCollection::class, + ]; + yield 'ContainsDateTimeNullableValueTrait_is_used_by_DateTimeImmutableNullableCollection' => [ + 'class' => DateTimeImmutableNullableCollection::class, + ]; + yield 'ContainsDateTimeNullableValueTrait_is_used_by_DateTimeInterfaceNullableCollection' => [ + 'class' => DateTimeInterfaceNullableCollection::class, + ]; + } +} diff --git a/tests/Unit/ObjectCollection/DateTimeCollection/ContainsDateTimeValueTest.php b/tests/Unit/ObjectCollection/DateTimeCollection/ContainsDateTimeValueTest.php new file mode 100644 index 0000000..7a9c6d4 --- /dev/null +++ b/tests/Unit/ObjectCollection/DateTimeCollection/ContainsDateTimeValueTest.php @@ -0,0 +1,75 @@ +add(new \DateInterval('PT1S')); + $dateTimeClone = clone $dateTimeA; + $dateTimeSameTime = (new \DateTime())->setTimestamp($dateTimeA->getTimestamp()); + + $dateTimeCollection = new DateTimeCollection([$dateTimeA]); + + static::assertTrue($dateTimeCollection->containsDateTimeValue($dateTimeA)); + static::assertTrue($dateTimeCollection->containsDateTimeValue($dateTimeCopy)); + static::assertFalse($dateTimeCollection->containsDateTimeValue($dateTimeB)); + static::assertTrue($dateTimeCollection->containsDateTimeValue($dateTimeClone)); + static::assertTrue($dateTimeCollection->containsDateTimeValue($dateTimeSameTime)); + } + + public function testContainsDateTimeValueWithTimezone(): void + { + $dateTime = new \DateTime('2024-07-14 12:00:00'); + $dateTimeB = clone $dateTime; + $dateTimeC = clone $dateTime; + $dateTimeD = clone $dateTime; + + // Setting timezones + $dateTime->setTimezone(new \DateTimeZone('+0800')); + $dateTimeB->setTimezone(new \DateTimeZone('+0600')); + $dateTimeC->setTimezone(new \DateTimeZone('-0600')); + $dateTimeD->setTimezone($dateTime->getTimezone()); + + $dateTimeCollection = new DateTimeCollection([$dateTime]); + + static::assertFalse($dateTimeCollection->containsDateTimeValue($dateTimeB)); + static::assertFalse($dateTimeCollection->containsDateTimeValue($dateTimeC)); + static::assertTrue($dateTimeCollection->containsDateTimeValue($dateTimeD)); + } + + public function testContainsDateTimeValueAfterClone(): void + { + $dateTime = new \DateTime(); + + $dateTimeCollection = (new DateTimeCollection([$dateTime])); + $dateTimeCollectionClone = clone ($dateTimeCollection); + + static::assertTrue($dateTimeCollection->containsDateTimeValue($dateTime)); + static::assertTrue($dateTimeCollectionClone->containsDateTimeValue($dateTime)); + } + + public function testContainsDateTimeValueAfterMerge(): void + { + $dateTime = new \DateTime(); + + static::assertTrue( + (new DateTimeCollection([$dateTime])) + ->merge(new DateTimeCollection([new \DateTime()])) + ->containsDateTimeValue($dateTime) + ); + } +} diff --git a/tests/Unit/ObjectCollection/DateTimeCollection/ContainsTest.php b/tests/Unit/ObjectCollection/DateTimeCollection/ContainsTest.php new file mode 100644 index 0000000..3cb7689 --- /dev/null +++ b/tests/Unit/ObjectCollection/DateTimeCollection/ContainsTest.php @@ -0,0 +1,54 @@ +setTimestamp($dateTimeA->getTimestamp()); + + $dateTimeCollection = new DateTimeCollection([$dateTimeA]); + + static::assertTrue($dateTimeCollection->contains($dateTimeA)); + static::assertTrue($dateTimeCollection->contains($dateTimeCopy)); + static::assertFalse($dateTimeCollection->contains($dateTimeB)); + static::assertFalse($dateTimeCollection->contains($dateTimeClone)); + static::assertFalse($dateTimeCollection->contains($dateTimeSameTime)); + } + + public function testContainsAfterClone(): void + { + $dateTime = new \DateTime(); + + $dateTimeCollection = (new DateTimeCollection([$dateTime])); + $dateTimeCollectionClone = clone ($dateTimeCollection); + + static::assertTrue($dateTimeCollection->contains($dateTime)); + static::assertTrue($dateTimeCollectionClone->contains($dateTime)); + } + + public function testContainsAfterMerge(): void + { + $dateTime = new \DateTime(); + + static::assertTrue( + (new DateTimeCollection([$dateTime])) + ->merge(new DateTimeCollection([new \DateTime()])) + ->contains($dateTime) + ); + } +} diff --git a/tests/Unit/ObjectCollection/DateTimeCollection/TypeTest.php b/tests/Unit/ObjectCollection/DateTimeCollection/TypeTest.php new file mode 100644 index 0000000..f320203 --- /dev/null +++ b/tests/Unit/ObjectCollection/DateTimeCollection/TypeTest.php @@ -0,0 +1,71 @@ +get(0)); + } + + /** @dataProvider provideInvalidType */ + public function testInvalidType(mixed $value): void + { + $this->expectException(InvalidTypeException::class); + /** @phpstan-ignore-next-line Parameter #1 $values ... constructor expects ... array given. */ + new DateTimeCollection([$value]); + } + + /** @return iterable */ + public static function provideInvalidType(): iterable + { + yield 'it_throws_invalid_type_exception_on_null_value' => [ + 'value' => null, + ]; + yield 'it_throws_invalid_type_exception_on_true_value' => [ + 'value' => true, + ]; + yield 'it_throws_invalid_type_exception_on_false_value' => [ + 'value' => false, + ]; + yield 'it_throws_invalid_type_exception_on_string_value' => [ + 'value' => '--value--', + ]; + yield 'it_throws_invalid_type_exception_on_integer_value' => [ + 'value' => 42, + ]; + yield 'it_throws_invalid_type_exception_on_float_value' => [ + 'value' => 3.14, + ]; + yield 'it_throws_invalid_type_exception_on_empty_array_value' => [ + 'value' => [], + ]; + yield 'it_throws_invalid_type_exception_on_DateTime_array_value' => [ + 'value' => [new \DateTime()], + ]; + yield 'it_throws_invalid_type_exception_on_object_value' => [ + 'value' => new class() { + }, + ]; + yield 'it_throws_invalid_type_exception_on_DateTimeCollection_value' => [ + 'value' => new DateTimeCollection(), + ]; + } +} diff --git a/tests/Unit/ObjectCollection/DateTimeImmutableCollection/ContainsDateTimeValueTest.php b/tests/Unit/ObjectCollection/DateTimeImmutableCollection/ContainsDateTimeValueTest.php new file mode 100644 index 0000000..e283af8 --- /dev/null +++ b/tests/Unit/ObjectCollection/DateTimeImmutableCollection/ContainsDateTimeValueTest.php @@ -0,0 +1,75 @@ +add(new \DateInterval('PT1S')); + $dateTimeImmutableClone = clone $dateTimeImmutableA; + $dateTimeImmutableSameTime = (new \DateTimeImmutable())->setTimestamp($dateTimeImmutableA->getTimestamp()); + + $dateTimeImmutableCollection = new DateTimeImmutableCollection([$dateTimeImmutableA]); + + static::assertTrue($dateTimeImmutableCollection->containsDateTimeValue($dateTimeImmutableA)); + static::assertTrue($dateTimeImmutableCollection->containsDateTimeValue($dateTimeImmutableCopy)); + static::assertFalse($dateTimeImmutableCollection->containsDateTimeValue($dateTimeImmutableB)); + static::assertTrue($dateTimeImmutableCollection->containsDateTimeValue($dateTimeImmutableClone)); + static::assertTrue($dateTimeImmutableCollection->containsDateTimeValue($dateTimeImmutableSameTime)); + } + + public function testContainsDateTimeValueWithTimezone(): void + { + $dateTimeImmutable = new \DateTimeImmutable('2024-07-14 12:00:00'); + $dateTimeImmutableB = clone $dateTimeImmutable; + $dateTimeImmutableC = clone $dateTimeImmutable; + $dateTimeImmutableD = clone $dateTimeImmutable; + + // Setting timezones + $dateTimeImmutable = $dateTimeImmutable->setTimezone(new \DateTimeZone('+0800')); + $dateTimeImmutableB = $dateTimeImmutableB->setTimezone(new \DateTimeZone('+0600')); + $dateTimeImmutableC = $dateTimeImmutableC->setTimezone(new \DateTimeZone('-0600')); + $dateTimeImmutableD = $dateTimeImmutableD->setTimezone($dateTimeImmutable->getTimezone()); + + $dateTimeImmutableCollection = new DateTimeImmutableCollection([$dateTimeImmutable]); + + static::assertFalse($dateTimeImmutableCollection->containsDateTimeValue($dateTimeImmutableB)); + static::assertFalse($dateTimeImmutableCollection->containsDateTimeValue($dateTimeImmutableC)); + static::assertTrue($dateTimeImmutableCollection->containsDateTimeValue($dateTimeImmutableD)); + } + + public function testContainsDateTimeValueAfterClone(): void + { + $dateTimeImmutable = new \DateTimeImmutable(); + + $dateTimeImmutableCollection = (new DateTimeImmutableCollection([$dateTimeImmutable])); + $dateTimeImmutableCollectionClone = clone ($dateTimeImmutableCollection); + + static::assertTrue($dateTimeImmutableCollection->containsDateTimeValue($dateTimeImmutable)); + static::assertTrue($dateTimeImmutableCollectionClone->containsDateTimeValue($dateTimeImmutable)); + } + + public function testContainsDateTimeValueAfterMerge(): void + { + $dateTimeImmutable = new \DateTimeImmutable(); + + static::assertTrue( + (new DateTimeImmutableCollection([$dateTimeImmutable])) + ->merge(new DateTimeImmutableCollection([new \DateTimeImmutable()])) + ->containsDateTimeValue($dateTimeImmutable) + ); + } +} diff --git a/tests/Unit/ObjectCollection/DateTimeImmutableCollection/ContainsTest.php b/tests/Unit/ObjectCollection/DateTimeImmutableCollection/ContainsTest.php new file mode 100644 index 0000000..637cee0 --- /dev/null +++ b/tests/Unit/ObjectCollection/DateTimeImmutableCollection/ContainsTest.php @@ -0,0 +1,54 @@ +setTimestamp($dateTimeImmutableA->getTimestamp()); + + $dateTimeImmutableCollection = new DateTimeImmutableCollection([$dateTimeImmutableA]); + + static::assertTrue($dateTimeImmutableCollection->contains($dateTimeImmutableA)); + static::assertTrue($dateTimeImmutableCollection->contains($dateTimeImmutableCopy)); + static::assertFalse($dateTimeImmutableCollection->contains($dateTimeImmutableB)); + static::assertFalse($dateTimeImmutableCollection->contains($dateTimeImmutableClone)); + static::assertFalse($dateTimeImmutableCollection->contains($dateTimeImmutableSameTime)); + } + + public function testContainsAfterClone(): void + { + $dateTimeImmutable = new \DateTimeImmutable(); + + $dateTimeImmutableCollection = (new DateTimeImmutableCollection([$dateTimeImmutable])); + $dateTimeImmutableCollectionClone = clone ($dateTimeImmutableCollection); + + static::assertTrue($dateTimeImmutableCollection->contains($dateTimeImmutable)); + static::assertTrue($dateTimeImmutableCollectionClone->contains($dateTimeImmutable)); + } + + public function testContainsAfterMerge(): void + { + $dateTimeImmutable = new \DateTimeImmutable(); + + static::assertTrue( + (new DateTimeImmutableCollection([$dateTimeImmutable])) + ->merge(new DateTimeImmutableCollection([new \DateTimeImmutable()])) + ->contains($dateTimeImmutable) + ); + } +} diff --git a/tests/Unit/ObjectCollection/DateTimeImmutableCollection/TypeTest.php b/tests/Unit/ObjectCollection/DateTimeImmutableCollection/TypeTest.php new file mode 100644 index 0000000..73393c3 --- /dev/null +++ b/tests/Unit/ObjectCollection/DateTimeImmutableCollection/TypeTest.php @@ -0,0 +1,71 @@ +get(0)); + } + + /** @dataProvider provideInvalidType */ + public function testInvalidType(mixed $value): void + { + $this->expectException(InvalidTypeException::class); + /** @phpstan-ignore-next-line Parameter #1 $values ... constructor expects ... array given. */ + new DateTimeImmutableCollection([$value]); + } + + /** @return iterable */ + public static function provideInvalidType(): iterable + { + yield 'it_throws_invalid_type_exception_on_null_value' => [ + 'value' => null, + ]; + yield 'it_throws_invalid_type_exception_on_true_value' => [ + 'value' => true, + ]; + yield 'it_throws_invalid_type_exception_on_false_value' => [ + 'value' => false, + ]; + yield 'it_throws_invalid_type_exception_on_string_value' => [ + 'value' => '--value--', + ]; + yield 'it_throws_invalid_type_exception_on_integer_value' => [ + 'value' => 42, + ]; + yield 'it_throws_invalid_type_exception_on_float_value' => [ + 'value' => 3.14, + ]; + yield 'it_throws_invalid_type_exception_on_empty_array_value' => [ + 'value' => [], + ]; + yield 'it_throws_invalid_type_exception_on_DateTimeImmutable_array_value' => [ + 'value' => [new \DateTimeImmutable()], + ]; + yield 'it_throws_invalid_type_exception_on_object_value' => [ + 'value' => new class() { + }, + ]; + yield 'it_throws_invalid_type_exception_on_DateTimeImmutableCollection_value' => [ + 'value' => new DateTimeImmutableCollection(), + ]; + } +} diff --git a/tests/Unit/ObjectCollection/DateTimeImmutableNullableCollection/ContainsDateTimeValueTest.php b/tests/Unit/ObjectCollection/DateTimeImmutableNullableCollection/ContainsDateTimeValueTest.php new file mode 100644 index 0000000..4e0b200 --- /dev/null +++ b/tests/Unit/ObjectCollection/DateTimeImmutableNullableCollection/ContainsDateTimeValueTest.php @@ -0,0 +1,75 @@ +add(new \DateInterval('PT1S')); + $dateTimeImmutableClone = clone $dateTimeImmutableA; + $dateTimeImmutableSameTime = (new \DateTimeImmutable())->setTimestamp($dateTimeImmutableA->getTimestamp()); + + $dateTimeImmutableNullableCollection = new DateTimeImmutableNullableCollection([$dateTimeImmutableA, null]); + + static::assertTrue($dateTimeImmutableNullableCollection->containsDateTimeValue($dateTimeImmutableA)); + static::assertTrue($dateTimeImmutableNullableCollection->containsDateTimeValue($dateTimeImmutableCopy)); + static::assertFalse($dateTimeImmutableNullableCollection->containsDateTimeValue($dateTimeImmutableB)); + static::assertTrue($dateTimeImmutableNullableCollection->containsDateTimeValue($dateTimeImmutableClone)); + static::assertTrue($dateTimeImmutableNullableCollection->containsDateTimeValue($dateTimeImmutableSameTime)); + } + + public function testContainsDateTimeValueWithTimezone(): void + { + $dateTimeImmutable = new \DateTimeImmutable('2024-07-14 12:00:00'); + $dateTimeImmutableB = clone $dateTimeImmutable; + $dateTimeImmutableC = clone $dateTimeImmutable; + $dateTimeImmutableD = clone $dateTimeImmutable; + + // Setting timezones + $dateTimeImmutable = $dateTimeImmutable->setTimezone(new \DateTimeZone('+0800')); + $dateTimeImmutableB = $dateTimeImmutableB->setTimezone(new \DateTimeZone('+0600')); + $dateTimeImmutableC = $dateTimeImmutableC->setTimezone(new \DateTimeZone('-0600')); + $dateTimeImmutableD = $dateTimeImmutableD->setTimezone($dateTimeImmutable->getTimezone()); + + $dateTimeImmutableNullableCollection = new DateTimeImmutableNullableCollection([$dateTimeImmutable]); + + static::assertFalse($dateTimeImmutableNullableCollection->containsDateTimeValue($dateTimeImmutableB)); + static::assertFalse($dateTimeImmutableNullableCollection->containsDateTimeValue($dateTimeImmutableC)); + static::assertTrue($dateTimeImmutableNullableCollection->containsDateTimeValue($dateTimeImmutableD)); + } + + public function testContainsDateTimeValueAfterClone(): void + { + $dateTimeImmutable = new \DateTimeImmutable(); + + $dateTimeImmutableNullableCollection = (new DateTimeImmutableNullableCollection([$dateTimeImmutable])); + $dateTimeImmutableNullableCollectionClone = clone ($dateTimeImmutableNullableCollection); + + static::assertTrue($dateTimeImmutableNullableCollection->containsDateTimeValue($dateTimeImmutable)); + static::assertTrue($dateTimeImmutableNullableCollectionClone->containsDateTimeValue($dateTimeImmutable)); + } + + public function testContainsDateTimeValueAfterMerge(): void + { + $dateTimeImmutable = new \DateTimeImmutable(); + + static::assertTrue( + (new DateTimeImmutableNullableCollection([$dateTimeImmutable])) + ->merge(new DateTimeImmutableNullableCollection([new \DateTimeImmutable()])) + ->containsDateTimeValue($dateTimeImmutable) + ); + } +} diff --git a/tests/Unit/ObjectCollection/DateTimeImmutableNullableCollection/ContainsTest.php b/tests/Unit/ObjectCollection/DateTimeImmutableNullableCollection/ContainsTest.php new file mode 100644 index 0000000..6b255ec --- /dev/null +++ b/tests/Unit/ObjectCollection/DateTimeImmutableNullableCollection/ContainsTest.php @@ -0,0 +1,55 @@ +setTimestamp($dateTimeImmutableA->getTimestamp()); + + $dateTimeImmutableNullableCollection = new DateTimeImmutableNullableCollection([$dateTimeImmutableA, null]); + + static::assertTrue($dateTimeImmutableNullableCollection->contains($dateTimeImmutableA)); + static::assertTrue($dateTimeImmutableNullableCollection->contains($dateTimeImmutableCopy)); + static::assertFalse($dateTimeImmutableNullableCollection->contains($dateTimeImmutableB)); + static::assertFalse($dateTimeImmutableNullableCollection->contains($dateTimeImmutableClone)); + static::assertFalse($dateTimeImmutableNullableCollection->contains($dateTimeImmutableSameTime)); + static::assertTrue($dateTimeImmutableNullableCollection->contains(null)); + } + + public function testContainsAfterClone(): void + { + $dateTimeImmutable = new \DateTimeImmutable(); + + $dateTimeImmutableNullableCollection = (new DateTimeImmutableNullableCollection([$dateTimeImmutable])); + $dateTimeImmutableNullableCollectionClone = clone ($dateTimeImmutableNullableCollection); + + static::assertTrue($dateTimeImmutableNullableCollection->contains($dateTimeImmutable)); + static::assertTrue($dateTimeImmutableNullableCollectionClone->contains($dateTimeImmutable)); + } + + public function testContainsAfterMerge(): void + { + $dateTimeImmutable = new \DateTimeImmutable(); + + static::assertTrue( + (new DateTimeImmutableNullableCollection([$dateTimeImmutable])) + ->merge(new DateTimeImmutableNullableCollection([new \DateTimeImmutable()])) + ->contains($dateTimeImmutable) + ); + } +} diff --git a/tests/Unit/ObjectCollection/DateTimeImmutableNullableCollection/TypeTest.php b/tests/Unit/ObjectCollection/DateTimeImmutableNullableCollection/TypeTest.php new file mode 100644 index 0000000..d4f3cc4 --- /dev/null +++ b/tests/Unit/ObjectCollection/DateTimeImmutableNullableCollection/TypeTest.php @@ -0,0 +1,76 @@ +get(0)); + } + + public function testAllowNull(): void + { + $dateTimeImmutableNullableCollection = new DateTimeImmutableNullableCollection([null]); + + static::assertCount(expectedCount: 1, haystack: $dateTimeImmutableNullableCollection); + static::assertNull($dateTimeImmutableNullableCollection->get(0)); + } + + /** @dataProvider provideInvalidType */ + public function testInvalidType(mixed $value): void + { + $this->expectException(InvalidTypeException::class); + /** @phpstan-ignore-next-line Parameter #1 $values ... constructor expects ... array given. */ + new DateTimeImmutableNullableCollection([$value]); + } + + /** @return iterable */ + public static function provideInvalidType(): iterable + { + yield 'it_throws_invalid_type_exception_on_true_value' => [ + 'value' => true, + ]; + yield 'it_throws_invalid_type_exception_on_false_value' => [ + 'value' => false, + ]; + yield 'it_throws_invalid_type_exception_on_string_value' => [ + 'value' => '--value--', + ]; + yield 'it_throws_invalid_type_exception_on_integer_value' => [ + 'value' => 42, + ]; + yield 'it_throws_invalid_type_exception_on_float_value' => [ + 'value' => 3.14, + ]; + yield 'it_throws_invalid_type_exception_on_empty_array_value' => [ + 'value' => [], + ]; + yield 'it_throws_invalid_type_exception_on_DateTimeImmutable_array_value' => [ + 'value' => [new \DateTimeImmutable()], + ]; + yield 'it_throws_invalid_type_exception_on_object_value' => [ + 'value' => new class() { + }, + ]; + yield 'it_throws_invalid_type_exception_on_DateTimeImmutableNullableCollection_value' => [ + 'value' => new DateTimeImmutableNullableCollection(), + ]; + } +} diff --git a/tests/Unit/ObjectCollection/DateTimeNullableCollection/ContainsDateTimeValueTest.php b/tests/Unit/ObjectCollection/DateTimeNullableCollection/ContainsDateTimeValueTest.php new file mode 100644 index 0000000..783b799 --- /dev/null +++ b/tests/Unit/ObjectCollection/DateTimeNullableCollection/ContainsDateTimeValueTest.php @@ -0,0 +1,75 @@ +add(new \DateInterval('PT1S')); + $dateTimeClone = clone $dateTimeA; + $dateTimeSameTime = (new \DateTime())->setTimestamp($dateTimeA->getTimestamp()); + + $dateTimeNullableCollection = new DateTimeNullableCollection([$dateTimeA, null]); + + static::assertTrue($dateTimeNullableCollection->containsDateTimeValue($dateTimeA)); + static::assertTrue($dateTimeNullableCollection->containsDateTimeValue($dateTimeCopy)); + static::assertFalse($dateTimeNullableCollection->containsDateTimeValue($dateTimeB)); + static::assertTrue($dateTimeNullableCollection->containsDateTimeValue($dateTimeClone)); + static::assertTrue($dateTimeNullableCollection->containsDateTimeValue($dateTimeSameTime)); + } + + public function testContainsDateTimeValueWithTimezone(): void + { + $dateTime = new \DateTime('2024-07-14 12:00:00'); + $dateTimeB = clone $dateTime; + $dateTimeC = clone $dateTime; + $dateTimeD = clone $dateTime; + + // Setting timezones + $dateTime->setTimezone(new \DateTimeZone('+0800')); + $dateTimeB->setTimezone(new \DateTimeZone('+0600')); + $dateTimeC->setTimezone(new \DateTimeZone('-0600')); + $dateTimeD->setTimezone($dateTime->getTimezone()); + + $dateTimeNullableCollection = new DateTimeNullableCollection([$dateTime]); + + static::assertFalse($dateTimeNullableCollection->containsDateTimeValue($dateTimeB)); + static::assertFalse($dateTimeNullableCollection->containsDateTimeValue($dateTimeC)); + static::assertTrue($dateTimeNullableCollection->containsDateTimeValue($dateTimeD)); + } + + public function testContainsDateTimeValueAfterClone(): void + { + $dateTime = new \DateTime(); + + $dateTimeNullableCollection = (new DateTimeNullableCollection([$dateTime])); + $dateTimeNullableCollectionClone = clone ($dateTimeNullableCollection); + + static::assertTrue($dateTimeNullableCollection->containsDateTimeValue($dateTime)); + static::assertTrue($dateTimeNullableCollectionClone->containsDateTimeValue($dateTime)); + } + + public function testContainsDateTimeValueAfterMerge(): void + { + $dateTime = new \DateTime(); + + static::assertTrue( + (new DateTimeNullableCollection([$dateTime])) + ->merge(new DateTimeNullableCollection([new \DateTime()])) + ->containsDateTimeValue($dateTime) + ); + } +} diff --git a/tests/Unit/ObjectCollection/DateTimeNullableCollection/ContainsTest.php b/tests/Unit/ObjectCollection/DateTimeNullableCollection/ContainsTest.php new file mode 100644 index 0000000..0c17249 --- /dev/null +++ b/tests/Unit/ObjectCollection/DateTimeNullableCollection/ContainsTest.php @@ -0,0 +1,55 @@ +setTimestamp($dateTimeA->getTimestamp()); + + $dateTimeNullableCollection = new DateTimeNullableCollection([$dateTimeA, null]); + + static::assertTrue($dateTimeNullableCollection->contains($dateTimeA)); + static::assertTrue($dateTimeNullableCollection->contains($dateTimeCopy)); + static::assertFalse($dateTimeNullableCollection->contains($dateTimeB)); + static::assertFalse($dateTimeNullableCollection->contains($dateTimeClone)); + static::assertFalse($dateTimeNullableCollection->contains($dateTimeSameTime)); + static::assertTrue($dateTimeNullableCollection->contains(null)); + } + + public function testContainsAfterClone(): void + { + $dateTime = new \DateTime(); + + $dateTimeNullableCollection = (new DateTimeNullableCollection([$dateTime])); + $dateTimeNullableCollectionClone = clone ($dateTimeNullableCollection); + + static::assertTrue($dateTimeNullableCollection->contains($dateTime)); + static::assertTrue($dateTimeNullableCollectionClone->contains($dateTime)); + } + + public function testContainsAfterMerge(): void + { + $dateTime = new \DateTime(); + + static::assertTrue( + (new DateTimeNullableCollection([$dateTime])) + ->merge(new DateTimeNullableCollection([new \DateTime()])) + ->contains($dateTime) + ); + } +} diff --git a/tests/Unit/ObjectCollection/DateTimeNullableCollection/TypeTest.php b/tests/Unit/ObjectCollection/DateTimeNullableCollection/TypeTest.php new file mode 100644 index 0000000..830ad83 --- /dev/null +++ b/tests/Unit/ObjectCollection/DateTimeNullableCollection/TypeTest.php @@ -0,0 +1,76 @@ +get(0)); + } + + public function testAllowNull(): void + { + $dateTimeNullableCollection = new DateTimeNullableCollection([null]); + + static::assertCount(expectedCount: 1, haystack: $dateTimeNullableCollection); + static::assertNull($dateTimeNullableCollection->get(0)); + } + + /** @dataProvider provideInvalidType */ + public function testInvalidType(mixed $value): void + { + $this->expectException(InvalidTypeException::class); + /** @phpstan-ignore-next-line Parameter #1 $values ... constructor expects ... array given. */ + new DateTimeNullableCollection([$value]); + } + + /** @return iterable */ + public static function provideInvalidType(): iterable + { + yield 'it_throws_invalid_type_exception_on_true_value' => [ + 'value' => true, + ]; + yield 'it_throws_invalid_type_exception_on_false_value' => [ + 'value' => false, + ]; + yield 'it_throws_invalid_type_exception_on_string_value' => [ + 'value' => '--value--', + ]; + yield 'it_throws_invalid_type_exception_on_integer_value' => [ + 'value' => 42, + ]; + yield 'it_throws_invalid_type_exception_on_float_value' => [ + 'value' => 3.14, + ]; + yield 'it_throws_invalid_type_exception_on_empty_array_value' => [ + 'value' => [], + ]; + yield 'it_throws_invalid_type_exception_on_DateTime_array_value' => [ + 'value' => [new \DateTime()], + ]; + yield 'it_throws_invalid_type_exception_on_object_value' => [ + 'value' => new class() { + }, + ]; + yield 'it_throws_invalid_type_exception_on_DateTimeNullableCollection_value' => [ + 'value' => new DateTimeNullableCollection(), + ]; + } +}