diff --git a/README.md b/README.md index 2bb3c6e..32c9f2d 100644 --- a/README.md +++ b/README.md @@ -1,28 +1,20 @@ -# The PHP framework that gets out of your way. -[![Coverage Status](https://coveralls.io/repos/github/tempestphp/tempest-framework/badge.svg?branch=main)](https://coveralls.io/github/tempestphp/tempest-framework?branch=main) +# tempest/console -Read how to get started with Tempest [here](https://github.com/tempestphp/tempest-docs/blob/main/app/Content/01-getting-started.md). +```php +composer require tempest/console +``` -Zero config, zero overhead. This is Tempest: +Getting started: ```php -final readonly class BookController -{ - #[Get('/blog')] - public function index() { /* … */ } - - #[Get('/blog/{post}')] - public function show(Post $post) { /* … */ } -} +#!/usr/bin/env php +run(); -# Contributing -We welcome contributing to the Tempest framework! We only ask that you take a quick look at our [guidelines](.github/CONTRIBUTING.md) and then head on over to the issues page to see some ways you might help out! +exit; +``` \ No newline at end of file diff --git a/composer.json b/composer.json index c3d7e1e..50097fa 100644 --- a/composer.json +++ b/composer.json @@ -1,5 +1,5 @@ { - "name": "tempest/framework", + "name": "tempest/console", "description": "The PHP framework that gets out of your way.", "require": { "php": "^8.3", @@ -44,7 +44,6 @@ "csfixer": "vendor/bin/php-cs-fixer fix --allow-risky=yes", "phpstan": "vendor/bin/phpstan analyse src tests app", "qa": [ - "./tempest discovery:clear", "composer csfixer", "composer phpstan", "composer phpunit" diff --git a/phpstan.neon.dist b/phpstan.neon.dist index f8f8acd..83effcc 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -2,13 +2,8 @@ includes: - phpstan-baseline.php - vendor/phpat/phpat/extension.neon - vendor/spaze/phpstan-disallowed-calls/extension.neon -services: - - - class: Tests\Tempest\Architecture\ArchitectureTest - tags: - - phpat.test parameters: - level: 6 + level: 4 reportUnmatchedIgnoredErrors: false paths: - app diff --git a/phpunit.xml b/phpunit.xml index c1f29fc..98e3782 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -7,12 +7,8 @@ displayDetailsOnTestsThatTriggerErrors="true" displayDetailsOnTestsThatTriggerNotices="true" displayDetailsOnTestsThatTriggerWarnings="true" - bootstrap="./tests/bootstrap.php" > - - ./tests/Integration - ./tests/Unit diff --git a/src/Actions/RenderConsoleCommand.php b/src/Actions/RenderConsoleCommand.php index 90bd729..fe25354 100644 --- a/src/Actions/RenderConsoleCommand.php +++ b/src/Actions/RenderConsoleCommand.php @@ -27,6 +27,7 @@ public function __invoke(ConsoleCommand $consoleCommand): string private function renderParameter(ReflectionParameter $parameter): string { + /** @phpstan-ignore-next-line */ $type = $parameter->getType()?->getName(); $optional = $parameter->isOptional(); $defaultValue = strtolower(var_export($optional ? $parameter->getDefaultValue() : null, true)); diff --git a/src/Actions/RenderConsoleCommandOverview.php b/src/Actions/RenderConsoleCommandOverview.php index fdee318..0ea217f 100644 --- a/src/Actions/RenderConsoleCommandOverview.php +++ b/src/Actions/RenderConsoleCommandOverview.php @@ -4,14 +4,14 @@ namespace Tempest\Console\Actions; +use Tempest\AppConfig; use Tempest\Console\ConsoleConfig; use Tempest\Console\ConsoleStyle; -use Tempest\CoreConfig; final readonly class RenderConsoleCommandOverview { public function __construct( - private CoreConfig $coreConfig, + private AppConfig $appConfig, private ConsoleConfig $consoleConfig, ) { } @@ -19,10 +19,10 @@ public function __construct( public function __invoke(): string { $lines = [ - ConsoleStyle::BOLD(ConsoleStyle::BG_DARK_BLUE(" Tempest Console ")), + ConsoleStyle::BOLD(ConsoleStyle::BG_DARK_BLUE(" {$this->consoleConfig->name} ")), ]; - if ($this->coreConfig->discoveryCache) { + if ($this->appConfig->discoveryCache) { $lines[] = ConsoleStyle::BG_RED(' Discovery cache is enabled! '); } diff --git a/src/Config/console.php b/src/Config/console.php new file mode 100644 index 0000000..433385c --- /dev/null +++ b/src/Config/console.php @@ -0,0 +1,7 @@ +init(); @@ -30,12 +32,15 @@ public static function boot(string $root): self $application = new self( args: $_SERVER['argv'], container: $container, - coreConfig: $coreConfig, + appConfig: $appConfig, ); $container->singleton(Application::class, fn () => $application); - $coreConfig->exceptionHandlers[] = $container->get(ConsoleExceptionHandler::class); + $appConfig->exceptionHandlers[] = $container->get(ConsoleExceptionHandler::class); + + $consoleConfig = $container->get(ConsoleConfig::class); + $consoleConfig->name = $name; return $application; } @@ -43,7 +48,7 @@ public static function boot(string $root): self public function __construct( private array $args, private Container $container, - private CoreConfig $coreConfig, + private AppConfig $appConfig, ) { } @@ -62,11 +67,11 @@ public function run(): void $this->handleCommand($commandName); } catch (Throwable $throwable) { - if (! $this->coreConfig->enableExceptionHandling) { + if (! $this->appConfig->enableExceptionHandling) { throw $throwable; } - foreach ($this->coreConfig->exceptionHandlers as $exceptionHandler) { + foreach ($this->appConfig->exceptionHandlers as $exceptionHandler) { $exceptionHandler->handle($throwable); } } diff --git a/src/ConsoleConfig.php b/src/ConsoleConfig.php index f8c6827..e3627fb 100644 --- a/src/ConsoleConfig.php +++ b/src/ConsoleConfig.php @@ -9,6 +9,8 @@ final class ConsoleConfig { public function __construct( + public string $name = 'Tempest', + /** @var \Tempest\Console\ConsoleCommand[] $commands */ public array $commands = [], ) { diff --git a/src/Exceptions/ConsoleExceptionHandler.php b/src/Exceptions/ConsoleExceptionHandler.php index b80013e..e2e6981 100644 --- a/src/Exceptions/ConsoleExceptionHandler.php +++ b/src/Exceptions/ConsoleExceptionHandler.php @@ -33,16 +33,6 @@ public function handle(Throwable $throwable): void } } - private function outputPath(array $line): void - { - if (! isset($line['file'])) { - return; - } - - $this->console->write($line['file'] . ':' . $line['line']); - $this->console->writeln(''); - } - private function outputLine(array $line): void { $this->console->write(' - '); diff --git a/src/Testing/Console/ConsoleCommandTester.php b/src/Testing/Console/ConsoleCommandTester.php index 90918b6..3ec6479 100644 --- a/src/Testing/Console/ConsoleCommandTester.php +++ b/src/Testing/Console/ConsoleCommandTester.php @@ -4,11 +4,11 @@ namespace Tempest\Console\Testing\Console; +use Tempest\AppConfig; use Tempest\Console\ConsoleApplication; use Tempest\Console\ConsoleOutput; use Tempest\Console\Exceptions\ConsoleExceptionHandler; use Tempest\Container\Container; -use Tempest\CoreConfig; final readonly class ConsoleCommandTester { @@ -22,14 +22,14 @@ public function __construct(private Container $container) public function call(string $command): TestConsoleHelper { - $coreConfig = $this->container->get(CoreConfig::class); + $appConfig = $this->container->get(AppConfig::class); - $coreConfig->exceptionHandlers[] = $this->container->get(ConsoleExceptionHandler::class); + $appConfig->exceptionHandlers[] = $this->container->get(ConsoleExceptionHandler::class); $application = new ConsoleApplication( args: ['tempest', ...explode(' ', $command)], container: $this->container, - coreConfig: $coreConfig, + appConfig: $appConfig, ); $application->run(); diff --git a/tempest b/tempest index c078a1b..f9363e6 100755 --- a/tempest +++ b/tempest @@ -2,9 +2,19 @@ run(); +ConsoleApplication::boot( + 'Tempest Console', + new AppConfig( + getcwd(), + discoveryLocations: [ + new DiscoveryLocation('App\\', __DIR__ . '/app/') + ], + ), +)->run(); exit; \ No newline at end of file diff --git a/tests/Architecture/ArchitectureTest.php b/tests/Architecture/ArchitectureTest.php deleted file mode 100644 index e6c3208..0000000 --- a/tests/Architecture/ArchitectureTest.php +++ /dev/null @@ -1,64 +0,0 @@ -classes(Selector::inNamespace('Tempest\Validation\Rules')) - ->shouldImplement() - ->classes(Selector::classname(\Tempest\Validation\Rule::class)); - } - - public function test_validation_rules_are_attributes(): Rule - { - return PHPat::rule() - ->classes(Selector::inNamespace('Tempest\Validation\Rules')) - ->shouldApplyAttribute() - ->classes(Selector::classname(Attribute::class)); - } - - public function test_validation_rules_are_final(): Rule - { - return PHPat::rule() - ->classes(Selector::inNamespace('Tempest\Validation\Rules')) - ->shouldBeFinal(); - } - - public function test_validation_rules_are_readonly(): Rule - { - return PHPat::rule() - ->classes(Selector::inNamespace('Tempest\Validation\Rules')) - ->shouldBeReadonly(); - } - - public function test_unit_tests_do_not_rely_on_application_classes(): Rule - { - return PHPat::rule() - ->classes(Selector::inNamespace('Tests\Tempest\Unit')) - ->shouldNotDependOn() - ->classes( - Selector::inNamespace('Tests\Tempest\Integration'), - Selector::inNamespace('Tempest\Testing'), - ); - } - - public function test_integration_tests_do_not_rely_on_unit_test_fixtures(): Rule - { - return PHPat::rule() - ->classes(Selector::inNamespace('Tests\Tempest\Integration')) - ->shouldNotDependOn() - ->classes( - Selector::inNamespace('Tests\Tempest\Unit'), - ); - } -} diff --git a/tests/Integration/Application/ConsoleApplicationTest.php b/tests/Integration/Application/ConsoleApplicationTest.php deleted file mode 100644 index 44d2b21..0000000 --- a/tests/Integration/Application/ConsoleApplicationTest.php +++ /dev/null @@ -1,52 +0,0 @@ -console - ->call('unknown') - ->assertContains('Command `unknown` not found'); - } - - public function test_cli_application() - { - $this->console - ->call('hello:world input') - ->assertContains('Hi') - ->assertContains('input'); - } - - public function test_cli_application_flags() - { - $this->console - ->call('hello:test --flag --optionalValue=1') - ->assertContains('1') - ->assertContains('flag'); - } - - public function test_cli_application_flags_defaults() - { - $this->console - ->call('hello:test') - ->assertContains('null') - ->assertContains('no-flag'); - } - - public function test_failing_command() - { - $this->console - ->call('hello:world') - ->assertContains('Something went wrong'); - } -} diff --git a/tests/Integration/Application/HttpApplicationTest.php b/tests/Integration/Application/HttpApplicationTest.php deleted file mode 100644 index dd45563..0000000 --- a/tests/Integration/Application/HttpApplicationTest.php +++ /dev/null @@ -1,21 +0,0 @@ -http - ->get('/') - ->assertOk(); - } -} diff --git a/tests/Integration/CommandBus/CommandBusTest.php b/tests/Integration/CommandBus/CommandBusTest.php deleted file mode 100644 index 0dc48be..0000000 --- a/tests/Integration/CommandBus/CommandBusTest.php +++ /dev/null @@ -1,51 +0,0 @@ -container->get(CommandBus::class); - - $this->assertEquals([$command], $bus->getHistory()); - } - - public function test_command_bus_with_middleware() - { - MyCommandBusMiddleware::$hit = false; - - $config = $this->container->get(CommandBusConfig::class); - - $config->addMiddleware(new MyCommandBusMiddleware()); - - command(new MyCommand()); - - $this->assertTrue(MyCommandBusMiddleware::$hit); - } - - public function test_unknown_handler_throws_exception() - { - $this->expectException(CommandHandlerNotFound::class); - - command(new class () {}); - } -} diff --git a/tests/Integration/CommandBus/Fixtures/MyCommandBusMiddleware.php b/tests/Integration/CommandBus/Fixtures/MyCommandBusMiddleware.php deleted file mode 100644 index 0948126..0000000 --- a/tests/Integration/CommandBus/Fixtures/MyCommandBusMiddleware.php +++ /dev/null @@ -1,19 +0,0 @@ -container->get(AppConfig::class); - - MyDiscovery::$cacheCleared = false; - - $appConfig->discoveryClasses = [MyDiscovery::class]; - - $this->console->call('discovery:clear'); - - $this->assertTrue(MyDiscovery::$cacheCleared); - } -} diff --git a/tests/Integration/Console/Commands/DiscoveryStatusCommandTest.php b/tests/Integration/Console/Commands/DiscoveryStatusCommandTest.php deleted file mode 100644 index 593cb27..0000000 --- a/tests/Integration/Console/Commands/DiscoveryStatusCommandTest.php +++ /dev/null @@ -1,30 +0,0 @@ -console->call('discovery:status'); - - $appConfig = $this->container->get(AppConfig::class); - - foreach ($appConfig->discoveryClasses as $discoveryClass) { - $output->assertContains($discoveryClass); - } - - foreach ($appConfig->discoveryLocations as $discoveryLocation) { - $output->assertContains($discoveryLocation->path); - } - } -} diff --git a/tests/Integration/Console/Commands/MigrateCommandTest.php b/tests/Integration/Console/Commands/MigrateCommandTest.php deleted file mode 100644 index d8b238b..0000000 --- a/tests/Integration/Console/Commands/MigrateCommandTest.php +++ /dev/null @@ -1,35 +0,0 @@ -console - ->call('migrate:up') - ->assertContains('create_migrations_table') - ->assertContains('Migrated 3 migrations'); - - Assert::assertCount(3, Migration::all()); - } - - public function test_migrate_command_inserts_new_records(): void - { - $this->console - ->call('migrate:up') - ->assertContains('create_migrations_table'); - - Assert::assertCount(3, Migration::all()); - } -} diff --git a/tests/Integration/Console/Commands/MigrateRollbackCommandTest.php b/tests/Integration/Console/Commands/MigrateRollbackCommandTest.php deleted file mode 100644 index fe061fc..0000000 --- a/tests/Integration/Console/Commands/MigrateRollbackCommandTest.php +++ /dev/null @@ -1,42 +0,0 @@ -console->call('migrate:up') - ->assertContains('create_migrations_table'); - - $this->console - ->call('migrate:down') - ->assertContains('create_migrations_table') - ->assertContains("Rolled back 3 migrations"); - - try { - Assert::assertEmpty(Migration::all()); - } catch (PDOException $e) { - Assert::assertStringContainsString('no such table: Migration', $e->getMessage()); - } - } - - public function test_errors_when_no_migrations_to_rollback(): void - { - $this->console - ->call('migrate:down') - ->assertContains(MigrationException::noTable()->getMessage()); - } -} diff --git a/tests/Integration/Console/Commands/RoutesCommandTest.php b/tests/Integration/Console/Commands/RoutesCommandTest.php deleted file mode 100644 index 3600f18..0000000 --- a/tests/Integration/Console/Commands/RoutesCommandTest.php +++ /dev/null @@ -1,23 +0,0 @@ -console - ->call('routes') - ->assertContains('/create-post') - ->assertContains(PostController::class); - } -} diff --git a/tests/Integration/Console/ConsoleOutputInitializerTest.php b/tests/Integration/Console/ConsoleOutputInitializerTest.php deleted file mode 100644 index c2da43e..0000000 --- a/tests/Integration/Console/ConsoleOutputInitializerTest.php +++ /dev/null @@ -1,39 +0,0 @@ -actAsConsoleApplication(); - - $consoleOutput = $initializer->initialize($this->container); - - $this->assertInstanceOf(GenericConsoleOutput::class, $consoleOutput); - } - - public function test_in_http_application() - { - $initializer = new ConsoleOutputInitializer(); - - $this->actAsHttpApplication(); - - $consoleOutput = $initializer->initialize($this->container); - - $this->assertInstanceOf(NullConsoleOutput::class, $consoleOutput); - } -} diff --git a/tests/Integration/Console/Fixtures/MyDiscovery.php b/tests/Integration/Console/Fixtures/MyDiscovery.php deleted file mode 100644 index 303a90f..0000000 --- a/tests/Integration/Console/Fixtures/MyDiscovery.php +++ /dev/null @@ -1,39 +0,0 @@ -container->get(MigrationManager::class); - - $migrationManager->up(); - $migrations = Migration::all(); - $this->assertCount(3, $migrations); - - $migrationManager->up(); - $migrations = Migration::all(); - $this->assertCount(3, $migrations); - } -} diff --git a/tests/Integration/Events/EventBusTest.php b/tests/Integration/Events/EventBusTest.php deleted file mode 100644 index 9ddf51c..0000000 --- a/tests/Integration/Events/EventBusTest.php +++ /dev/null @@ -1,44 +0,0 @@ -container->get(EventBus::class); - - MyEventHandler::$itHappened = false; - - $eventBus->dispatch(new ItHappened()); - - $this->assertTrue(MyEventHandler::$itHappened); - } - - public function test_event_bus_with_middleware() - { - MyEventBusMiddleware::$hit = false; - - $config = $this->container->get(EventBusConfig::class); - - $config->addMiddleware(new MyEventBusMiddleware()); - - event(new ItHappened()); - - $this->assertTrue(MyEventBusMiddleware::$hit); - } -} diff --git a/tests/Integration/Events/Fixtures/MyEventBusMiddleware.php b/tests/Integration/Events/Fixtures/MyEventBusMiddleware.php deleted file mode 100644 index e70c8d3..0000000 --- a/tests/Integration/Events/Fixtures/MyEventBusMiddleware.php +++ /dev/null @@ -1,19 +0,0 @@ -appConfig->enableExceptionHandling = true; - $this->appConfig->exceptionHandlers = [ - $this->container->get(ConsoleExceptionHandler::class), - ]; - - $this->console - ->call('fail output') - ->assertContains(FailCommand::class) - ->assertContains('__invoke'); - } -} diff --git a/tests/Integration/Exceptions/HttpExceptionHandlerTest.php b/tests/Integration/Exceptions/HttpExceptionHandlerTest.php deleted file mode 100644 index 7743bae..0000000 --- a/tests/Integration/Exceptions/HttpExceptionHandlerTest.php +++ /dev/null @@ -1,34 +0,0 @@ -actAsHttpApplication(); - $this->appConfig->enableExceptionHandling = true; - $this->appConfig->exceptionHandlers = [ - $this->container->get(HttpExceptionHandler::class), - ]; - - $_SERVER['REQUEST_URI'] = uri(FailController::class); - - ob_start(); - $app->run(); - $contents = ob_get_clean(); - - $this->assertStringContainsString('Nope', $contents); - } -} diff --git a/tests/Integration/FrameworkIntegrationTestCase.php b/tests/Integration/FrameworkIntegrationTestCase.php deleted file mode 100644 index 2dda6f7..0000000 --- a/tests/Integration/FrameworkIntegrationTestCase.php +++ /dev/null @@ -1,64 +0,0 @@ -appConfig = new AppConfig( - root: __DIR__ . '/../../', - discoveryCache: true, - discoveryLocations: [ - new DiscoveryLocation( - 'App\\', - __DIR__ . '/../../app', - ), - ], - ); - - parent::setUp(); - - $databasePath = __DIR__ . '/../../app/database.sqlite'; - $cleanDatabasePath = __DIR__ . '/../../app/database-clean.sqlite'; - - @unlink(DiscoveryDiscovery::CACHE_PATH); - @unlink($databasePath); - copy($cleanDatabasePath, $databasePath); - } - - protected function actAsConsoleApplication(string $command = ''): Application - { - $application = new ConsoleApplication( - args: ['tempest', ...explode(' ', $command)], - container: $this->container, - coreConfig: $this->container->get(AppConfig::class), - ); - - $this->container->singleton(Application::class, fn () => $application); - - return $application; - } - - protected function actAsHttpApplication(): HttpApplication - { - $application = new HttpApplication( - $this->container, - $this->container->get(AppConfig::class), - ); - - $this->container->singleton(Application::class, fn () => $application); - - return $application; - } -} diff --git a/tests/Integration/Http/CleanupSessionsCommandTest.php b/tests/Integration/Http/CleanupSessionsCommandTest.php deleted file mode 100644 index c1792ef..0000000 --- a/tests/Integration/Http/CleanupSessionsCommandTest.php +++ /dev/null @@ -1,48 +0,0 @@ -clock('2024-01-01 00:00:00'); - - $this->container->config(new SessionConfig( - path: __DIR__ . '/sessions', - expirationInSeconds: 10, - )); - - $sessionManager = $this->container->get(SessionManager::class); - - $sessionManager->set(new SessionId('session_a'), 'test', 'value'); - - $clock->changeTime(9); - - $sessionManager->set(new SessionId('session_b'), 'test', 'value'); - - $clock->changeTime(2); - - $this->console - ->call('session:clean') - ->assertContains('session_a') - ->assertDoesNotContain('session_b'); - - $this->assertFileDoesNotExist(__DIR__ . '/sessions/session_a'); - $this->assertFileExists(__DIR__ . '/sessions/session_b'); - } -} diff --git a/tests/Integration/Http/CookieManagerTest.php b/tests/Integration/Http/CookieManagerTest.php deleted file mode 100644 index c7cee9d..0000000 --- a/tests/Integration/Http/CookieManagerTest.php +++ /dev/null @@ -1,75 +0,0 @@ -container->get(CookieManager::class); - - $this->assertEquals('value', $cookies->get('existing')->value); - } - - public function test_creating_a_cookie(): void - { - $cookies = $this->container->get(CookieManager::class); - - $cookies->set('new', 'value'); - - $this->http - ->get('/') - ->assertOk() - ->assertHeaderContains('set-cookie', 'new=value'); - } - - public function test_removing_a_cookie(): void - { - $cookies = $this->container->get(CookieManager::class); - - $cookies->remove('new'); - - $this->http - ->get('/') - ->assertOk() - ->assertHeaderContains('set-cookie', 'new=; Expires=Wed, 31-Dec-1969 23:59:59 GMT; Max-Age=0'); - } - - public function test_manually_adding_a_cookie(): void - { - $clock = new MockClock('2023-01-01 00:00:00'); - $this->container->singleton(Clock::class, fn () => $clock); - $cookies = $this->container->get(CookieManager::class); - - $cookies->add(new Cookie( - key: 'key', - value: 'value', - expiresAt: $clock->time() + 1, - domain: 'test.com', - path: '/test', - secure: true, - httpOnly: true, - sameSite: SameSite::STRICT, - )); - - $this->http - ->get('/') - ->assertOk() - ->assertHeaderContains('set-cookie', 'key=value; Expires=Sun, 01-Jan-2023 00:00:01 GMT; Max-Age=1; Domain=test.com; Path=/test; Secure; HttpOnly; SameSite=Strict'); - } -} diff --git a/tests/Integration/Http/FileSessionTest.php b/tests/Integration/Http/FileSessionTest.php deleted file mode 100644 index 396daf4..0000000 --- a/tests/Integration/Http/FileSessionTest.php +++ /dev/null @@ -1,103 +0,0 @@ -path = __DIR__ . '/sessions'; - - $this->container->config(new SessionConfig(path: $this->path)); - $this->container->singleton( - SessionManager::class, - fn () => new FileSessionManager( - $this->container->get(Clock::class), - $this->container->get(SessionConfig::class) - ) - ); - } - - protected function tearDown(): void - { - array_map(unlink(...), glob("{$this->path}/*")); - rmdir($this->path); - } - - public function test_create_session_from_container(): void - { - $session = $this->container->get(Session::class); - - $this->assertInstanceOf(Session::class, $session); - } - - public function test_put_get(): void - { - $session = $this->container->get(Session::class); - - $session->set('test', 'value'); - $value = $session->get('test'); - $this->assertEquals('value', $value); - } - - public function test_remove(): void - { - $session = $this->container->get(Session::class); - - $session->set('test', 'value'); - $session->remove('test'); - $value = $session->get('test'); - $this->assertNull($value); - } - - public function test_destroy(): void - { - $session = $this->container->get(Session::class); - - $path = path($this->path, (string) $session->id); - $this->assertFileExists($path); - $session->destroy(); - $this->assertFileDoesNotExist($path); - } - - public function test_is_valid(): void - { - $clock = $this->clock('2023-01-01 00:00:00'); - - $this->container->config(new SessionConfig( - path: __DIR__ . '/sessions', - expirationInSeconds: 1, - )); - - $sessionManager = $this->container->get(SessionManager::class); - - $this->assertFalse($sessionManager->isValid(new SessionId('unknown'))); - - $session = $sessionManager->create(new SessionId('new')); - - $this->assertTrue($session->isValid()); - - $clock->changeTime(seconds: 1); - - $this->assertFalse($session->isValid()); - } -} diff --git a/tests/Integration/Http/ResponseSenderInitializerTest.php b/tests/Integration/Http/ResponseSenderInitializerTest.php deleted file mode 100644 index 54b7c5c..0000000 --- a/tests/Integration/Http/ResponseSenderInitializerTest.php +++ /dev/null @@ -1,26 +0,0 @@ -assertInstanceOf( - GenericResponseSender::class, - $initializer->initialize($this->container) - ); - } -} diff --git a/tests/Integration/Http/SessionFromCookieTest.php b/tests/Integration/Http/SessionFromCookieTest.php deleted file mode 100644 index 76b0c05..0000000 --- a/tests/Integration/Http/SessionFromCookieTest.php +++ /dev/null @@ -1,56 +0,0 @@ -container->config(new SessionConfig( - path: __DIR__ . '/sessions', - idResolverClass: CookieSessionIdResolver::class, - )); - - $cookieManager = $this->container->get(CookieManager::class); - - $cookieManager->set('tempest_session_id', 'session_a'); - $sessionA = $this->container->get(Session::class); - $sessionA->set('test', 'a'); - - $cookieManager->set('tempest_session_id', 'session_b'); - $sessionB = $this->container->get(Session::class); - $this->assertNull($sessionB->get('test')); - - $cookieManager->set('tempest_session_id', 'session_a'); - $sessionA = $this->container->get(Session::class); - $this->assertEquals('a', $sessionA->get('test')); - } - - public function test_cookie_expiration(): void - { - $clock = $this->clock('2023-01-01 00:00:00'); - - $this->container->config(new SessionConfig( - path: __DIR__ . '/sessions', - expirationInSeconds: 1, - )); - - $this->container->get(Session::class); - $cookieManager = $this->container->get(CookieManager::class); - $cookie = $cookieManager->get('tempest_session_id'); - $this->assertEquals(1, $cookie->maxAge); - $this->assertEquals($clock->time() + 1, $cookie->getExpiresAtTime()); - } -} diff --git a/tests/Integration/Http/SessionFromHeaderTest.php b/tests/Integration/Http/SessionFromHeaderTest.php deleted file mode 100644 index 29d5a8c..0000000 --- a/tests/Integration/Http/SessionFromHeaderTest.php +++ /dev/null @@ -1,48 +0,0 @@ -container->config(new SessionConfig( - path: __DIR__ . '/sessions', - idResolverClass: HeaderSessionIdResolver::class, - )); - - $this->setSessionId('session_a'); - $sessionA = $this->container->get(Session::class); - $sessionA->set('test', 'a'); - - $this->setSessionId('session_b'); - $sessionB = $this->container->get(Session::class); - $this->assertNull($sessionB->get('test')); - - $this->setSessionId('session_a'); - $sessionA = $this->container->get(Session::class); - $this->assertEquals('a', $sessionA->get('test')); - } - - private function setSessionId(string $id): void - { - $request = new GenericRequest(Method::GET, '/', [], [Session::ID => $id]); - - $this->container->register(Request::class, fn () => $request); - $this->container->register(GenericRequest::class, fn () => $request); - } -} diff --git a/tests/Integration/Http/ValidationResponseTest.php b/tests/Integration/Http/ValidationResponseTest.php deleted file mode 100644 index 08819b7..0000000 --- a/tests/Integration/Http/ValidationResponseTest.php +++ /dev/null @@ -1,43 +0,0 @@ -http - ->post(uri([ValidationController::class, 'store']), ['number' => 11, 'item.number' => 11]) - ->assertRedirect(uri([ValidationController::class, 'store'])) - ->assertHasValidationError('number'); - - $this->http - ->get(uri([ValidationController::class, 'get'])) - ->assertOk() - ->assertHasNoValidationsErrors(); - } - - public function test_original_values(): void - { - $values = ['number' => 11, 'item.number' => 11]; - - $this->http - ->post(uri([ValidationController::class, 'store']), $values) - ->assertRedirect(uri([ValidationController::class, 'store'])) - ->assertHasValidationError('number') - ->assertHasSession(Session::ORIGINAL_VALUES, function (Session $session, array $data) use ($values) { - $this->assertEquals($values, $data); - }); - } -} diff --git a/tests/Integration/HttpClient/HttpClientDriverInitializerTest.php b/tests/Integration/HttpClient/HttpClientDriverInitializerTest.php deleted file mode 100644 index a352568..0000000 --- a/tests/Integration/HttpClient/HttpClientDriverInitializerTest.php +++ /dev/null @@ -1,24 +0,0 @@ -container->get(HttpClientDriver::class); - - $this->assertInstanceOf(HttpClientDriver::class, $driver); - $this->assertInstanceOf(Psr18Driver::class, $driver); - } -} diff --git a/tests/Integration/HttpClient/HttpClientInitializerTest.php b/tests/Integration/HttpClient/HttpClientInitializerTest.php deleted file mode 100644 index 1e553d8..0000000 --- a/tests/Integration/HttpClient/HttpClientInitializerTest.php +++ /dev/null @@ -1,24 +0,0 @@ -container->get(HttpClient::class); - - $this->assertInstanceOf(HttpClient::class, $httpClient); - $this->assertInstanceOf(GenericHttpClient::class, $httpClient); - } -} diff --git a/tests/Integration/Mapper/Fixtures/ObjectFactoryA.php b/tests/Integration/Mapper/Fixtures/ObjectFactoryA.php deleted file mode 100644 index b733156..0000000 --- a/tests/Integration/Mapper/Fixtures/ObjectFactoryA.php +++ /dev/null @@ -1,17 +0,0 @@ -from([ - 'id' => 1, - 'name' => 'test', - ]); - - $this->assertSame('test', $author->name); - $this->assertSame(1, $author->id->id); - } - - public function test_make_collection() - { - $authors = make(Author::class)->collection()->from([ - [ - 'id' => 1, - 'name' => 'test', - ], - ]); - - $this->assertCount(1, $authors); - $this->assertSame('test', $authors[0]->name); - $this->assertSame(1, $authors[0]->id->id); - } - - public function test_make_object_from_existing_object() - { - $author = Author::new( - name: 'original', - ); - - $author = make($author)->from([ - 'id' => 1, - 'name' => 'other', - ]); - - $this->assertSame('other', $author->name); - $this->assertSame(1, $author->id->id); - } - - public function test_make_object_with_map_to() - { - $author = Author::new( - name: 'original', - ); - - $author = map([ - 'id' => 1, - 'name' => 'other', - ])->to($author); - - $this->assertSame('other', $author->name); - $this->assertSame(1, $author->id->id); - } - - public function test_make_object_with_has_many_relation() - { - $author = make(Author::class)->from([ - 'name' => 'test', - 'books' => [ - ['title' => 'a'], - ['title' => 'b'], - ], - ]); - - $this->assertSame('test', $author->name); - $this->assertCount(2, $author->books); - $this->assertSame('a', $author->books[0]->title); - $this->assertSame('b', $author->books[1]->title); - $this->assertSame('test', $author->books[0]->author->name); - } - - public function test_make_object_with_one_to_one_relation() - { - $book = make(Book::class)->from([ - 'title' => 'test', - 'author' => [ - 'name' => 'author', - ], - ]); - - $this->assertSame('test', $book->title); - $this->assertSame('author', $book->author->name); - $this->assertSame('test', $book->author->books[0]->title); - } - - public function test_make_object_with_missing_values_throws_exception() - { - $this->expectException(MissingValuesException::class); - - make(Book::class)->from([ - 'title' => 'test', - 'author' => [ - ], - ]); - } - - public function test_caster_on_field() - { - $object = make(ObjectFactoryA::class)->from([ - 'prop' => [], - ]); - - $this->assertSame('casted', $object->prop); - } - - public function test_single_with_query() - { - $this->migrate( - CreateMigrationsTable::class, - ObjectFactoryAMigration::class, - ); - - ObjectFactoryA::create( - prop: 'a', - ); - - ObjectFactoryA::create( - prop: 'b', - ); - - $a = make(ObjectFactoryA::class)->from(new Query( - "SELECT * FROM ObjectFactoryA WHERE id = :id", - [ - 'id' => 1, - ], - )); - - $this->assertSame(1, $a->id->id); - $this->assertSame('casted', $a->prop); - - $collection = make(ObjectFactoryA::class)->from(new Query( - "SELECT * FROM ObjectFactoryA", - )); - - $this->assertCount(2, $collection); - $this->assertSame('casted', $collection[0]->prop); - $this->assertSame('casted', $collection[1]->prop); - } - - public function test_validation() - { - $this->expectException(ValidationException::class); - - map(['prop' => 'a'])->to(ObjectFactoryWithValidation::class); - } - - public function test_empty_string_can_cast_to_int(): void - { - $object = map(['prop' => ''])->to(ObjectWithIntProp::class); - - $this->assertEquals(0, $object->prop); - } - - public function test_empty_string_can_cast_to_float(): void - { - $object = map(['prop' => ''])->to(ObjectWithFloatProp::class); - - $this->assertEquals(0.0, $object->prop); - } - - public function test_empty_string_can_cast_to_bool(): void - { - $object = map(['prop' => ''])->to(ObjectWithBoolProp::class); - - $this->assertFalse($object->prop); - } -} diff --git a/tests/Integration/Mapper/PsrRequestToRequestMapperTest.php b/tests/Integration/Mapper/PsrRequestToRequestMapperTest.php deleted file mode 100644 index d505d85..0000000 --- a/tests/Integration/Mapper/PsrRequestToRequestMapperTest.php +++ /dev/null @@ -1,77 +0,0 @@ -assertTrue($mapper->canMap(from: $this->http->makePsrRequest('/'), to: PostRequest::class)); - $this->assertFalse($mapper->canMap(from: $this->http->makePsrRequest('/'), to: self::class)); - } - - public function test_map_with() - { - $mapper = new PsrRequestToRequestMapper(); - - $request = $mapper->map( - from: $this->http->makePsrRequest( - uri: '/', - body: ['title' => 'a', 'text' => 'b'], - headers: ['x-test' => 'test'], - ), - to: PostRequest::class, - ); - - $this->assertInstanceOf(PostRequest::class, $request); - $this->assertEquals('a', $request->title); - $this->assertEquals('b', $request->text); - $this->assertEquals(['x-test' => 'test'], $request->getHeaders()); - } - - public function test_map_with_with_missing_data() - { - $this->expectException(MissingValuesException::class); - - $mapper = new PsrRequestToRequestMapper(); - - try { - $mapper->map( - from: $this->http->makePsrRequest('/'), - to: PostRequest::class, - ); - } catch (MissingValuesException $exception) { - $this->assertStringContainsString('title', $exception->getMessage()); - $this->assertStringContainsString('text', $exception->getMessage()); - - throw $exception; - } - } - - public function test_generic_request_is_used_when_interface_is_passed() - { - $mapper = new PsrRequestToRequestMapper(); - - $request = $mapper->map( - from: $this->http->makePsrRequest('/'), - to: Request::class, - ); - - $this->assertInstanceOf(GenericRequest::class, $request); - } -} diff --git a/tests/Integration/ORM/Foo.php b/tests/Integration/ORM/Foo.php deleted file mode 100644 index ff59d87..0000000 --- a/tests/Integration/ORM/Foo.php +++ /dev/null @@ -1,15 +0,0 @@ -migrate( - CreateMigrationsTable::class, - FooMigration::class, - ); - - $foo = Foo::create( - bar: 'baz', - ); - - $this->assertSame('baz', $foo->bar); - $this->assertInstanceOf(Id::class, $foo->id); - - $foo = Foo::find($foo->id); - - $this->assertSame('baz', $foo->bar); - $this->assertInstanceOf(Id::class, $foo->id); - - $foo->update( - bar: 'boo', - ); - - $foo = Foo::find($foo->id); - - $this->assertSame('boo', $foo->bar); - } - - public function test_complex_query() - { - $this->migrate( - CreateMigrationsTable::class, - CreateAuthorTable::class, - CreateBookTable::class, - ); - - $book = Book::new( - title: 'Book Title', - author: new Author( - name: 'Author Name', - ), - ); - - $book = $book->save(); - - $book = Book::find($book->id, relations: [ - Author::class, - ]); - - $this->assertEquals(1, $book->id->id); - $this->assertSame('Book Title', $book->title); - $this->assertInstanceOf(Author::class, $book->author); - $this->assertSame('Author Name', $book->author->name); - $this->assertEquals(1, $book->author->id->id); - } -} diff --git a/tests/Integration/ORM/Mappers/QueryMapperTest.php b/tests/Integration/ORM/Mappers/QueryMapperTest.php deleted file mode 100644 index 973a31a..0000000 --- a/tests/Integration/ORM/Mappers/QueryMapperTest.php +++ /dev/null @@ -1,68 +0,0 @@ -from($author); - - $table = Author::table(); - - $this->assertSame("INSERT INTO {$table} (name) VALUES (:name);", $query->getSql()); - $this->assertSame(['name' => 'test'], $query->bindings); - } - - public function test_create_query_with_nested_relation() - { - $book = Book::new( - title: 'Book Title', - author: Author::new( - name: 'Author Name', - ), - ); - - $query = make(Query::class)->from($book); - - $bookTable = Book::table(); - - $this->assertSame("INSERT INTO {$bookTable} (title, author_id) VALUES (:title, :author_id);", $query->getSql()); - $this->assertSame(['title', 'author_id'], array_keys($query->bindings)); - $this->assertSame('Book Title', $query->bindings['title']); - - $authorTable = Author::table(); - - $authorQuery = $query->bindings['author_id']; - $this->assertInstanceOf(Query::class, $authorQuery); - $this->assertSame("INSERT INTO {$authorTable} (name) VALUES (:name);", $authorQuery->getSql()); - $this->assertSame('Author Name', $authorQuery->bindings['name']); - } - - public function test_update_query() - { - $author = Author::new(id: new Id(1), name: 'other'); - - $query = make(Query::class)->from($author); - - $table = Author::table(); - - $this->assertSame("UPDATE {$table} SET name = :name WHERE id = 1;", $query->getSql()); - $this->assertSame(['name' => 'other'], $query->bindings); - } -} diff --git a/tests/Integration/Route/RequestTest.php b/tests/Integration/Route/RequestTest.php deleted file mode 100644 index 4ff1414..0000000 --- a/tests/Integration/Route/RequestTest.php +++ /dev/null @@ -1,114 +0,0 @@ -value; - $_SERVER['REQUEST_URI'] = '/test'; - $_POST = ['test']; - $_SERVER['HTTP_X-TEST'] = 'test'; - $_COOKIE['test'] = 'test'; - - $request = (new RequestFactory())->make(); - - $this->assertEquals(Method::POST->value, $request->getMethod()); - $this->assertEquals('/test', $request->getUri()->getPath()); - $this->assertEquals(['test'], $request->getParsedBody()); - $this->assertEquals(['x-test' => ['test']], $request->getHeaders()); - $this->assertEquals(['test' => 'test'], $request->getCookieParams()); - } - - public function test_custom_request_test() - { - $response = $this->http - ->post( - uri: '/create-post', - body: [ - 'title' => 'test-title', - 'text' => 'test-text', - ], - ) - ->assertOk(); - - $this->assertEquals('test-title test-text', $response->getBody()); - } - - public function test_generic_request_can_map_to_custom_request() - { - $response = $this->http - ->post( - uri: '/create-post', - body: [ - 'title' => 'test-title', - 'text' => 'test-text', - ], - ) - ->assertOk(); - - $this->assertEquals('test-title test-text', $response->getBody()); - } - - public function test_custom_request_test_with_validation() - { - $this->migrate(CreateMigrationsTable::class, CreateBookTable::class); - - $this->http - ->post( - uri: uri([BookController::class, 'store']), - body: [ - 'title' => 'a', - ], - ) - ->assertStatus(Status::FOUND); - - $book = Book::find(new Id(1)); - $this->assertSame(1, $book->id->id); - $this->assertSame('a', $book->title); - } - - public function test_custom_request_test_with_nested_validation() - { - $this->migrate( - CreateMigrationsTable::class, - CreateBookTable::class, - CreateAuthorTable::class, - ); - - $this->http - ->post( - uri: uri([BookController::class, 'storeWithAuthor']), - body: [ - 'title' => 'a', - 'author.name' => 'b', - ], - ) - ->assertStatus(Status::FOUND); - - $book = Book::find(new Id(1), relations: [Author::class]); - $this->assertSame(1, $book->id->id); - $this->assertSame('a', $book->title); - $this->assertSame('b', $book->author->name); - } -} diff --git a/tests/Integration/Route/RouterTest.php b/tests/Integration/Route/RouterTest.php deleted file mode 100644 index c396d3f..0000000 --- a/tests/Integration/Route/RouterTest.php +++ /dev/null @@ -1,105 +0,0 @@ -container->get(GenericRouter::class); - - $response = $router->dispatch($this->http->makePsrRequest('/test')); - - $this->assertEquals(Status::OK, $response->getStatus()); - $this->assertEquals('test', $response->getBody()); - } - - public function test_dispatch_with_parameter() - { - $router = $this->container->get(GenericRouter::class); - - $response = $router->dispatch($this->http->makePsrRequest('/test/1/a')); - - $this->assertEquals(Status::OK, $response->getStatus()); - $this->assertEquals('1a', $response->getBody()); - } - - public function test_generate_uri() - { - $router = $this->container->get(GenericRouter::class); - - $this->assertEquals('/test/1/a', $router->toUri([TestController::class, 'withParams'], id: 1, name: 'a')); - $this->assertEquals('/test', $router->toUri(TestController::class)); - } - - public function test_with_view() - { - $router = $this->container->get(GenericRouter::class); - - $response = $router->dispatch($this->http->makePsrRequest('/view')); - - $this->assertEquals(Status::OK, $response->getStatus()); - - $expected = << - - - -Hello Brent! - -HTML; - - $this->assertEquals($expected, $response->getBody()); - } - - public function test_route_binding() - { - $this->migrate( - CreateMigrationsTable::class, - CreateBookTable::class, - CreateAuthorTable::class, - ); - - Book::create( - title: 'Test', - author: new Author(name: 'Brent'), - ); - - $router = $this->container->get(Router::class); - - $response = $router->dispatch($this->http->makePsrRequest('/books/1')); - - $this->assertSame(Status::OK, $response->getStatus()); - $this->assertSame('Test', $response->getBody()); - } - - public function test_middleware() - { - $router = $this->container->get(GenericRouter::class); - - $router->addMiddleware(TestGlobalMiddleware::class); - - $response = $router->dispatch($this->http->makePsrRequest('/with-middleware')); - - $this->assertEquals(['from-dependency'], $response->getHeader('middleware')->values); - $this->assertEquals(['yes'], $response->getHeader('global-middleware')->values); - } -} diff --git a/tests/Integration/Testing/Http/HttpRouterTesterIntegrationTest.php b/tests/Integration/Testing/Http/HttpRouterTesterIntegrationTest.php deleted file mode 100644 index 37f5e37..0000000 --- a/tests/Integration/Testing/Http/HttpRouterTesterIntegrationTest.php +++ /dev/null @@ -1,33 +0,0 @@ -http - ->get('/test') - ->assertOk(); - } - - public function test_get_requests_failure() - { - $this->expectException(AssertionFailedError::class); - - $this - ->http - ->get('/this-route-does-not-exist') - ->assertOk(); - } -} diff --git a/tests/Integration/Testing/Http/TestResponseHelperTest.php b/tests/Integration/Testing/Http/TestResponseHelperTest.php deleted file mode 100644 index 07984d5..0000000 --- a/tests/Integration/Testing/Http/TestResponseHelperTest.php +++ /dev/null @@ -1,205 +0,0 @@ -assertSame($response, $helper->getResponse()); - } - - public function test_assert_has_header() - { - $helper = new TestResponseHelper( - new GenericResponse( - status: Status::OK, - headers: ['Location' => '/new-location'] - ) - ); - - $helper->assertHasHeader('Location'); - } - - public function test_assert_has_header_failure() - { - $helper = new TestResponseHelper( - new GenericResponse( - status: Status::OK - ) - ); - - $this->expectException(AssertionFailedError::class); - - $helper->assertHasHeader('Location'); - } - - public function test_assert_header_value_equals() - { - $helper = new TestResponseHelper( - new GenericResponse( - status: Status::OK, - headers: ['Content-Type' => ['application/json']] - ) - ); - - $helper->assertHeaderContains('Content-Type', 'application/json'); - } - - public function test_assert_header_value_equals_failure() - { - $helper = new TestResponseHelper( - new GenericResponse(status: Status::OK) - ); - - $this->expectException(AssertionFailedError::class); - - $helper->assertHeaderContains('Content-Type', 'application/json'); - } - - public function test_assert_redirect() - { - $helper = new TestResponseHelper( - new GenericResponse( - status: Status::FOUND, - headers: [ - 'Location' => ['/other-location'], - ] - ) - ); - - $helper->assertRedirect(); - } - - public function test_assert_redirect_without_location_header() - { - $helper = new TestResponseHelper( - new GenericResponse(status: Status::FOUND) - ); - - $this->expectException(AssertionFailedError::class); - - $helper->assertRedirect(); - } - - public function test_assert_redirect_without_3xx_status_code() - { - $helper = new TestResponseHelper( - new GenericResponse( - status: Status::OK, - headers: ['Location' => '/other-location'] - ) - ); - - $this->expectException(AssertionFailedError::class); - - $helper->assertRedirect(); - } - - public function test_assert_redirect_to() - { - $helper = new TestResponseHelper( - new GenericResponse( - status: Status::FOUND, - headers: ['Location' => ['/other-location']] - ) - ); - - $helper->assertRedirect('/other-location'); - } - - public function test_assert_ok() - { - $helper = new TestResponseHelper( - new GenericResponse(status: Status::OK) - ); - - $helper->assertOk(); - } - - public function test_assert_ok_fails_with_not_okay_response() - { - $helper = new TestResponseHelper( - new GenericResponse(status: Status::INTERNAL_SERVER_ERROR) - ); - - $this->expectException(AssertionFailedError::class); - - $helper->assertOk(); - } - - public function test_assert_not_found() - { - $helper = new TestResponseHelper( - new GenericResponse(status: Status::NOT_FOUND) - ); - - $helper->assertNotFound(); - } - - public function test_assert_not_found_fails_with_okay_response() - { - $helper = new TestResponseHelper( - new GenericResponse(status: Status::OK) - ); - - $this->expectException(AssertionFailedError::class); - - $helper->assertNotFound(); - } - - /** - * @dataProvider provide_assert_status_cases - */ - public function test_assert_status(Status $expectedStatus, GenericResponse $response) - { - $helper = new TestResponseHelper($response); - - $helper->assertStatus($expectedStatus); - } - - /** - * @dataProvider provide_assert_status_fails_when_status_does_not_match_cases - */ - public function test_assert_status_fails_when_status_does_not_match(Status $expectedStatus, GenericResponse $response) - { - $helper = new TestResponseHelper($response); - - $this->expectException(AssertionFailedError::class); - - $helper->assertStatus($expectedStatus); - } - - public static function provide_assert_status_cases(): iterable - { - return [ - [Status::OK, new GenericResponse(status: Status::OK)], - [Status::CREATED, new GenericResponse(status: Status::CREATED)], - [Status::INTERNAL_SERVER_ERROR, new GenericResponse(status: Status::INTERNAL_SERVER_ERROR)], - ]; - } - - public static function provide_assert_status_fails_when_status_does_not_match_cases(): iterable - { - return [ - [Status::CREATED, new GenericResponse(status: Status::OK)], - [Status::OK, new GenericResponse(status: Status::CREATED)], - [Status::NOT_FOUND, new GenericResponse(status: Status::INTERNAL_SERVER_ERROR)], - ]; - } -} diff --git a/tests/Integration/View/ViewTest.php b/tests/Integration/View/ViewTest.php deleted file mode 100644 index 79fb805..0000000 --- a/tests/Integration/View/ViewTest.php +++ /dev/null @@ -1,155 +0,0 @@ -container->get(AppConfig::class); - - $view = new GenericView( - 'Views/overview.php', - params: [ - 'name' => 'Brent', - ], - ); - - $html = $view->render($appConfig); - - $expected = << - - - -Hello Brent! - -HTML; - - $this->assertEquals($expected, $html); - } - - public function test_render_with_view_model() - { - $appConfig = $this->container->get(AppConfig::class); - - $view = new ViewModel('Brent'); - - $html = $view->render($appConfig); - - $expected = <<assertEquals($expected, $html); - } - - public function test_with_view_function() - { - $appConfig = $this->container->get(AppConfig::class); - - $view = view('Views/overview.php')->data( - name: 'Brent', - ); - - $html = $view->render($appConfig); - - $expected = << - - - -Hello Brent! - -HTML; - - $this->assertEquals($expected, $html); - } - - public function test_raw_and_escaping() - { - $html = view('Views/rawAndEscaping.php')->data( - property: '

