diff --git a/php/BasicTestCase.php b/php/BasicTestCase.php new file mode 100644 index 0000000..536ddba --- /dev/null +++ b/php/BasicTestCase.php @@ -0,0 +1,109 @@ +assertTrue($this->checkIsSameClass($expected, $actual)); + } + + /** + * Checks that $actual object or class is same as $expected one + * + * @param object|string $class1 Object of any class or class name to check against to + * @param object|string $class2 Object of any class or class name to check + * @return bool + */ + protected function checkIsSameClass(object|string $class1, object|string $class2): bool + { + return (is_object($class1) ? $class1::class : $class1) === (is_object($class2) ? $class2::class : $class2); + } + + /** + * Asserts that $actual object or class extends $expected one + * + * @param array $expected Array of classes to check against to + * @param object|string $actual Object of any class or class name to check + */ + public function assertExtendsClasses(array $expected, object|string $actual): void + { + $this->assertTrue($this->checkExtendsClasses($expected, $actual)); + } + + /** + * Checks that $actual object or class extends $expected one + * + * @param string[] $parents Array of parent classes to check against to + * @param object|string $class Object of any class or class name to check + * @see https://www.php.net/manual/en/function.class-parents.php + */ + protected function checkExtendsClasses(array $parents, object|string $class): bool + { + return !empty(array_intersect($parents, is_object($class) ? class_parents($class) : [$class])); + } + + /** + * Asserts that $actual object or class implements $expected interfaces + * + * @param string[] $expected Array of interface classes to check against to + * @param object|string $actual Object of any class or class name to check + * @see https://www.php.net/manual/en/function.class-implements.php + */ + public function assertImplementsInterfaces(array $expected, object|string $actual): void + { + $this->assertNotEmpty(array_intersect($expected, is_object($actual) ? class_implements($actual) : [$actual])); + } + + /** + * Asserts that $actual object or class uses $expected traits + * + * @param string[] $expected Array of trait classes to check against to + * @param object|string $actual Object of any class or class name to check + * @see https://www.php.net/manual/en/function.class-uses.php#110752 + */ + public function assertUsesTraits(array $expected, object|string $actual): void + { + $found_traits = []; + $check_class = is_object($actual) ? $actual::class : $actual; + do { + $found_traits = array_merge(class_uses($check_class, true), $found_traits); + } while ($check_class = get_parent_class($check_class)); + foreach ($found_traits as $trait => $same) { + $found_traits = array_merge(class_uses($trait, true), $found_traits); + } + $this->assertNotEmpty(array_intersect(array_unique($found_traits), $expected)); + } + + /** + * Asserts that $value is instance Laravel Collection + * + * @param mixed $value + */ + public function assertIsCollection(mixed $value): void + { + $this->assertIsObject($value); + $this->assertIsIterable($value); + $this->assertTrue( + $this->checkIsSameClass(Collection::class, $value) + || $this->checkExtendsClasses([Collection::class], $value) + ); + } +}