Testing your admin

Kinetis\Vector\Testing drives the REST API from your own test suite, through the framework’s TestClient, so your middleware, authentication, policies and hooks all run as in production.

use Kinetis\Vector\Testing\InteractsWithVector;

final class CatalogAdminTest extends ApplicationTestCase
{
    use InteractsWithVector;

    public function testEditorsCannotSeeCosts(): void
    {
        $products = $this->vector(['Authorization' => "Bearer {$this->editorToken()}"])->resource('products');

        $products->list(filter: ['status' => ['eq' => 'active']])->assertOk()->assertMissingField('costCents');
        $id = $products->create(['sku' => 'A-1', 'name' => 'Lamp'])->assertCreated()->id();
        $products->update($id, ['sku' => ''])->assertInvalid('sku', 'required');
        $products->action('reprice', [$id], ['percent' => 5])->assertQueued();
    }
}

$this->vector($headers) is a client authenticated as you choose.

  • resource($slug) has one method per endpoint: list, show, create, update, delete, restore, batch, changes, action, related, attach, detach, options, audit, revert, export, upload and file.

  • The client itself has schema(), me(), search(), badges() and job(); withHeaders() switches identity.

Every call answers a VectorResponse with chaining assertions — assertRecord, assertTotal, assertIds, assertListed, assertEveryRecord, assertInvalid, assertForbidden, assertPermission, assertHasField, assertQueued and more. raw() is the framework’s TestResponse, for anything else.

Waiting on the database without blocking

On a persistent worker, a request that waits on the database has to yield to the event loop, so the worker can keep serving other requests. The demo proves this for Vector’s list, show, update and action requests in demo/backend/tests/Vector/LoopLivenessTest.php, with the framework’s LoopLiveness::turnedDuring().

PHPUnit gets a blocking PDO connection by default, so the test sets DB_DRIVER, DB_ADMIN_DRIVER and DB_SUPPORT_DRIVER to native in configOverrides(). A local database answers too fast to show anything, so a separate process (tests/Fixtures/hold-products-lock.php) holds LOCK TABLES products WRITE for 300 ms while each request runs. The request’s own statements wait on that lock through the connection Vector uses. Each path also runs on pdo, where the same request must report that the loop did not turn, so the proof can fail. The blocking setup stays outside the observed request, and only those two files get the PHPStan kinetis.blockingCall ignore.

See also