Skip to content

Releases: rasuvaeff/property-testing-openapi

v0.19.0

Choose a tag to compare

@github-actions github-actions released this 11 Oct 20:49
945cb61
  • Added. Bounded constructive generation for prefixItems/contains
    (including minContains/maxContains), dependentRequired,
    dependentSchemas, and unevaluatedProperties/unevaluatedItems (#157).
  • Added. Conditional schemas (if/then/else) are generated
    constructively, including boolean and nested branches. Each candidate is
    checked by openapi-contract's SchemaCheck; unreachable branches are
    omitted and a conditional with no finite value fails closed (#157).
  • Fixed. A member under patternProperties is now generated against the
    schema of the name it actually lands under. The value was compiled once for
    the whole map, so every name received the schema of whichever name was drawn
    first — an object whose ^a member carried a boolean and whose z$ member
    carried a string, which the contract rejects (#157).
  • Changed. Requires rasuvaeff/openapi-contract ^0.16 (in place of
    ^0.15) for the schema keywords added in 0.16: prefixItems, contains
    with minContains/maxContains, dependentRequired, dependentSchemas,
    unevaluatedProperties/unevaluatedItems (#157).

v0.18.0

Choose a tag to compare

@github-actions github-actions released this 29 Sep 10:45
c1147a1
  • Changed. Requires rasuvaeff/openapi-contract ^0.15 (in place of
    ^0.13) so downstream projects can adopt the contract's 0.14/0.15
    releases (#137): 0.14 keeps a shared component as one resolution per
    document (the local {$ref: '#/$defs/…'} form the generator already
    unfolds since 0.16.0), 0.15 adds Contract::validateWebhook() and per-leaf
    body diagnostics — verdicts unchanged. No generator change was needed; the
    one test expectation that moved is the formatter rendering of a body
    member's actual (now printed unless the member path looks like a
    credential; wholesale [redacted] stays for a whole-body violation at
    $ and a cookie).

v0.17.0

Choose a tag to compare

@github-actions github-actions released this 20 Sep 09:20
446709a
  • Changed. Requires rasuvaeff/property-testing-core ^1.0 — the
    engine's stability release, whose surface is that of 0.12.0 — in place of
    ^0.10 || ^0.11; the dev requirement on rasuvaeff/property-testing-testo
    is ^1.0 likewise. Nothing in the generators or the runner changes: the
    release is the constraint, so a project on the 1.0 family can install this
    package beside it. rasuvaeff/openapi-contract stays at ^0.13; this
    package's own 1.0 waits for the contract's.

v0.16.0

Choose a tag to compare

@github-actions github-actions released this 19 Sep 23:07
1634dc5
  • Added. A schema that refers to itself — a tree whose children are
    trees — is generated. rasuvaeff/openapi-contract 0.13 compiles such a
    schema to $defs plus a local {$ref: '#/$defs/<name>'} for every
    reference back into the cycle; the generator unfolds the def three levels
    below the root and ends at a leaf where the recursive member is left out —
    an optional property omitted, an array that may be empty left empty, a
    branch of anyOf/oneOf skipped, a member of an allOf inlined as the
    def's body. A def whose only way down is a required member that is the def
    itself has no finite instance and is refused (recursive schema "…" has no finite instance), as is a def that is an allOf member of itself; a
    $ref to anything but the schema's own $defs is refused by name. The
    JSON body encoder follows the same references, so a nested empty object
    three levels down is still written as {}. The zoo gains tree.create;
    the recorded corpus grows by its 25 cases.
  • Changed. Requires rasuvaeff/openapi-contract ^0.13.

v0.15.2

Choose a tag to compare

@github-actions github-actions released this 19 Sep 17:07
c0b0eb1
  • Fixed. Whether the number branch of a oneOf admits an integer was
    judged by a copy of the contract's old float multipleOf rule; with
    0.12.1 the contract judges on the decimals and the two disagreed on 4670
    of the integers in ±100000 for multipleOf: 0.7 — the generator kept
    58254 on the integer branch, the contract saw it on both, and a case
    called valid was rejected. The verdict is the contract's now:
    SchemaCheck::isMultipleOf() (openapi-contract 0.12.2, required as
    ^0.12.2). The zoo's amounts.create carries step (0.7 beside a wide
    integer branch) and the contract's corpus is re-recorded (#132).
  • Fixed. A number schema whose bound is so wide that its decimal
    multiples need more significant digits than a double holds
    (|bound| × 10^decimals > 2^53) fails closed at compile time instead of
    rounding onto a neighbouring decimal that is no multiple; a multiple that
    divides one (1, 0.5, 0.25) is exempt, every double that wide being
    an integer. A property pins that every generated multiple is one to the
    contract (#133).
  • CI. static-analysis.yml runs composer rector on every PR: 0.15.0
    shipped with a rule red in a test its last commit added, and nothing
    before the next PR ran rector.

v0.15.1

Choose a tag to compare

@github-actions github-actions released this 19 Sep 16:09
8aa3fa8
  • Changed. Requires rasuvaeff/openapi-contract ^0.12.1, which judges
    multipleOf on the decimals a message spells rather than on the parsed
    doubles (openapi-contract#151). A decimal multiple is generated as the
    clean decimal it means, always: 64.1, never 64.10000000000001. 0.15.0
    emitted the float product wherever the contract's old float path demanded
    it — from about 64 upward for multipleOf: 0.1 — and 0.12.1 rejects
    that product, as the specification does. The zoo's precise.get carries a
    decimal multipleOf again and the tests that pinned the agreement no
    longer skip under ext-bcmath.

v0.15.0

Choose a tag to compare

@github-actions github-actions released this 19 Sep 12:16
ed13cb3

The 1.0-readiness review of 2026-09-18 (#117–#129). A minor on 0.x: the
constructor of ResponseMaterializer narrows, the OperationPropertyFailed
factories take one more argument, the RequestCaseData /
NegativeRequestCaseData psalm aliases are gone, and case-shape errors are a
type of their own.

  • Changed. Requires rasuvaeff/openapi-contract ^0.12 and
    rasuvaeff/property-testing-core ^0.10 || ^0.11 (develops against
    rasuvaeff/property-testing-testo ^0.10 || ^0.11): the compile-time
    probes catch GenerationExhaustedException by name, which exists since the
    core's 0.10 contract freeze, so ^0.5–^0.9 are no longer accepted. The
    directional schema
    rewrite is delegated to SchemaCheck::effective() — this package's own
    copy never recursed into additionalProperties — and the request body and
    responses arrive as the contract's typed shapes, so the guards that
    re-checked them are gone.
  • Fixed. A numeric parameter reached the wire through (string), which
    rounds to precision=14 and put a different number there for any value
    that needed more digits (846608010056.187 went as 846608010056.19). A
    float is spelled the way json_encode spells it now. The multipleOf
    generator also rounded k × m back to the decimal it meant, which from
    about 64 upwards is one ulp away from the product the validator
    computes and tolerates, so a third of the draws for 0.1 were rejected;
    the decimal spelling is kept only where the validator agrees with it.
    Under ext-bcmath the contract evaluates multipleOf in decimal
    arithmetic and its verdict is its own — openapi-contract#151 (#117).
  • Fixed. missing-required no longer targets a path parameter, and
    negativeCoverage() no longer lists it: omitting one leaves the template
    literal in the request target, which a string schema accepts, so the
    negative phase failed on any /{slug} operation with
    unexpectedlyValidRequest. An operation whose only required component is a
    path parameter skips the category and names the reason (#118).
  • Fixed. + stays %2B under allowReserved: a raw plus in a query is
    a space to the validator and to every SAPI (#119).
  • Fixed. A form body property with an object schema and explode: true
    is generated without undeclared members — its flat member=value pairs can
    carry only the declared ones, and an extra landed as a top-level member of
    the body. A nested object whose minProperties its declared properties
    cannot meet fails closed at compile time (#120).
  • Fixed. oneOf over an integer and a number branch was compiled as a
    plain choice between disjoint branches, and half the draws matched both.
    The number branch is generated without integral values, the integer branch
    keeps only what the number branch's bounds and multiple refuse, and a
    number branch that admits every value outside the integer branch fails
    closed. 1.0 is an integer to JSON Schema, and is treated as one (#121).
  • Fixed. A multipart part declared under a JSON media type carries the
    JSON encoding of its value; text/* and application/octet-stream parts
    carry it verbatim; any other part media type fails closed instead of
    sending a body the generator cannot vouch for (#122).
  • Fixed. Three legal documents reached a run-time GenerationExhausted:
    a header enum outside ASCII (isHeaderSafe() admits obs-text now, as RFC
    9110 and the validator do), a path pattern that always carries a slash
    (probed at compile time and refused by name, as is a header pattern none
    of whose strings survives the wire), and an object whose twelve optionals
    were drawn as independent presence choices against maxProperties: 1
    (minProperties/maxProperties are met by construction: an optional past
    the ceiling is left out, one needed for the floor brought in). uniqueItems
    with minItems over a bounded integer domain smaller than it fails closed
    at compile time (#123).
  • Fixed. A header enum member with an interior space (New York) was
    refused at compile time although the validator accepts it: a scalar
    header's members are refused only for whitespace at an end or a control
    character, a list or object header's additionally for a comma (#129).
  • Added. ContractSuite::redaction(RedactionPolicy) configures the policy
    every rendering goes through: reproduce() by default (its policy
    argument is optional now) and the minimal case OperationPropertyFailed
    prints, which used to be the unredacted counterexample JSON.
    ContractSuite::redact(array $case): array applies it to a case. The
    READMEs and llms.txt claimed Cookie was in the default redacted header
    set; it is not, by design since #73, and they say so now (#124).
  • Added. OpenApiPropertyTestingException, an empty marker interface
    implemented by every exception of the package; InvalidCase
    (\InvalidArgumentException) for a case that does not have the exported
    shape — the materializer and the serializer threw UnsupportedGeneration
    for it, which is a document limitation, not a caller error; a
    Psr15Transport configuration error is a SuiteConfigurationError rather
    than a bare \LogicException. UnsupportedGeneration::forSchema()
    refusals name the operation and the parameter or body being compiled
    (Unsupported OpenAPI schema generation for operation "pets.list", query parameter "limit": minLength exceeds maxLength) through
    inOperation() (#127).
  • Changed. The case shape is declared once, on ContractSuite
    (CaseData with ParameterMap, BodyData, PartData, MisuseData), and
    imported everywhere else; the RequestCaseData and
    NegativeRequestCaseData aliases and the inline copies are gone.
    checkValid(), checkNegative(), reproduce(), redact() and
    RequestMaterializer::materialize() refuse a case missing a key with
    InvalidCase naming it — a hand-written case without misuse used to
    raise a PHP warning and pass checkValid() (#128).
  • Changed. ResponseMaterializer::__construct() no longer takes the
    @internal JsonBodyEncoder and ParameterSerializer as defaulted
    parameters; it builds them, as RequestMaterializer does (#125).
    CheckFailed::$result is readonly, assigned through the constructor by
    the factories (#126). OperationPropertyFailed::forCounterExample() and
    forExample() take the redacted case to print as their last argument.
  • Zoo: labels.get, sparse.create, amounts.create, settings.create,
    precise.get; the contract's generated corpus is re-recorded from it
    (openapi-contract#152).

v0.14.1

Choose a tag to compare

@github-actions github-actions released this 18 Sep 15:15
4ad82ad
  • Fixed. Valid number schemas now keep exclusive bounds at the adjacent
    IEEE-754 value, including subnormals, instead of stepping by a decimal
    fraction that could cross an entire representable interval.
  • Fixed. Integer multipleOf calculations stay in the native integer
    domain and fail closed at its limits; number multiples whose index cannot
    fit that domain now fail closed too.
  • Fixed. Multipart per-part content types and encoding headers reject
    invalid field names and CR/LF values before either a case or a PSR-7 request
    is constructed.

v0.14.0

Choose a tag to compare

@github-actions github-actions released this 12 Sep 19:08
22cf723
  • Changed. Accepts rasuvaeff/property-testing-core ^0.10 alongside
    ^0.5–^0.9, and develops against rasuvaeff/property-testing-testo
    ^0.10 as well. None of the 0.10 contract freeze reaches this package: it
    never called FilesystemCorpus::fromEnv(), reads no CounterExample::$skips,
    names neither GenerationExhausted nor PostconditionViolation in code
    (two comments mention the former by its old name), and types every
    generator as ArbitraryInterface — which is exactly what Gen::* returns
    from 0.10 on. The suite (866 tests) is green against core 0.10.0 and the
    adapter 0.10.0.
  • Docs. The requirements line in both READMEs names the constraints
    composer.json actually declares: openapi-contract ^0.11 (it said
    ^0.8 / ^0.9 / ^0.10 since 0.13.0 moved on) and property-testing-core
    ^0.5–^0.10.

v0.13.1

Choose a tag to compare

@github-actions github-actions released this 12 Sep 17:37
498c4cf
  • Fixed. A JSON body property declaring OAS 3.0 nullable: true beside
    a bound yielded no body case for any category: JsonBodyWitness withheld
    its candidates from the check, on the reasoning that a schema admitting
    null promises nothing about what is written over it — but null is
    admitted in addition to the declared keywords, and a string longer than
    maxLength is no more valid for it. The candidates now go to
    WitnessCheck like every other property's, which already approved them.
    Under OAS 3.1 nothing changes: nullable is not a keyword there, the
    contract refuses the schema and the check fails closed — spell it as a
    type union containing null (#112).