hi

', - )->render($this->container->get(AppConfig::class)); - - $expected = <<hi - HTML; - - $this->assertSame(trim($expected), trim($html)); - } - - public function test_extends_parameters() - { - $html = view('Views/extendsWithVariables.php')->render($this->container->get(AppConfig::class)); - - $this->assertStringContainsString('Test', $html); - $this->assertStringContainsString('

Hello

', $html); - } - - public function test_named_slots() - { - $html = view('Views/extendsWithNamedSlot.php')->render($this->container->get(AppConfig::class)); - - $this->assertStringContainsString( - needle: <<

beginning

-

in between

-

default slot

- HTML, - haystack: $html - ); - - $this->assertStringContainsString( - needle: <<

named slot

- HTML, - haystack: $html - ); - - $this->assertStringContainsString( - needle: <<

named slot 2

- HTML, - haystack: $html - ); - } - - public function test_include_parameters() - { - $html = view('Views/include-parent.php') - ->data(prop: 'test') - ->render($this->container->get(AppConfig::class)); - - $expected = <<assertSame(trim($expected), trim($html)); - } - - public function test_view_model_with_response_data() - { - $this->http - ->get(uri([TestController::class, 'viewModelWithResponseData'])) - ->assertHasHeader('x-from-viewmodel') - ->assertStatus(Status::CREATED); - } -} diff --git a/tests/Unit/Container/ContainerTest.php b/tests/Unit/Container/ContainerTest.php deleted file mode 100644 index 1d14e5a..0000000 --- a/tests/Unit/Container/ContainerTest.php +++ /dev/null @@ -1,192 +0,0 @@ -get(ContainerObjectB::class); - - $this->assertInstanceOf(ContainerObjectB::class, $b); - $this->assertInstanceOf(ContainerObjectA::class, $b->a); - } - - public function test_get_with_definition() - { - $container = new GenericContainer(); - - $container->register( - ContainerObjectC::class, - fn () => new ContainerObjectC(prop: 'test'), - ); - - $c = $container->get(ContainerObjectC::class); - - $this->assertEquals('test', $c->prop); - } - - public function test_get_with_initializer() - { - $container = new GenericContainer(initializers: [ - ContainerObjectD::class => ContainerObjectDInitializer::class, - ]); - - $d = $container->get(ContainerObjectD::class); - - $this->assertEquals('test', $d->prop); - } - - public function test_singleton() - { - $container = new GenericContainer(); - - $container->singleton(SingletonClass::class, fn () => new SingletonClass()); - - $instance = $container->get(SingletonClass::class); - - $this->assertEquals(1, $instance::$count); - - $instance = $container->get(SingletonClass::class); - - $this->assertEquals(1, $instance::$count); - } - - public function test_initialize_with_can_initializer() - { - $container = new GenericContainer(); - - $container->addInitializer(ContainerObjectEInitializer::class); - - $object = $container->get(ContainerObjectE::class); - - $this->assertInstanceOf(ContainerObjectE::class, $object); - } - - public function test_call_tries_to_transform_unmatched_values() - { - $container = new GenericContainer(); - $container->addInitializer(ContainerObjectEInitializer::class); - $classToCall = new CallContainerObjectE(); - - $return = $container->call($classToCall, 'method', input: '1'); - $this->assertInstanceOf(ContainerObjectE::class, $return); - $this->assertSame('default', $return->id); - - $return = $container->call($classToCall, 'method', input: new ContainerObjectE('other')); - $this->assertInstanceOf(ContainerObjectE::class, $return); - $this->assertSame('other', $return->id); - } - - public function test_arrays_are_automatically_created() - { - $container = new GenericContainer(); - - /** - * @var BuiltinArrayClass $class - */ - $class = $container->get(BuiltinArrayClass::class); - - $this->assertIsArray($class->anArray); - $this->assertEmpty($class->anArray); - } - - public function test_builtin_defaults_are_used() - { - $container = new GenericContainer(); - - /** - * @var BuiltinTypesWithDefaultsClass $class - */ - $class = $container->get(BuiltinTypesWithDefaultsClass::class); - - $this->assertSame('This is a default value', $class->aString); - } - - public function test_optional_types_resolve_to_null() - { - $container = new GenericContainer(); - - /** - * @var OptionalTypesClass $class - */ - $class = $container->get(OptionalTypesClass::class); - - $this->assertNull($class->aString); - } - - public function test_union_types_iterate_to_resolution() - { - $container = new GenericContainer(); - - /** @var UnionTypesClass $class */ - $class = $container->get(UnionTypesClass::class); - - $this->assertInstanceOf(UnionTypesClass::class, $class); - $this->assertInstanceOf(ContainerObjectA::class, $class->input); - } - - public function test_singleton_initializers() - { - $container = new GenericContainer(); - $container->addInitializer(SingletonInitializer::class); - - $a = $container->get(ContainerObjectE::class); - $b = $container->get(ContainerObjectE::class); - $this->assertSame(spl_object_id($a), spl_object_id($b)); - } - - public function test_union_initializers() - { - $container = new GenericContainer(); - $container->addInitializer(UnionInitializer::class); - - $a = $container->get(UnionInterfaceA::class); - $b = $container->get(UnionInterfaceB::class); - - $this->assertInstanceOf(UnionImplementation::class, $a); - $this->assertInstanceOf(UnionImplementation::class, $b); - } - - public function test_intersection_initializers() - { - $container = new GenericContainer(); - $container->addInitializer(IntersectionInitializer::class); - - $a = $container->get(UnionInterfaceA::class); - $b = $container->get(UnionInterfaceB::class); - - $this->assertInstanceOf(UnionImplementation::class, $a); - $this->assertInstanceOf(UnionImplementation::class, $b); - } -} diff --git a/tests/Unit/Container/Exceptions/CannotAutowireExceptionTest.php b/tests/Unit/Container/Exceptions/CannotAutowireExceptionTest.php deleted file mode 100644 index 57a40fd..0000000 --- a/tests/Unit/Container/Exceptions/CannotAutowireExceptionTest.php +++ /dev/null @@ -1,38 +0,0 @@ -expectException(CannotAutowireException::class); - - try { - $container = new GenericContainer(); - - $container->get(AutowireA::class); - } catch (CannotAutowireException $exception) { - $this->assertStringContainsString("Cannot autowire Tests\\Tempest\\Unit\\Container\\Fixtures\\AutowireA because Tests\\Tempest\\Unit\\Container\\Fixtures\\AutowireC cannot be resolved", $exception->getMessage()); - - $this->assertStringContainsString("┌── AutowireA::__construct(AutowireB \$b)", $exception->getMessage()); - $this->assertStringContainsString("├── AutowireB::__construct(AutowireC \$c)", $exception->getMessage()); - $this->assertStringContainsString("└── AutowireC::__construct(ContainerObjectA \$other, string \$unknown)", $exception->getMessage()); - $this->assertStringContainsString(" ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒", $exception->getMessage()); - $this->assertStringContainsString("CannotAutowireExceptionTest.php:25", $exception->getMessage()); - - throw $exception; - } - } -} diff --git a/tests/Unit/Container/Exceptions/CircularDependencyExceptionTest.php b/tests/Unit/Container/Exceptions/CircularDependencyExceptionTest.php deleted file mode 100644 index 40a4700..0000000 --- a/tests/Unit/Container/Exceptions/CircularDependencyExceptionTest.php +++ /dev/null @@ -1,59 +0,0 @@ -expectException(CircularDependencyException::class); - - try { - $container = new GenericContainer(); - - $container->get(CircularA::class); - } catch (CircularDependencyException $exception) { - $this->assertStringContainsString("Cannot autowire Tests\\Tempest\\Unit\\Container\\Fixtures\\CircularA because it has a circular dependency on Tests\\Tempest\\Unit\\Container\\Fixtures\\CircularA", $exception->getMessage()); - - $this->assertStringContainsString("┌─► CircularA::__construct(ContainerObjectA \$other, CircularB \$b)", $exception->getMessage()); - $this->assertStringContainsString("│ CircularB::__construct(CircularC \$c)", $exception->getMessage()); - $this->assertStringContainsString("│ CircularC::__construct(ContainerObjectA \$other, CircularA \$a)", $exception->getMessage()); - $this->assertStringContainsString("└───────────────────────────────────────────────────▒▒▒▒▒▒▒▒▒", $exception->getMessage()); - $this->assertStringContainsString("CircularDependencyExceptionTest.php:", $exception->getMessage()); - - throw $exception; - } - } - - public function test_circular_dependency_as_a_child_test() - { - $this->expectException(CircularDependencyException::class); - - try { - $container = new GenericContainer(); - - $container->get(CircularZ::class); - } catch (CircularDependencyException $exception) { - $this->assertStringContainsString("Cannot autowire Tests\\Tempest\\Unit\\Container\\Fixtures\\CircularZ because it has a circular dependency on Tests\\Tempest\\Unit\\Container\\Fixtures\\CircularA", $exception->getMessage()); - $this->assertStringContainsString(" CircularZ::__construct(CircularA \$a)", $exception->getMessage()); - $this->assertStringContainsString("┌─► CircularA::__construct(ContainerObjectA \$other, CircularB \$b)", $exception->getMessage()); - $this->assertStringContainsString("│ CircularB::__construct(CircularC \$c)", $exception->getMessage()); - $this->assertStringContainsString("│ CircularC::__construct(ContainerObjectA \$other, CircularA \$a)", $exception->getMessage()); - $this->assertStringContainsString("└───────────────────────────────────────────────────▒▒▒▒▒▒▒▒▒", $exception->getMessage()); - - throw $exception; - } - } -} diff --git a/tests/Unit/Container/Fixtures/AutowireA.php b/tests/Unit/Container/Fixtures/AutowireA.php deleted file mode 100644 index 4651c6e..0000000 --- a/tests/Unit/Container/Fixtures/AutowireA.php +++ /dev/null @@ -1,12 +0,0 @@ - ['application/json']] - ); - - $responseSender = new GenericResponseSender(); - - $this->assertSame($response, $responseSender->send($response)); - - ob_get_clean(); - } - - public function test_sending_of_array_to_json() - { - ob_start(); - - $response = new GenericResponse( - status: Status::CREATED, - body: ['key' => 'value'], - ); - - $responseSender = new GenericResponseSender(); - - $response = $responseSender->send($response); - - ob_get_clean(); - - $this->assertSame('{"key":"value"}', $response->getBody()); - $this->assertSame(['application/json'], $response->getHeader('Content-Type')->values); - } -} diff --git a/tests/Unit/Http/Responses/CreatedResponseTest.php b/tests/Unit/Http/Responses/CreatedResponseTest.php deleted file mode 100644 index 1037d5d..0000000 --- a/tests/Unit/Http/Responses/CreatedResponseTest.php +++ /dev/null @@ -1,26 +0,0 @@ - 'bar'])); - - $this->assertSame(Status::CREATED, $response->getStatus()); - $this->assertSame([], $response->getHeaders()); - $this->assertSame('{"foo":"bar"}', $response->getBody()); - $this->assertNotSame(Status::OK, $response->getStatus()); - } -} diff --git a/tests/Unit/Http/StatusTest.php b/tests/Unit/Http/StatusTest.php deleted file mode 100644 index 2c0ebfe..0000000 --- a/tests/Unit/Http/StatusTest.php +++ /dev/null @@ -1,150 +0,0 @@ -assertSame( - $this->descriptionToStatus($description), - $status - ); - - $this->assertSame($description, $status->description()); - - if ($code >= 100 && $code < 200) { - $this->assertTrue($status->isInformational()); - $this->assertFalse($status->isSuccessful()); - $this->assertFalse($status->isRedirect()); - $this->assertFalse($status->isClientError()); - $this->assertFalse($status->isServerError()); - } - - if ($code >= 200 && $code < 300) { - $this->assertFalse($status->isInformational()); - $this->assertTrue($status->isSuccessful()); - $this->assertFalse($status->isRedirect()); - $this->assertFalse($status->isClientError()); - $this->assertFalse($status->isServerError()); - } - - if ($code >= 300 && $code < 400) { - $this->assertFalse($status->isInformational()); - $this->assertFalse($status->isSuccessful()); - $this->assertTrue($status->isRedirect()); - $this->assertFalse($status->isClientError()); - $this->assertFalse($status->isServerError()); - } - - if ($code >= 400 && $code < 500) { - $this->assertFalse($status->isInformational()); - $this->assertFalse($status->isSuccessful()); - $this->assertFalse($status->isRedirect()); - $this->assertTrue($status->isClientError()); - $this->assertFalse($status->isServerError()); - } - - if ($code >= 500 && $code < 600) { - $this->assertFalse($status->isInformational()); - $this->assertFalse($status->isSuccessful()); - $this->assertFalse($status->isRedirect()); - $this->assertFalse($status->isClientError()); - $this->assertTrue($status->isServerError()); - } - } - - public static function provide_status_code_cases(): iterable - { - return [ - [100, 'Continue'], - [101, 'Switching Protocols'], - [102, 'Processing'], - [103, 'Early Hints'], - - [200, 'OK'], - [201, 'Created'], - [202, 'Accepted'], - [203, 'Non-Authoritative Information'], - [204, 'No Content'], - [205, 'Reset Content'], - [206, 'Partial Content'], - [207, 'Multi-Status'], - [208, 'Already Reported'], - [226, 'IM Used'], - - [300, 'Multiple Choices'], - [301, 'Moved Permanently'], - [302, 'Found'], - [303, 'See Other'], - [304, 'Not Modified'], - [305, 'Use Proxy'], - [307, 'Temporary Redirect'], - [308, 'Permanent Redirect'], - - [400, 'Bad Request'], - [401, 'Unauthorized'], - [402, 'Payment Required'], - [403, 'Forbidden'], - [404, 'Not Found'], - [405, 'Method Not Allowed'], - [406, 'Not Acceptable'], - [407, 'Proxy Authentication Required'], - [408, 'Request Timeout'], - [409, 'Conflict'], - [410, 'Gone'], - [411, 'Length Required'], - [412, 'Precondition Failed'], - [413, 'Content Too Large'], - [414, 'URI Too Long'], - [415, 'Unsupported Media Type'], - [416, 'Range Not Satisfiable'], - [417, 'Expectation Failed'], - [421, 'Misdirected Request'], - [422, 'Unprocessable Content'], - [423, 'Locked'], - [424, 'Failed Dependency'], - [425, 'Too Early'], - [426, 'Upgrade Required'], - [428, 'Precondition Required'], - [429, 'Too Many Requests'], - [431, 'Request Header Fields Too Large'], - [451, 'Unavailable For Legal Reasons'], - - [500, 'Internal Server Error'], - [501, 'Not Implemented'], - [502, 'Bad Gateway'], - [503, 'Service Unavailable'], - [504, 'Gateway Timeout'], - [505, 'HTTP Version Not Supported'], - [506, 'Variant Also Negotiates'], - [507, 'Insufficient Storage'], - [508, 'Loop Detected'], - [510, 'Not Extended'], - [511, 'Network Authentication Required'], - ]; - } -} diff --git a/tests/Unit/HttpClient/GenericHttpClientTest.php b/tests/Unit/HttpClient/GenericHttpClientTest.php deleted file mode 100644 index c44ad50..0000000 --- a/tests/Unit/HttpClient/GenericHttpClientTest.php +++ /dev/null @@ -1,153 +0,0 @@ -client->sendRequest($request); - - $this - ->mock - ->assertMethod('PUT') - ->assertUri('/testing-put'); - } - - public function test_get_proxies_to_http_client() - { - $this->client->get('/test-get'); - - $this - ->mock - ->assertMethod('GET') - ->assertUri('/test-get'); - } - - public function test_get_with_headers_proxies_to_http_client_with_headers() - { - $this->client->get('/test-get-with-headers', [ - 'X-Tempest' => 'We love Tempest!', - ]); - - $this - ->mock - ->assertMethod('GET') - ->assertHeaderEquals('X-Tempest', 'We love Tempest!'); - } - - public function test_head_proxies_to_http_client() - { - $this->client->head('/test-head'); - - $this - ->mock - ->assertMethod('HEAD') - ->assertUri('/test-head'); - } - - public function test_post_proxies_to_http_client() - { - $this->client->post(uri: '/test-post', body: '{"test":"value"}'); - - $this - ->mock - ->assertMethod('POST') - ->assertUri('/test-post') - ->assertBodyIs('{"test":"value"}'); - } - - public function test_trace_proxies_to_http_client() - { - $this->client->trace('/test-trace'); - - $this - ->mock - ->assertMethod('TRACE') - ->assertUri('/test-trace'); - } - - public function test_put_proxies_to_http_client() - { - $this->client->put(uri: '/test-put', body: '{"test":"test-value"}'); - - $this - ->mock - ->assertMethod('PUT') - ->assertUri('/test-put') - ->assertBodyIs('{"test":"test-value"}'); - } - - public function test_patch_proxies_to_http_client() - { - $this->client->patch(uri: '/test-patch', body: '{"firstName":"Dwight"}'); - - $this - ->mock - ->assertMethod('PATCH') - ->assertUri('/test-patch') - ->assertBodyIs('{"firstName":"Dwight"}'); - } - - public function test_delete_proxies_to_http_client() - { - $this->client->delete(uri: '/test-delete'); - - $this - ->mock - ->assertMethod('DELETE') - ->assertUri('/test-delete'); - } - - public function test_options_proxies_to_http_client() - { - $this->client->options('/test-options'); - - $this - ->mock - ->assertMethod('OPTIONS') - ->assertUri('/test-options'); - } - - protected function setUp(): void - { - parent::setUp(); - - $this->factory = new HttpFactory(); - - $this->mock = new Client( - responseFactory: $this->factory, - streamFactory: $this->factory - ); - - $psr18Driver = new Psr18Driver( - client: $this->mock, - uriFactory: $this->factory, - requestFactory: $this->factory, - streamFactory: $this->factory - ); - - $this->client = new GenericHttpClient($psr18Driver); - } -} diff --git a/tests/Unit/KernelTest.php b/tests/Unit/KernelTest.php deleted file mode 100644 index 01d955b..0000000 --- a/tests/Unit/KernelTest.php +++ /dev/null @@ -1,42 +0,0 @@ -init(); - - $config = $container->get(RouteConfig::class); - - $this->assertTrue(count($config->staticRoutes) > 1); - } -} diff --git a/tests/Unit/Support/ArrayHelperTest.php b/tests/Unit/Support/ArrayHelperTest.php deleted file mode 100644 index 0900c88..0000000 --- a/tests/Unit/Support/ArrayHelperTest.php +++ /dev/null @@ -1,166 +0,0 @@ - 'Jim']; - - $value = ArrayHelper::get($array, 'firstName'); - - $this->assertSame('Jim', $value); - } - - public function test_getting_array_value_with_dot_notation() - { - $array = [ - 'person' => [ - 'firstName' => 'Jim', - ], - ]; - - $value = ArrayHelper::get($array, 'person.firstName'); - - $this->assertSame('Jim', $value); - } - - public function test_getting_non_existent_value_with_dot_notation() - { - $array = []; - - $value = ArrayHelper::get($array, 'person.firstName', 'This is the default'); - - $this->assertSame('This is the default', $value); - } - - public function test_has_key_with_single_key() - { - $array = ['firstName' => 'Jim']; - - $this->assertTrue(ArrayHelper::has($array, 'firstName')); - $this->assertFalse(ArrayHelper::has($array, 'lastName')); - } - - public function test_has_key_with_dot_notation() - { - $array = [ - 'person' => ['firstName' => 'Jim'], - ]; - - $this->assertTrue(ArrayHelper::has($array, 'person.firstName')); - $this->assertFalse(ArrayHelper::has($array, 'person.lastName')); - } - - public function test_setting_array_value_with_single_key() - { - $array = []; - - ArrayHelper::set($array, 'test', 'testing'); - - $this->assertSame( - ['test' => 'testing'], - $array - ); - } - - public function test_setting_array_value_with_dot_notation() - { - $array = []; - - ArrayHelper::set($array, 'test.key', 'Bob'); - - $this->assertEqualsCanonicalizing( - [ - 'test' => ['key' => 'Bob'], - ], - $array - ); - } - - public function test_unwrap_single_key() - { - $this->assertSame( - ['a' => 'a'], - (new ArrayHelper())->unwrap(['a' => 'a']), - ); - } - - public function test_unwrap_nested_key() - { - $this->assertSame( - [ - 'a' => [ - 'b' => 'ab', - ], - ], - (new ArrayHelper())->unwrap(['a.b' => 'ab']), - ); - } - - public function test_unwrap_several_items() - { - $this->assertSame( - ['a' => 'a', 'b' => 'b'], - (new ArrayHelper())->unwrap(['a' => 'a', 'b' => 'b']), - ); - } - - public function test_unwrap_nested_key_multiple_items() - { - $this->assertSame( - [ - 'a' => [ - 'x', - 'y', - ], - ], - (new ArrayHelper())->unwrap(['a.0' => 'x', 'a.1' => 'y']), - ); - } - - public function test_unwrap_real() - { - $this->assertSame( - [ - 'author' => [ - 'name' => 'Brent', - 'books' => [ - ['title' => 'a'], - ['title' => 'b'], - ], - ], - ], - (new ArrayHelper())->unwrap([ - 'author.name' => 'Brent', - 'author.books.0.title' => 'a', - 'author.books.1.title' => 'b', - ]), - ); - } - - public function test_to_array_with_nested_property() - { - $this->assertSame( - [ - 'a' => [ - 'b' => 'ab', - ], - ], - (new ArrayHelper())->toArray( - key: 'a.b', - value: 'ab', - ), - ); - } -} diff --git a/tests/Unit/Validation/Fixtures/ObjectToBeValidated.php b/tests/Unit/Validation/Fixtures/ObjectToBeValidated.php deleted file mode 100644 index 6b13697..0000000 --- a/tests/Unit/Validation/Fixtures/ObjectToBeValidated.php +++ /dev/null @@ -1,16 +0,0 @@ -assertSame('Value must be a date after ' . $date->format("Y-m-d H:i:s"), $rule->message()); - - $this->assertTrue($rule->isValid($date->modify('+1 minute'))); - $this->assertFalse($rule->isValid($date->modify('-1 second'))); - $this->assertFalse($rule->isValid($date)); - } - - public function test_it_works_with_inclusive_param(): void - { - $date = new DateTimeImmutable(); - $rule = new AfterDate($date, inclusive: true); - - $this->assertSame('Value must be a date after or equal to ' . $date->format("Y-m-d H:i:s"), $rule->message()); - - $this->assertTrue($rule->isValid($date->modify('+1 minute'))); - $this->assertFalse($rule->isValid($date->modify('-1 second'))); - $this->assertTrue($rule->isValid($date)); - } - - public function test_it_works_with_timezones(): void - { - // given we create a date in a specific timezone (UTC-5) - $date = new DateTimeImmutable('now', new DateTimeZone('America/New_York')); - $rule = new AfterDate($date, inclusive: false); - - $utcDate = new DateTimeImmutable(); - - // when we validate the date, it doesn't matter that timezones are different, - // it'll compare the UTC timestamps - $this->assertTrue($utcDate->format('Y-m-d H:i:s') > $date->format('Y-m-d H:i:s')); - $this->assertTrue($rule->isValid($utcDate->modify('+1 minute'))); - $this->assertFalse($rule->isValid($utcDate->modify('-1 minute'))); - } -} diff --git a/tests/Unit/Validation/Rules/AlphaNumericTest.php b/tests/Unit/Validation/Rules/AlphaNumericTest.php deleted file mode 100644 index a6f1a40..0000000 --- a/tests/Unit/Validation/Rules/AlphaNumericTest.php +++ /dev/null @@ -1,25 +0,0 @@ -assertSame('Value should only contain alphanumeric characters', $rule->message()); - $this->assertFalse($rule->isValid('string_123')); - $this->assertTrue($rule->isValid('string123')); - $this->assertTrue($rule->isValid('STRING123')); - } -} diff --git a/tests/Unit/Validation/Rules/AlphaTest.php b/tests/Unit/Validation/Rules/AlphaTest.php deleted file mode 100644 index 61dce8c..0000000 --- a/tests/Unit/Validation/Rules/AlphaTest.php +++ /dev/null @@ -1,25 +0,0 @@ -assertSame('Value should only contain alphabetic characters', $rule->message()); - $this->assertFalse($rule->isValid('string123')); - $this->assertTrue($rule->isValid('string')); - $this->assertTrue($rule->isValid('STRING')); - } -} diff --git a/tests/Unit/Validation/Rules/BeforeDateTest.php b/tests/Unit/Validation/Rules/BeforeDateTest.php deleted file mode 100644 index 3d0ba45..0000000 --- a/tests/Unit/Validation/Rules/BeforeDateTest.php +++ /dev/null @@ -1,56 +0,0 @@ -assertSame('Value must be a date before ' . $date->format("Y-m-d H:i:s"), $rule->message()); - - $this->assertFalse($rule->isValid($date->modify('+1 minute'))); - $this->assertTrue($rule->isValid($date->modify('-1 second'))); - $this->assertTrue($rule->isValid($date)); - } - - public function test_it_works_with_inclusive_param(): void - { - $date = new DateTimeImmutable(); - $rule = new BeforeDate($date, inclusive: true); - - $this->assertSame('Value must be a date before or equal to ' . $date->format("Y-m-d H:i:s"), $rule->message()); - - $this->assertFalse($rule->isValid($date->modify('+1 minute'))); - $this->assertTrue($rule->isValid($date->modify('-1 second'))); - $this->assertFalse($rule->isValid($date)); - } - - public function test_it_works_with_timezones(): void - { - // given we create a date in a specific timezone (UTC-5) - $date = new DateTimeImmutable('now', new DateTimeZone('America/New_York')); - $rule = new BeforeDate($date, inclusive: false); - - $utcDate = new DateTimeImmutable(); - - // when we validate the date, it doesn't matter that timezones are different, - // it'll compare the UTC timestamps - $this->assertTrue($utcDate->format('Y-m-d H:i:s') > $date->format('Y-m-d H:i:s')); - $this->assertFalse($rule->isValid($utcDate->modify('+1 minute'))); - $this->assertTrue($rule->isValid($utcDate->modify('-1 minute'))); - } -} diff --git a/tests/Unit/Validation/Rules/BetweenTest.php b/tests/Unit/Validation/Rules/BetweenTest.php deleted file mode 100644 index 7f38eeb..0000000 --- a/tests/Unit/Validation/Rules/BetweenTest.php +++ /dev/null @@ -1,28 +0,0 @@ -assertSame('Value should be between 0 and 10', $rule->message()); - - $this->assertTrue($rule->isValid(0)); - $this->assertTrue($rule->isValid(10)); - $this->assertTrue($rule->isValid(5)); - $this->assertFalse($rule->isValid(11)); - $this->assertFalse($rule->isValid(-1)); - } -} diff --git a/tests/Unit/Validation/Rules/BooleanTest.php b/tests/Unit/Validation/Rules/BooleanTest.php deleted file mode 100644 index 14ebe75..0000000 --- a/tests/Unit/Validation/Rules/BooleanTest.php +++ /dev/null @@ -1,39 +0,0 @@ -assertTrue($rule->isValid(true)); - $this->assertTrue($rule->isValid('true')); - $this->assertTrue($rule->isValid(1)); - $this->assertTrue($rule->isValid('1')); - $this->assertTrue($rule->isValid(false)); - $this->assertTrue($rule->isValid('false')); - $this->assertTrue($rule->isValid(0)); - $this->assertTrue($rule->isValid('0')); - $this->assertFalse($rule->isValid(5)); - $this->assertFalse($rule->isValid(2.5)); - $this->assertFalse($rule->isValid('string')); - } - - public function test_boolean_message() - { - $rule = new Boolean(); - - $this->assertSame('Value should represent a boolean value', $rule->message()); - } -} diff --git a/tests/Unit/Validation/Rules/CountTest.php b/tests/Unit/Validation/Rules/CountTest.php deleted file mode 100644 index 5cbb354..0000000 --- a/tests/Unit/Validation/Rules/CountTest.php +++ /dev/null @@ -1,90 +0,0 @@ -assertEquals($expected, $rule->isValid($stringToTest)); - } - - /** - * @dataProvider provide_returns_the_proper_message_based_on_min_and_max_arguments_cases - */ - public function test_returns_the_proper_message_based_on_min_and_max_arguments( - Count $rule, - string $expectedMessage - ): void { - $this->assertEquals($expectedMessage, $rule->message()); - } - - public function test_throws_an_exception_if_neither_min_or_max_is_supplied(): void - { - $this->expectException(InvalidArgumentException::class); - - new Count(); - } - - public static function provide_returns_the_proper_message_based_on_min_and_max_arguments_cases(): iterable - { - return [ - 'Should provide correct message when both min and max limits are defined (1, 5)' => [ - new Count(min: 1, max: 5), - 'Array should contain between 1 and 5 items', - ], - 'Should provide correct message when only min limit is defined (1)' => [ - new Count(min: 1), - 'Array should contain no less than 1 items', - ], - 'Should provide correct message when only max limit is defined (5)' => [ - new Count(max: 5), - 'Array should contain no more than 5 items', - ], - ]; - } - - public static function provide_count_cases(): iterable - { - return [ - 'Should invalidate when array length is less than the minimum limit (1)' => [ - new Count(min: 1, max: 5), - [], - false, - ], - 'Should validate when array length is exactly the minimum limit (1)' => [ - new Count(min: 1, max: 5), - [1], - true, - ], - 'Should validate when array length is between the minimum (1) and maximum (5) limits' => [ - new Count(min: 1, max: 5), - [1, 2, 3], - true, - ], - 'Should validate when array length is exactly at the maximum limit (5)' => [ - new Count(min: 1, max: 5), - [1, 2, 3, 4, 5], - true, - ], - 'Should invalidate when array length is greater than the maximum limit (5)' => [ - new Count(min: 1, max: 5), - [1, 2, 3, 4, 5, 6], - false, - ], - ]; - } -} diff --git a/tests/Unit/Validation/Rules/DateTimeFormatTest.php b/tests/Unit/Validation/Rules/DateTimeFormatTest.php deleted file mode 100644 index 41089d5..0000000 --- a/tests/Unit/Validation/Rules/DateTimeFormatTest.php +++ /dev/null @@ -1,48 +0,0 @@ -assertFalse($rule->isValid(false)); - $this->assertFalse($rule->isValid(null)); - $this->assertFalse($rule->isValid('')); - $this->assertFalse($rule->isValid('this is not a date')); - $this->assertTrue($rule->isValid('2024-02-19')); - } - - public function test_datetime_format_with_different_format() - { - $rule = new DateTimeFormat('d/m/Y'); - - $this->assertFalse($rule->isValid('2024-02-19')); - $this->assertTrue($rule->isValid('19/02/2024')); - } - - public function test_datetime_format_with_integer_value() - { - $rule = new DateTimeFormat(); - - $this->assertFalse($rule->isValid(1)); - } - - public function test_datetime_format_message() - { - $rule = new DateTimeFormat(); - - $this->assertSame('Value should be a valid datetime in the format Y-m-d', $rule->message()); - } -} diff --git a/tests/Unit/Validation/Rules/DivisibleByTest.php b/tests/Unit/Validation/Rules/DivisibleByTest.php deleted file mode 100644 index a38fbe5..0000000 --- a/tests/Unit/Validation/Rules/DivisibleByTest.php +++ /dev/null @@ -1,30 +0,0 @@ -assertTrue($rule->isValid(10)); - $this->assertTrue($rule->isValid(5)); - $this->assertFalse($rule->isValid(0)); - - $this->assertFalse($rule->isValid(3)); - $this->assertFalse($rule->isValid(4)); - $this->assertFalse($rule->isValid(6)); - - $this->assertSame('Value should be divisible by 5', $rule->message()); - } -} diff --git a/tests/Unit/Validation/Rules/DoesNotEndWithTest.php b/tests/Unit/Validation/Rules/DoesNotEndWithTest.php deleted file mode 100644 index d515b72..0000000 --- a/tests/Unit/Validation/Rules/DoesNotEndWithTest.php +++ /dev/null @@ -1,46 +0,0 @@ -assertSame('Value should not end with ' . $needle, $rule->message()); - - $this->assertEquals($expected, $rule->isValid($stringToTest)); - } - - public static function provide_rule_cases(): iterable - { - return [ - 'should return false if it ends with the given string' => ['test', 'this is a test', false], - 'should return true if it does not end with the given string' => ['test', 'test this is a', true], - 'should return true for an empty string' => ['test', '', true], - 'should return true for a single non-matching character' => ['test', 'a', true], - 'should return false for a matching character string' => ['a', 'banana', false], - 'should return true if it ends with a different string' => [ - 'test', - 'this is a test best', - true, - ], - 'should return true if the string is the reverse of the given string' => ['test', 'tset', true], - 'should return false if the string and given string are the same' => ['test', 'test', false], - ]; - } -} diff --git a/tests/Unit/Validation/Rules/DoesNotStartWithTest.php b/tests/Unit/Validation/Rules/DoesNotStartWithTest.php deleted file mode 100644 index 258fe00..0000000 --- a/tests/Unit/Validation/Rules/DoesNotStartWithTest.php +++ /dev/null @@ -1,43 +0,0 @@ -assertSame('Value should not start with ' . $needle, $rule->message()); - - $this->assertEquals($expected, $rule->isValid($stringToTest)); - } - - public static function provide_rule_cases(): iterable - { - return [ - 'should return false if it starts with the given string' => ['test', 'test this is a test', false], - 'should return true if it does not start with the given string' => ['test', 'this is a test', true], - 'should return true for an empty string' => ['test', '', true], - 'should return true for a single non-matching character' => ['test', 'a', true], - 'should return false for a matching character string' => ['a', 'apple', false], - 'should return true if it starts with a different string' => ['test', 'best this is a test', true], - 'should return true if the string is the reverse of the given string' => ['test', 'tset', true], - 'should return false if the string and given string are the same' => ['test', 'test', false], - ]; - } -} diff --git a/tests/Unit/Validation/Rules/EmailTest.php b/tests/Unit/Validation/Rules/EmailTest.php deleted file mode 100644 index 5d389f7..0000000 --- a/tests/Unit/Validation/Rules/EmailTest.php +++ /dev/null @@ -1,24 +0,0 @@ -assertSame('Value should be a valid email address', $rule->message()); - $this->assertFalse($rule->isValid('this is not an email')); - $this->assertTrue($rule->isValid('jim.halpert@dundermifflinpaper.biz')); - } -} diff --git a/tests/Unit/Validation/Rules/EndsWithTest.php b/tests/Unit/Validation/Rules/EndsWithTest.php deleted file mode 100644 index 8ee5a2d..0000000 --- a/tests/Unit/Validation/Rules/EndsWithTest.php +++ /dev/null @@ -1,27 +0,0 @@ -assertSame('Value should end with ab', $rule->message()); - - $this->assertTrue($rule->isValid('ab')); - $this->assertTrue($rule->isValid('cab')); - $this->assertFalse($rule->isValid('b')); - $this->assertFalse($rule->isValid('3434')); - } -} diff --git a/tests/Unit/Validation/Rules/EnumTest.php b/tests/Unit/Validation/Rules/EnumTest.php deleted file mode 100644 index 0ba8180..0000000 --- a/tests/Unit/Validation/Rules/EnumTest.php +++ /dev/null @@ -1,66 +0,0 @@ -assertSame( - sprintf( - 'The value must be a valid enumeration [%s] case', - SomeEnum::class - ), - $rule->message() - ); - - $this->assertFalse($rule->isValid('NOPE_NOT_HERE')); - $this->assertFalse($rule->isValid('NOPE_NOT_HERE_EITHER')); - $this->assertTrue($rule->isValid('VALUE_1')); - $this->assertTrue($rule->isValid('VALUE_2')); - } - - public function test_validating_backed_enums() - { - $rule = new Enum(SomeBackedEnum::class); - - $this->assertSame( - sprintf( - 'The value must be a valid enumeration [%s] case', - SomeBackedEnum::class - ), - $rule->message() - ); - - $this->assertFalse($rule->isValid('three')); - $this->assertFalse($rule->isValid('four')); - $this->assertTrue($rule->isValid('one')); - $this->assertTrue($rule->isValid('two')); - } - - public function test_enum_has_to_exist() - { - $this->expectExceptionObject(new UnexpectedValueException( - sprintf( - 'The enum parameter must be a valid enum. Was given [%s].', - 'Bob' - ) - )); - - new Enum('Bob'); - } -} diff --git a/tests/Unit/Validation/Rules/EvenRuleTest.php b/tests/Unit/Validation/Rules/EvenRuleTest.php deleted file mode 100644 index b0632d4..0000000 --- a/tests/Unit/Validation/Rules/EvenRuleTest.php +++ /dev/null @@ -1,29 +0,0 @@ -assertTrue($rule->isValid(4)); - $this->assertTrue($rule->isValid(2)); - $this->assertTrue($rule->isValid(0)); - - $this->assertFalse($rule->isValid(1)); - $this->assertFalse($rule->isValid(3)); - - $this->assertSame('Value should be an even number', $rule->message()); - } -} diff --git a/tests/Unit/Validation/Rules/Fixtures/SomeBackedEnum.php b/tests/Unit/Validation/Rules/Fixtures/SomeBackedEnum.php deleted file mode 100644 index 7fd9e23..0000000 --- a/tests/Unit/Validation/Rules/Fixtures/SomeBackedEnum.php +++ /dev/null @@ -1,11 +0,0 @@ -assertSame('Value should be a valid IP address', $rule->message()); - - $this->assertTrue($rule->isValid('192.168.0.1')); - $this->assertTrue($rule->isValid('10.0.0.1')); - $this->assertTrue($rule->isValid('172.16.0.1')); - $this->assertTrue($rule->isValid('2001:0db8:85a3:0000:0000:8a2e:0370:7334')); - $this->assertTrue($rule->isValid('2001:db8:85a3::8a2e:370:7334')); - - $this->assertFalse($rule->isValid('256.0.0.1')); - $this->assertFalse($rule->isValid('300.168.0.1')); - $this->assertFalse($rule->isValid('192.168.0')); - $this->assertFalse($rule->isValid('192.168.0.1.2')); - $this->assertFalse($rule->isValid('192.168.0.1/24')); - } - - public function test_messages() - { - $rule = new IP(); - $this->assertSame('Value should be a valid IP address', $rule->message()); - - $rule = new IP(allowPrivateRange: false); - $this->assertSame('Value should be a valid IP address that is not in a private range', $rule->message()); - - $rule = new IP(allowReservedRange: false); - $this->assertSame('Value should be a valid IP address that is not in a reserved range', $rule->message()); - - $rule = new IP(allowPrivateRange: false, allowReservedRange: false); - $this->assertSame('Value should be a valid IP address that is not in a private range and not in a reserved range', $rule->message()); - } -} diff --git a/tests/Unit/Validation/Rules/IPv4Test.php b/tests/Unit/Validation/Rules/IPv4Test.php deleted file mode 100644 index fc02346..0000000 --- a/tests/Unit/Validation/Rules/IPv4Test.php +++ /dev/null @@ -1,60 +0,0 @@ -assertSame('Value should be a valid IPv4 address', $rule->message()); - - $this->assertTrue($rule->isValid('192.168.0.1')); - $this->assertTrue($rule->isValid('10.0.0.1')); - $this->assertTrue($rule->isValid('172.16.0.1')); - - $this->assertFalse($rule->isValid('2001:0db8:85a3:0000:0000:8a2e:0370:7334')); - $this->assertFalse($rule->isValid('2001:db8:85a3::8a2e:370:7334')); - } - - public function test_ip_address_without_private_range() - { - $rule = new IPv4(allowPrivateRange: false); - - $this->assertFalse($rule->isValid('192.168.1.1')); - $this->assertTrue($rule->isValid('210.221.151.70')); - } - - public function test_ip_address_without_reserved_range() - { - $rule = new IPv4(allowReservedRange: false); - - $this->assertFalse($rule->isValid('169.254.0.0')); - $this->assertTrue($rule->isValid('172.16.1.1')); - } - - public function test_messages() - { - $rule = new IPv4(); - $this->assertSame('Value should be a valid IPv4 address', $rule->message()); - - $rule = new IPv4(allowPrivateRange: false); - $this->assertSame('Value should be a valid IPv4 address that is not in a private range', $rule->message()); - - $rule = new IPv4(allowReservedRange: false); - $this->assertSame('Value should be a valid IPv4 address that is not in a reserved range', $rule->message()); - - $rule = new IPv4(allowPrivateRange: false, allowReservedRange: false); - $this->assertSame('Value should be a valid IPv4 address that is not in a private range and not in a reserved range', $rule->message()); - } -} diff --git a/tests/Unit/Validation/Rules/IPv6Test.php b/tests/Unit/Validation/Rules/IPv6Test.php deleted file mode 100644 index 6814beb..0000000 --- a/tests/Unit/Validation/Rules/IPv6Test.php +++ /dev/null @@ -1,66 +0,0 @@ -assertSame('Value should be a valid IPv6 address', $rule->message()); - - $this->assertTrue($rule->isValid('2001:0db8:85a3:0000:0000:8a2e:0370:7334')); - $this->assertTrue($rule->isValid('2a03:b0c0:3:d0::11f5:3001')); - - $this->assertFalse($rule->isValid('192.168.0.1')); - $this->assertFalse($rule->isValid('10.0.0.1')); - $this->assertFalse($rule->isValid('172.16.0.1')); - } - - public function test_ip_address_without_private_range() - { - $rule = new IPv6(allowPrivateRange: false); - $this->assertFalse($rule->isValid('fd36:ecf4:e32b:5e21:aaaa:aaaa:aaaa:aaaa')); - $this->assertTrue($rule->isValid('2a03:b0c0:3:d0::11f5:3001')); - - $rule = new IPv6(allowPrivateRange: true); - $this->assertTrue($rule->isValid('fd36:ecf4:e32b:5e21:aaaa:aaaa:aaaa:aaaa')); - $this->assertTrue($rule->isValid('2a03:b0c0:3:d0::11f5:3001')); - } - - public function test_ip_address_without_reserved_range() - { - $rule = new IPv6(allowReservedRange: false); - $this->assertFalse($rule->isValid('2001:0db8:0000:08d3:0000:8a2e:0070:7344')); - $this->assertTrue($rule->isValid('2a03:b0c0:3:d0::11f5:3001')); - - $rule = new IPv6(allowReservedRange: true); - $this->assertTrue($rule->isValid('2001:0db8:0000:08d3:0000:8a2e:0070:7344')); - $this->assertTrue($rule->isValid('2a03:b0c0:3:d0::11f5:3001')); - } - - public function test_messages() - { - $rule = new IPv6(); - $this->assertSame('Value should be a valid IPv6 address', $rule->message()); - - $rule = new IPv6(allowPrivateRange: false); - $this->assertSame('Value should be a valid IPv6 address that is not in a private range', $rule->message()); - - $rule = new IPv6(allowReservedRange: false); - $this->assertSame('Value should be a valid IPv6 address that is not in a reserved range', $rule->message()); - - $rule = new IPv6(allowPrivateRange: false, allowReservedRange: false); - $this->assertSame('Value should be a valid IPv6 address that is not in a private range and not in a reserved range', $rule->message()); - } -} diff --git a/tests/Unit/Validation/Rules/InTest.php b/tests/Unit/Validation/Rules/InTest.php deleted file mode 100644 index f64665e..0000000 --- a/tests/Unit/Validation/Rules/InTest.php +++ /dev/null @@ -1,29 +0,0 @@ -assertTrue($rule->isValid(4)); - $this->assertTrue($rule->isValid(2)); - $this->assertTrue($rule->isValid(0)); - - $this->assertFalse($rule->isValid(1)); - $this->assertFalse($rule->isValid(3)); - - $this->assertSame('Value should be one of: 4, 2, 0', $rule->message()); - } -} diff --git a/tests/Unit/Validation/Rules/JSONTest.php b/tests/Unit/Validation/Rules/JSONTest.php deleted file mode 100644 index 999966e..0000000 --- a/tests/Unit/Validation/Rules/JSONTest.php +++ /dev/null @@ -1,50 +0,0 @@ -assertTrue($rule->isValid('{"test": "test"}')); - } - - public function test_it_returns_false_for_invalid_json_string(): void - { - $rule = new Json(); - $this->assertFalse($rule->isValid('{"test": test}')); - } - - public function test_it_allows_to_specify_depth(): void - { - // Not sure if there is a better way of asserting that a php function was called with a given argument - $this->expectException(ValueError::class); - $rule = new Json(depth: 0); // we intentionally send something that is not valid - $rule->isValid('{"test": "test"}'); - } - - public function test_it_allows_to_specify_flags(): void - { - // Not sure if there is a better way of asserting that a php function was called with a given argument - $this->expectException(ValueError::class); - $rule = new Json(flags: 232312312); // we intentionally send something that is not valid - $rule->isValid('{"test": "test"}'); - } - - public function test_it_returns_the_proper_message(): void - { - $rule = new Json(); - $this->assertEquals('Value should be a valid JSON string', $rule->message()); - } -} diff --git a/tests/Unit/Validation/Rules/LengthTest.php b/tests/Unit/Validation/Rules/LengthTest.php deleted file mode 100644 index 2ce87c6..0000000 --- a/tests/Unit/Validation/Rules/LengthTest.php +++ /dev/null @@ -1,135 +0,0 @@ -assertEquals($expected, $rule->isValid($stringToTest)); - } - - /** - * @dataProvider provide_returns_the_proper_message_based_on_min_and_max_arguments_cases - */ - public function test_returns_the_proper_message_based_on_min_and_max_arguments( - Length $rule, - string $expectedMessage - ): void { - $this->assertEquals($expectedMessage, $rule->message()); - } - - public function test_throws_an_exception_if_neither_min_or_max_is_supplied(): void - { - $this->expectException(InvalidArgumentException::class); - - new Length(); - } - - public static function provide_returns_the_proper_message_based_on_min_and_max_arguments_cases(): iterable - { - return [ - 'Should provide correct message for string length validation with both minimum and maximum limits of 10 to 20' => [ - new Length(min: 10, max: 20), - 'Value should be between 10 and 20', - ], - 'Should provide correct message for string length validation being no less than 10' => [ - new Length(min: 10), - 'Value should be no less than 10', - ], - 'Should provide correct message for string length validation being no more than 10' => [ - new Length(max: 10), - 'Value should be no more than 10', - ], - ]; - } - - public static function provide_length_cases(): iterable - { - return [ - 'Should return true when string meets minimum length requirement of 10' => [ - new Length(min: 10), - 'aaaaaaaaaa', - true, - ], - 'Should return true when string exceeds minimum length requirement of 10' => [ - new Length(min: 10), - 'aaaaaaaaaaa', - true, - ], - 'Should return false when string does not meet minimum length requirement of 10' => [ - new Length(min: 10), - 'aaaaaaaaa', - false, - ], - 'Should return true when string meets maximum length requirement of 5' => [ - new Length(max: 5), - 'aaaaa', - true, - ], - 'Should return true when string is shorter than maximum length requirement of 5' => [ - new Length(max: 5), - 'aaaa', - true, - ], - 'Should return false when string exceeds maximum length requirement of 5' => [ - new Length(max: 5), - 'aaaaaa', - false, - ], - 'Should return true when string is within minimum and maximum length requirement of 2-5' => [ - new Length( - min: 2, - max: 5 - ), - 'aaaaa', - true, - ], - 'Should return true when string is within minimum and maximum length requirement of 2-5 but shorter' => [ - new Length( - min: 2, - max: 5 - ), - 'aaaa', - true, - ], - 'Should return true when string meets minimum length requirement of 2 within 2-5 limit' => [ - new Length( - min: 2, - max: 5 - ), - 'aa', - true, - ], - 'Should return false when string does not meet minimum length requirement of 2 within 2-5 limit' => [ - new Length( - min: 2, - max: 5 - ), - 'a', - false, - ], - 'Should return false when string exceeds maximum length requirement of 5 within 2-5 limit' => [ - new Length( - min: 2, - max: 5 - ), - 'aaaaaa', - false, - ], - ]; - } -} diff --git a/tests/Unit/Validation/Rules/LowercaseTest.php b/tests/Unit/Validation/Rules/LowercaseTest.php deleted file mode 100644 index 3feccdb..0000000 --- a/tests/Unit/Validation/Rules/LowercaseTest.php +++ /dev/null @@ -1,28 +0,0 @@ -assertSame('Value should be a lowercase string', $rule->message()); - - $this->assertTrue($rule->isValid('abc')); - $this->assertTrue($rule->isValid('àbç')); - $this->assertFalse($rule->isValid('ABC')); - $this->assertFalse($rule->isValid('ÀBÇ')); - $this->assertFalse($rule->isValid('AbC')); - } -} diff --git a/tests/Unit/Validation/Rules/MACAddressTest.php b/tests/Unit/Validation/Rules/MACAddressTest.php deleted file mode 100644 index 3452ef8..0000000 --- a/tests/Unit/Validation/Rules/MACAddressTest.php +++ /dev/null @@ -1,33 +0,0 @@ -assertSame('Value should be a valid MAC Address', $rule->message()); - $this->assertTrue($rule->isValid('00:1A:2B:3C:4D:5E')); - $this->assertTrue($rule->isValid('01-23-45-67-89-AB')); - $this->assertTrue($rule->isValid('A1:B2:C3:D4:E5:F6')); - $this->assertTrue($rule->isValid('a1:b2:c3:d4:e5:f6')); - $this->assertTrue($rule->isValid('FF:FF:FF:FF:FF:FF')); - - $this->assertFalse($rule->isValid('00:1A:2B:3C:4D')); - $this->assertFalse($rule->isValid('01-23-45-67-89-AB-CD')); - $this->assertFalse($rule->isValid('A1:B2:C3:D4:E5:G6')); - $this->assertFalse($rule->isValid('a1:b2:c3:d4:e5:f6:7')); - $this->assertFalse($rule->isValid('FF:FF:FF:FF:FF')); - } -} diff --git a/tests/Unit/Validation/Rules/MultipleOfTest.php b/tests/Unit/Validation/Rules/MultipleOfTest.php deleted file mode 100644 index 11bedd9..0000000 --- a/tests/Unit/Validation/Rules/MultipleOfTest.php +++ /dev/null @@ -1,30 +0,0 @@ -assertTrue($rule->isValid(10)); - $this->assertTrue($rule->isValid(5)); - $this->assertTrue($rule->isValid(0)); - - $this->assertFalse($rule->isValid(3)); - $this->assertFalse($rule->isValid(4)); - $this->assertFalse($rule->isValid(6)); - - $this->assertSame('Value should be a multiple of 5', $rule->message()); - } -} diff --git a/tests/Unit/Validation/Rules/NotEmptyTest.php b/tests/Unit/Validation/Rules/NotEmptyTest.php deleted file mode 100644 index fd8447f..0000000 --- a/tests/Unit/Validation/Rules/NotEmptyTest.php +++ /dev/null @@ -1,24 +0,0 @@ -assertTrue($rule->isValid('t')); - $this->assertFalse($rule->isValid('')); - $this->assertFalse($rule->isValid(1)); - } -} diff --git a/tests/Unit/Validation/Rules/NotInTest.php b/tests/Unit/Validation/Rules/NotInTest.php deleted file mode 100644 index 2b79d76..0000000 --- a/tests/Unit/Validation/Rules/NotInTest.php +++ /dev/null @@ -1,29 +0,0 @@ -assertFalse($rule->isValid(4)); - $this->assertFalse($rule->isValid(2)); - $this->assertFalse($rule->isValid(0)); - - $this->assertTrue($rule->isValid(1)); - $this->assertTrue($rule->isValid(3)); - - $this->assertSame('Value cannot be any of: 4, 2, 0', $rule->message()); - } -} diff --git a/tests/Unit/Validation/Rules/OddRuleTest.php b/tests/Unit/Validation/Rules/OddRuleTest.php deleted file mode 100644 index 080f48e..0000000 --- a/tests/Unit/Validation/Rules/OddRuleTest.php +++ /dev/null @@ -1,29 +0,0 @@ -assertFalse($rule->isValid(4)); - $this->assertFalse($rule->isValid(2)); - $this->assertFalse($rule->isValid(0)); - - $this->assertTrue($rule->isValid(1)); - $this->assertTrue($rule->isValid(3)); - - $this->assertSame('Value should be an odd number', $rule->message()); - } -} diff --git a/tests/Unit/Validation/Rules/PasswordTest.php b/tests/Unit/Validation/Rules/PasswordTest.php deleted file mode 100644 index fb73bf8..0000000 --- a/tests/Unit/Validation/Rules/PasswordTest.php +++ /dev/null @@ -1,92 +0,0 @@ -assertTrue($rule->isValid('123456789012')); - $this->assertTrue($rule->isValid('aaaaaaaaaaaa')); - } - - public function test_invalid_input() - { - $rule = new Password(); - $this->assertFalse($rule->isValid(123456789012)); - $this->assertFalse($rule->isValid([123456789012])); - } - - public function test_minimum() - { - $rule = new Password(min: 4); - $this->assertTrue($rule->isValid('12345')); - $this->assertTrue($rule->isValid('1234')); - $this->assertFalse($rule->isValid('123')); - } - - public function test_mixed_case() - { - $rule = new Password(mixedCase: true); - $this->assertTrue($rule->isValid('abcdEFGHIJKL')); - $this->assertFalse($rule->isValid('abcdefghijkl')); - $this->assertFalse($rule->isValid('ABCDEFGHIJKL')); - } - - public function test_letters() - { - $rule = new Password(letters: true); - $this->assertTrue($rule->isValid('12345678901a')); - $this->assertFalse($rule->isValid('123456789012')); - } - - public function test_numbers() - { - $rule = new Password(numbers: true); - $this->assertTrue($rule->isValid('123456789012')); - $this->assertTrue($rule->isValid('1aaaaaaaaaaa')); - $this->assertFalse($rule->isValid('abcdefghijkl')); - } - - public function test_symbols() - { - $rule = new Password(symbols: true); - $this->assertTrue($rule->isValid('123456789012@')); - $this->assertFalse($rule->isValid('123456789012')); - } - - public function test_message() - { - $rule = new Password(); - $this->assertSame('Value should contain at least 12 characters', $rule->message()); - - $rule = new Password(min: 4); - $this->assertSame('Value should contain at least 4 characters', $rule->message()); - - $rule = new Password(mixedCase: true); - $this->assertSame('Value should contain at least 12 characters and at least one uppercase and one lowercase letter', $rule->message()); - - $rule = new Password(letters: true); - $this->assertSame('Value should contain at least 12 characters and at least one letter', $rule->message()); - - $rule = new Password(numbers: true); - $this->assertSame('Value should contain at least 12 characters and at least one number', $rule->message()); - - $rule = new Password(symbols: true); - $this->assertSame('Value should contain at least 12 characters and at least one symbol', $rule->message()); - - $rule = new Password(min: 4, mixedCase: true, letters: true, numbers: true, symbols: true); - $this->assertSame('Value should contain at least 4 characters, at least one uppercase and one lowercase letter, at least one number, at least one letter and at least one symbol', $rule->message()); - } -} diff --git a/tests/Unit/Validation/Rules/PhoneNumberTest.php b/tests/Unit/Validation/Rules/PhoneNumberTest.php deleted file mode 100644 index 1c2c2fc..0000000 --- a/tests/Unit/Validation/Rules/PhoneNumberTest.php +++ /dev/null @@ -1,37 +0,0 @@ -assertSame('Value should be a valid phone number', $rule->message()); - - $this->assertFalse($rule->isValid('this is not a phone number')); - $this->assertFalse($rule->isValid('john.doe@example.com')); - $this->assertTrue($rule->isValid('+1 (805) 380-4329')); - $this->assertTrue($rule->isValid('+32 0497 88 93 11')); - - $rule = new PhoneNumber('US'); - - $this->assertSame('Value should be a valid US phone number', $rule->message()); - $this->assertTrue($rule->isValid('(805) 380-4329')); - - $rule = new PhoneNumber('BE'); - - $this->assertSame('Value should be a valid BE phone number', $rule->message()); - $this->assertTrue($rule->isValid('0497 88 93 11')); - } -} diff --git a/tests/Unit/Validation/Rules/RegexTest.php b/tests/Unit/Validation/Rules/RegexTest.php deleted file mode 100644 index b47ae53..0000000 --- a/tests/Unit/Validation/Rules/RegexTest.php +++ /dev/null @@ -1,32 +0,0 @@ -assertSame( - 'The value must match the regular expression pattern: /^[aA][bB]$/', - $rule->message() - ); - - $this->assertFalse($rule->isValid('cd')); - $this->assertFalse($rule->isValid('za')); - - $this->assertTrue($rule->isValid('ab')); - $this->assertTrue($rule->isValid('AB')); - $this->assertTrue($rule->isValid('Ab')); - } -} diff --git a/tests/Unit/Validation/Rules/ShouldBeFalseTest.php b/tests/Unit/Validation/Rules/ShouldBeFalseTest.php deleted file mode 100644 index 26be977..0000000 --- a/tests/Unit/Validation/Rules/ShouldBeFalseTest.php +++ /dev/null @@ -1,36 +0,0 @@ -assertFalse($rule->isValid(true)); - $this->assertFalse($rule->isValid('true')); - $this->assertFalse($rule->isValid(1)); - $this->assertFalse($rule->isValid('1')); - $this->assertTrue($rule->isValid(false)); - $this->assertTrue($rule->isValid('false')); - $this->assertTrue($rule->isValid(0)); - $this->assertTrue($rule->isValid('0')); - } - - public function test_should_be_false_message() - { - $rule = new ShouldBeFalse(); - - $this->assertSame('Value should represent a boolean false value.', $rule->message()); - } -} diff --git a/tests/Unit/Validation/Rules/ShouldBeTrueTest.php b/tests/Unit/Validation/Rules/ShouldBeTrueTest.php deleted file mode 100644 index fab8628..0000000 --- a/tests/Unit/Validation/Rules/ShouldBeTrueTest.php +++ /dev/null @@ -1,36 +0,0 @@ -assertFalse($rule->isValid(false)); - $this->assertFalse($rule->isValid('false')); - $this->assertFalse($rule->isValid(0)); - $this->assertFalse($rule->isValid('0')); - $this->assertTrue($rule->isValid(true)); - $this->assertTrue($rule->isValid('true')); - $this->assertTrue($rule->isValid(1)); - $this->assertTrue($rule->isValid('1')); - } - - public function test_should_be_true_message() - { - $rule = new ShouldBeTrue(); - - $this->assertSame('Value should represent a boolean true value.', $rule->message()); - } -} diff --git a/tests/Unit/Validation/Rules/StartsWithTest.php b/tests/Unit/Validation/Rules/StartsWithTest.php deleted file mode 100644 index ac27e27..0000000 --- a/tests/Unit/Validation/Rules/StartsWithTest.php +++ /dev/null @@ -1,27 +0,0 @@ -assertSame('Value should start with ab', $rule->message()); - - $this->assertTrue($rule->isValid('ab')); - $this->assertTrue($rule->isValid('abc')); - $this->assertFalse($rule->isValid('a')); - $this->assertFalse($rule->isValid('3434')); - } -} diff --git a/tests/Unit/Validation/Rules/TimeTest.php b/tests/Unit/Validation/Rules/TimeTest.php deleted file mode 100644 index eeeeb25..0000000 --- a/tests/Unit/Validation/Rules/TimeTest.php +++ /dev/null @@ -1,86 +0,0 @@ -assertSame('Value should be a valid time in the format of hh:mm xm', $rule->message()); - - $this->assertFalse($rule->isValid('0001')); - $this->assertFalse($rule->isValid('01:00')); - $this->assertFalse($rule->isValid('200')); - $this->assertFalse($rule->isValid('01:60 a.m.')); - $this->assertFalse($rule->isValid('23:00')); - $this->assertFalse($rule->isValid('2300')); - - - $this->assertTrue($rule->isValid('01:00 am')); - $this->assertTrue($rule->isValid('01:00 a.m.')); - $this->assertTrue($rule->isValid('01:00 A.M.')); - $this->assertTrue($rule->isValid('01:00 AM')); - $this->assertTrue($rule->isValid('01:00 pm')); - $this->assertTrue($rule->isValid('01:00 p.m.')); - $this->assertTrue($rule->isValid('01:00 P.M.')); - $this->assertTrue($rule->isValid('01:00 PM')); - $this->assertTrue($rule->isValid('01:59 a.m.')); - } - - public function test_military_time() - { - $rule = new Time(twentyFourHour: true); - - $this->assertSame('Value should be a valid time in the 24-hour format of hh:mm', $rule->message()); - - $this->assertFalse($rule->isValid('2400')); - $this->assertFalse($rule->isValid('01:00 am')); - $this->assertFalse($rule->isValid('01:00 a.m.')); - $this->assertFalse($rule->isValid('01:00 A.M.')); - $this->assertFalse($rule->isValid('01:00 AM')); - $this->assertFalse($rule->isValid('01:00 pm')); - $this->assertFalse($rule->isValid('01:00 p.m.')); - $this->assertFalse($rule->isValid('01:00 P.M.')); - $this->assertFalse($rule->isValid('01:00 PM')); - $this->assertFalse($rule->isValid('01:59 a.m.')); - $this->assertFalse($rule->isValid('24:00')); - - $this->assertTrue($rule->isValid('23:00')); - $this->assertTrue($rule->isValid('2300')); - $this->assertTrue($rule->isValid('0100')); - $this->assertTrue($rule->isValid('0200')); - $this->assertTrue($rule->isValid('0300')); - $this->assertTrue($rule->isValid('0400')); - $this->assertTrue($rule->isValid('0500')); - $this->assertTrue($rule->isValid('0600')); - $this->assertTrue($rule->isValid('0700')); - $this->assertTrue($rule->isValid('0800')); - $this->assertTrue($rule->isValid('0900')); - $this->assertTrue($rule->isValid('1000')); - $this->assertTrue($rule->isValid('1100')); - $this->assertTrue($rule->isValid('1200')); - $this->assertTrue($rule->isValid('1300')); - $this->assertTrue($rule->isValid('1400')); - $this->assertTrue($rule->isValid('1500')); - $this->assertTrue($rule->isValid('1600')); - $this->assertTrue($rule->isValid('1700')); - $this->assertTrue($rule->isValid('1800')); - $this->assertTrue($rule->isValid('1900')); - $this->assertTrue($rule->isValid('2000')); - $this->assertTrue($rule->isValid('2100')); - $this->assertTrue($rule->isValid('2200')); - $this->assertTrue($rule->isValid('2300')); - $this->assertTrue($rule->isValid('2340')); - } -} diff --git a/tests/Unit/Validation/Rules/TimestampTest.php b/tests/Unit/Validation/Rules/TimestampTest.php deleted file mode 100644 index f62c6dc..0000000 --- a/tests/Unit/Validation/Rules/TimestampTest.php +++ /dev/null @@ -1,30 +0,0 @@ -assertTrue($rule->isValid(time())); - $this->assertFalse($rule->isValid('2021-01-01')); - } - - public function test_timestamp_message() - { - $rule = new Timestamp(); - - $this->assertSame('Value should be a valid timestamp', $rule->message()); - } -} diff --git a/tests/Unit/Validation/Rules/TimezoneTest.php b/tests/Unit/Validation/Rules/TimezoneTest.php deleted file mode 100644 index 7f10998..0000000 --- a/tests/Unit/Validation/Rules/TimezoneTest.php +++ /dev/null @@ -1,62 +0,0 @@ -assertSame('Value should be a valid timezone', $rule->message()); - - $this->assertFalse($rule->isValid('invalid_timezone')); - $this->assertFalse($rule->isValid('Asia/Sydney')); - $this->assertTrue($rule->isValid('America/New_York')); - $this->assertTrue($rule->isValid('Europe/London')); - $this->assertTrue($rule->isValid('Europe/Paris')); - $this->assertTrue($rule->isValid('UTC')); - } - - public function test_timezone_with_country_code() - { - $rule = new Timezone(DateTimeZone::PER_COUNTRY, 'AU'); - - $this->assertFalse($rule->isValid('America/New_York')); - $this->assertTrue($rule->isValid('Australia/Sydney')); - $this->assertTrue($rule->isValid('Australia/Melbourne')); - - $rule = new Timezone(DateTimeZone::PER_COUNTRY, 'US'); - - $this->assertFalse($rule->isValid('Europe/Paris')); - $this->assertTrue($rule->isValid('America/New_York')); - $this->assertTrue($rule->isValid('America/Los_Angeles')); - $this->assertTrue($rule->isValid('America/Chicago')); - } - - public function test_timezone_with_group() - { - $rule = new Timezone(DateTimeZone::ASIA); - - $this->assertFalse($rule->isValid('Africa/Nairobi')); - $this->assertTrue($rule->isValid('Asia/Tokyo')); - $this->assertTrue($rule->isValid('Asia/Hong_Kong')); - $this->assertTrue($rule->isValid('Asia/Singapore')); - - $rule = new Timezone(DateTimeZone::INDIAN); - - $this->assertFalse($rule->isValid('Europe/Paris')); - $this->assertTrue($rule->isValid('Indian/Reunion')); - $this->assertTrue($rule->isValid('Indian/Comoro')); - } -} diff --git a/tests/Unit/Validation/Rules/UlidTest.php b/tests/Unit/Validation/Rules/UlidTest.php deleted file mode 100644 index 946cf77..0000000 --- a/tests/Unit/Validation/Rules/UlidTest.php +++ /dev/null @@ -1,29 +0,0 @@ -assertSame('Value should be a valid ULID', $rule->message()); - - $this->assertTrue($rule->isValid('01FV8CE8P3XVZTVK0S6F05Z5ZA')); - $this->assertTrue($rule->isValid('01fv8ce8p3xvztvk0S6f05z5za')); - $this->assertFalse($rule->isValid('01FV8CE8P3XVZTVK0S6F05Z5ZU')); // contains invalid character - $this->assertFalse($rule->isValid('01FV8CE8P3XVZTVK0S6F05')); // too short - $this->assertFalse($rule->isValid('01FV8CE8P3XVZTVK0S6F05Z5ZAAAAA')); // too long - - } -} diff --git a/tests/Unit/Validation/Rules/UppercaseTest.php b/tests/Unit/Validation/Rules/UppercaseTest.php deleted file mode 100644 index 596167e..0000000 --- a/tests/Unit/Validation/Rules/UppercaseTest.php +++ /dev/null @@ -1,28 +0,0 @@ -assertSame('Value should be an uppercase string', $rule->message()); - - $this->assertTrue($rule->isValid('ABC')); - $this->assertTrue($rule->isValid('ÀBÇ')); - $this->assertFalse($rule->isValid('abc')); - $this->assertFalse($rule->isValid('àbç')); - $this->assertFalse($rule->isValid('AbC')); - } -} diff --git a/tests/Unit/Validation/Rules/UrlTest.php b/tests/Unit/Validation/Rules/UrlTest.php deleted file mode 100644 index 767bab0..0000000 --- a/tests/Unit/Validation/Rules/UrlTest.php +++ /dev/null @@ -1,47 +0,0 @@ -assertFalse($rule->isValid('this is not a url')); - $this->assertFalse($rule->isValid('https://https://example.com')); - $this->assertTrue($rule->isValid('https://example.com')); - $this->assertTrue($rule->isValid('http://example.com')); - } - - public function test_url_with_restricted_protocols() - { - $rule = new Url(['https']); - - $this->assertFalse($rule->isValid('http://example.com')); - $this->assertTrue($rule->isValid('https://example.com')); - } - - public function test_url_with_integer_value() - { - $rule = new Url(); - - $this->assertFalse($rule->isValid(1)); - } - - public function test_url_message() - { - $rule = new Url(); - - $this->assertSame('Value should be a valid URL', $rule->message()); - } -} diff --git a/tests/Unit/Validation/Rules/UuidTest.php b/tests/Unit/Validation/Rules/UuidTest.php deleted file mode 100644 index 36b9047..0000000 --- a/tests/Unit/Validation/Rules/UuidTest.php +++ /dev/null @@ -1,36 +0,0 @@ -assertSame('Value should contain a valid UUID', $rule->message()); - - $this->assertFalse($rule->isValid('string_123')); - - // UUID v1 - $this->assertTrue($rule->isValid('CB2F46B4-D0C6-11EE-A506-0242AC120002')); - $this->assertTrue($rule->isValid('cb2f46b4-d0c6-11ee-a506-0242ac120002')); - - // UUID v4 - $this->assertTrue($rule->isValid('0EC29141-3D58-4187-B664-2D93B7DA0D31')); - $this->assertTrue($rule->isValid('0ec29141-3d58-4187-b664-2d93b7da0d31')); - - // UUID v7 - $this->assertTrue($rule->isValid('018DCC19-7E65-7C4B-9B14-9A11DF3E0FDB')); - $this->assertTrue($rule->isValid('018dcc19-7e65-7c4b-9b14-9a11df3e0fdb')); - } -} diff --git a/tests/Unit/Validation/ValidatorTest.php b/tests/Unit/Validation/ValidatorTest.php deleted file mode 100644 index 0ea0e9f..0000000 --- a/tests/Unit/Validation/ValidatorTest.php +++ /dev/null @@ -1,26 +0,0 @@ -expectException(ValidationException::class); - - $validator = new Validator(); - - $validator->validate(new ObjectToBeValidated(name: 'a')); - } -} diff --git a/tests/bootstrap.php b/tests/bootstrap.php deleted file mode 100644 index 6c2ff58..0000000 --- a/tests/bootstrap.php +++ /dev/null @@ -1,7 +0,0 @@ -