Find framework reference pages for handlers, routes, middleware, modules, database, views, and security.

Testing An App

Tests protect your application code while CorianderCore can update independently.

What To Test First

Start with the behavior that would hurt if it broke:

  • route smoke tests
  • repository methods
  • permission services
  • validation rules
  • Markdown/documentation links, for documentation sites
  • generated downloads, for guided projects

Module Unit Test

Modules are the easiest app code to test because they should not depend on HTTP rendering.

use App\Modules\Blog\BlogValidator;
use PHPUnit\Framework\TestCase;

final class BlogValidatorTest extends TestCase
{
    public function testTitleIsRequired(): void
    {
        $errors = (new BlogValidator())->validatePost([
            'title' => '',
            'body' => 'Content',
        ]);

        self::assertArrayHasKey('title', $errors);
    }
}

Route Smoke Test

Smoke tests check that important public routes still respond after framework updates.

public function testDocumentationRouteResponds(): void
{
    $request = new \Nyholm\Psr7\ServerRequest('GET', '/documentation');
    $response = (new \CorianderCore\Core\Router\Router())->handle($request);

    self::assertSame(200, $response->getStatusCode());
    self::assertStringContainsString('Documentation', (string) $response->getBody());
}

Prefer focused route smoke tests over browser-heavy tests for basic coverage.

Bootstrap the test's environment, configuration, and autoloaders first. Use an isolated test database and session storage, never your production database. The router test exercises middleware and handlers, not the front controller's parsing or HTTP emission; add an HTTP check for those boundaries.

For JSON integration requests, use RequestFactory::fromGlobals() or set withParsedBody($payload) on a constructed PSR request. Cookie-authenticated writes need a valid csrf_token body field; do not disable root middleware in a permission test.

Repository Tests

For repository code, use a test database when possible.

SQLite is practical for fast local tests. If production uses MySQL-specific SQL, add at least one integration check against MySQL before release.

Permission Tests

Permission services should be deterministic.

public function testAdminCanEditAnyPost(): void
{
    $service = new BlogPermissionService();

    self::assertTrue($service->canEdit(
        ['id' => 1, 'role' => 'admin'],
        ['author_id' => 99]
    ));
}

Test permission rules once in the permission class, then keep handler tests lighter.

Documentation App Checks

For documentation websites, add quality checks:

  • internal links exist
  • code fence languages are supported
  • downloads exist
  • generated assets exist
  • no app code lives under CorianderCore

This documentation site uses that pattern in tests/Docs.

Before Merging

Run:

composer test
php coriander nodejs run build-prod

When downloads or assets changed, also run:

composer generate-downloads
php coriander nodejs run build-prod