Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Laravel Json Schema Assertions Laravel Package

sixlive/laravel-json-schema-assertions

Validate JSON responses and payloads against JSON Schema definitions in your Laravel tests. Adds expressive assertions like assertJsonSchema so you can verify API structure and contracts with minimal setup.

View on GitHub
Deep Wiki
Context7

Getting Started

sixlive/laravel-json-schema-assertions adds an assertJsonSchema() macro to Laravel's TestResponse, letting you validate a JSON HTTP response body against a JSON Schema document instead of hand-writing dozens of assertJsonStructure / assertJsonPath calls.

Install (dev only):

composer require --dev sixlive/laravel-json-schema-assertions

No manual provider registration is needed — package discovery wires up the service provider, and the macro is available on any TestResponse returned by $this->getJson(), $this->postJson(), $this->json(), etc.

First use case — contract-test an API endpoint. Drop a schema next to your tests:

// tests/schemas/users/index.json
{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "type": "object",
  "required": ["data"],
  "properties": {
    "data": {
      "type": "array",
      "items": {
        "type": "object",
        "required": ["id", "name", "email"],
        "properties": {
          "id":        { "type": "integer" },
          "name":      { "type": "string" },
          "email":     { "type": "string", "format": "email" },
          "created_at":{ "type": ["string", "null"] }
        }
      }
    }
  }
}

Then assert against it:

public function test_users_index_matches_schema(): void
{
    $this->getJson('/api/users')
        ->assertOk()
        ->assertJsonSchema(base_path('tests/schemas/users/index.json'));
}

Where to look first: the package's test suite/README for the exact accepted argument forms (file path vs. inline schema string), and justinrainbow/json-schema docs — that library does the actual validation, so its draft support and error wording are what you'll be reading when an assertion fails.

Recommended rollout: pick one high-traffic read endpoint, write the schema from a real response ($response->json() pretty-printed), assert it, then expand to the rest of the resource. Schemas are cheap to keep in tests/schemas/ and act as living API documentation.

Implementation Patterns

Layered assertion: status → schema → specific values. assertJsonSchema() only checks shape/type/constraints, so pair it with targeted assertions for business rules:

$response = $this->getJson('/api/users')
    ->assertOk()
    ->assertJsonSchema(base_path('tests/schemas/users/index.json'))
    ->assertJsonPath('data.0.email', '[email protected]');

Reusable schema fragments via $ref. Keep a tests/schemas/definitions.json with shared objects (user, pagination, error) and reference them locally from each endpoint schema. This is the single biggest maintainability win — one place to change when a resource gains a field.

Data providers for polymorphic responses. When an endpoint returns different shapes by role or state, drive the schema from a PHPUnit data provider so one test method covers admin, member, and guest payloads.

Snapshot the schema from a real response while writing tests. Temporarily dump($response->json()) in a failing test, paste into the schema file, then tighten constraints (required, format, enum, minimum). Start permissive ("type": "object") so CI stays green, then ratchet down.

Test the error envelope too. Most teams schema-test only happy paths. Error responses (404/422/403) are exactly where clients break — write one schema for your error body and assert it across all failure tests.

Pest integration works transparently because it's a macro:

it('returns a valid user collection', function () {
    $this->getJson('/api/users')
        ->assertOk()
        ->assertJsonSchema(base_path('tests/schemas/users/index.json'));
});

CI wiring. Nothing special is required; the schemas are plain files committed with the tests. If you run tests inside a container, prefer base_path() / __DIR__ over relative paths so resolution doesn't depend on the working directory.

Complementary tooling. Use this package for response-shape assertions in feature tests, and keep a separate contract test (or OpenAPI validation) if your spec is the source of truth — the two can drift otherwise.

Gotchas and Tips

  • Schema draft support is inherited from justinrainbow/json-schema. Draft-04 is the safe target; newer drafts (2019-09, 2020-12) and keywords from them (unevaluatedProperties, dependentRequired, modern $defs semantics) are not reliably supported. Stick to draft-04/06 keywords.
  • format validation is opt-in in the underlying validator. "format": "email" / "uuid" may not be enforced by default depending on how the package constructs the validator. Don't assume format gives you enforcement — add a regex pattern if it matters.
  • Decoded response vs. raw body. Validation runs against the decoded JSON ($response->json()), so integer/float coercion, null handling, and large-number precision behave as PHP does, not as the JSON text does. A schema requiring "type": "integer" can fail on a value that serialized as "1" in a badly-typed resource.
  • Empty or non-JSON bodies produce confusing failures. Always assertOk() (or check content type) first so you're not debugging a schema error that's really a 500 HTML error page.
  • $ref resolution. Local file refs are fine; remote HTTP $refs require network access and can be flaky/blocked in CI. Keep all refs local to the repo.
  • Failure output is verbose. A schema violation dumps the full validator error tree. When it's noisy, isolate by asserting a smaller sub-schema first, or narrow the failing test to a single item.
  • Path handling. Pass absolute paths (base_path('tests/schemas/…')). Relative-path resolution depends on the process working directory, which differs between php artisan test, IDE runners, and CI containers.
  • Don't use it as a substitute for assertJsonStructure. assertJsonStructure is faster and gives cleaner diffs for simple shape checks; reach for JSON Schema when you need types, enums, ranges, and reusable definitions across many endpoints.
  • Version pinning. v4.4.0 is the release that adds Laravel 12.x compatibility and clears PHPUnit deprecation warnings — if you're on Laravel 12 or PHPUnit 11/12, you need ^4.4; older 4.x pins will emit deprecations or fail to install. Keep it in require-dev so it never ships to production.
  • Extension point. The macro is registered by the package's service provider; if you need custom behaviour (schema path conventions, caching of parsed schemas, custom retriever), wrap assertJsonSchema() in your own base TestCase helper rather than forking the package — you keep upgrade paths open.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core