Pular para o conteúdo principal

Migration Guide

OpenAPI 3.1 Support (Added in 6.1)

Non-Breaking Addition

Version 6.1 adds full support for OpenAPI 3.1 with JSON Schema 2020-12 compatibility. All existing code continues to work without changes.

What's New in OpenAPI 3.1

  • Automatic Version Detection: The library now automatically detects and handles OpenAPI 3.1 schemas
  • Type Array Nullable: Support for JSON Schema union types like ["string", "null"]
  • Webhooks: Test incoming HTTP requests your API will receive
  • Modern JSON Schema Keywords: const, if/then/else, prefixItems for tuples
  • Enhanced $ref: References can have sibling keywords

Migration from OpenAPI 3.0 to 3.1

No Code Changes Required

The library automatically detects the version - your existing code works with both 3.0 and 3.1 schemas!

Example: Automatic version detection
// This works for both 3.0 and 3.1
$schema = Schema::fromFile('/path/to/openapi.json');

// Check which version you're using
echo $schema->getSpecificationVersion(); // "3.0" or "3.1"

Updating Your OpenAPI Schemas

If you want to upgrade your OpenAPI schemas from 3.0 to 3.1:

1. Update the version number:

Update OpenAPI version
{
"openapi": "3.1.0"
}

2. Replace nullable with type arrays (optional but recommended):

Before (OpenAPI 3.0):

{
"type": "string",
"nullable": true
}

After (OpenAPI 3.1):

{
"type": [
"string",
"null"
]
}

3. Use webhooks for incoming requests (new feature):

Example: Webhook definition
{
"openapi": "3.1.0",
"webhooks": {
"newUser": {
"post": {
"requestBody": {},
"responses": {}
}
}
}
}

For detailed information on OpenAPI 3.1 features, see OpenAPI 3.1 Features Guide.

Backward Compatibility

100% Backward Compatible
  • ✅ All OpenAPI 3.0 and Swagger 2.0 schemas work without changes
  • ✅ All existing test code continues to work
  • ✅ No breaking changes
  • ✅ Mixed 3.0 and 3.1 schemas can be used in the same project

Migrating from Schema::getInstance() (Deprecated in 6.0)

Deprecated

The Schema::getInstance() method has been deprecated in version 6.0 and will be removed in version 7.0.

Why the Change?

Reason for Deprecation

The method name getInstance() suggests a singleton pattern, but it actually creates new instances each time (factory pattern). This is confusing for developers.

New Factory Methods

Three new, clearer factory methods have been added:

Old Way (Deprecated):

// From JSON string
$schema = Schema::getInstance(file_get_contents('/path/to/spec.json'));

// From array
$schema = Schema::getInstance($arrayData);

New Way (Recommended):

// From file (recommended - simplest)
$schema = Schema::fromFile('/path/to/spec.json');

// From JSON string
$jsonString = file_get_contents('/path/to/spec.json');
$schema = Schema::fromJson($jsonString);

// From array
$schema = Schema::fromArray($arrayData);

// With null values allowed (Swagger 2.0 only)
$schema = Schema::fromFile('/path/to/spec.json', allowNullValues: true);
$schema = Schema::fromJson($jsonString, allowNullValues: true);
$schema = Schema::fromArray($arrayData, allowNullValues: true);

Benefits

Why Use New Methods
  1. Clearer intent: Method name matches what it does (factory, not singleton)
  2. Better error messages: Each method validates its specific input type
  3. More convenient: fromFile() handles file reading for you
  4. Consistent naming: Follows common factory method patterns

Migrating from assertRequest() (Deprecated in 6.0)

Deprecated

The assertRequest() method has been renamed to sendRequest() for clarity.

Why the Change?

Reason for Deprecation

The method name assertRequest() is misleading because:

  • It returns a value (assertions typically don't return)
  • The actual validation happens inside via exceptions
  • Developers expect assertion methods to be void

Migration

Old Way (Deprecated):

$response = $this->assertRequest($request);

New Way:

$response = $this->sendRequest($request);

That's it! The functionality is identical, just the name is clearer.


Migrating to expect* Methods (Version 6.0)

Renamed for Clarity

The assertion-style methods (assertStatus(), assertResponseCode(), assertBodyContains(), etc.) have been renamed to expectation-style methods in version 6.0 for better semantic clarity.

Why the Change?

The new "expect" terminology is more semantically accurate:

  • These methods set up expectations that are validated later when sendRequest() is called
  • They don't immediately assert - they register expectations to validate after the response
  • "Expect" clearly indicates you're defining what you expect, not asserting what already happened
  • Common pattern in testing frameworks (PHPUnit prophecy, Mockery, etc.)

Migration

Old Way:

$request = new ApiRequester();
$request
->withMethod('GET')
->withPath('/pet/1')
->assertResponseCode(200) // or assertStatus(200)
->assertBodyContains('Spike')
->assertHeaderContains('Content-Type', 'json');

New Way:

$request = new ApiRequester();
$request
->withMethod('GET')
->withPath('/pet/1')
->expectStatus(200)
->expectBodyContains('Spike')
->expectHeaderContains('Content-Type', 'json');

Method Mapping

Old MethodNew Method
assertResponseCode()expectStatus()
assertStatus()expectStatus()
assertBodyContains()expectBodyContains()
assertHeaderContains()expectHeaderContains()
assertJsonContains()expectJsonContains()
assertJsonPath()expectJsonPath()

Migrating from makeRequest() (Deprecated in 6.0)

Deprecated

The makeRequest() method with 6 parameters has been deprecated in version 6.0 and will be removed in version 7.0.

Why the Change?

Old makeRequest() Issues:

  • Required passing 6 parameters (even empty ones)
  • Parameters in specific order
  • Not easily extensible
  • Less readable code

New ApiRequester Benefits:

  • More readable and self-documenting
  • Only specify parameters you need
  • Easy to extend with new features
  • Better IDE autocomplete support

Migration Examples

Example 1: Simple GET Request

Old Way (Deprecated):

protected function testGetPet()
{
$this->makeRequest(
'GET',
'/pet/1',
200,
null,
null,
[]
);
}

New Way:

public function testGetPet()
{
$request = new \ByJG\ApiTools\ApiRequester();
$request
->withMethod('GET')
->withPath('/pet/1');

$this->sendRequest($request);
}

Example 2: POST with Body

Old Way (Deprecated):

protected function testCreatePet()
{
$this->makeRequest(
'POST',
'/pet',
201,
null,
['name' => 'Fluffy', 'status' => 'available'],
[]
);
}

New Way:

public function testCreatePet()
{
$request = new \ByJG\ApiTools\ApiRequester();
$request
->withMethod('POST')
->withPath('/pet')
->withRequestBody(['name' => 'Fluffy', 'status' => 'available'])
->expectStatus(201);

$this->sendRequest($request);
}

Example 3: GET with Query Parameters

Old Way (Deprecated):

protected function testFindPets()
{
$this->makeRequest(
'GET',
'/pet/findByStatus',
200,
['status' => 'available'],
null,
[]
);
}

New Way:

public function testFindPets()
{
$request = new \ByJG\ApiTools\ApiRequester();
$request
->withMethod('GET')
->withPath('/pet/findByStatus')
->withQuery(['status' => 'available']);

$this->sendRequest($request);
}

Example 4: Request with Headers

Old Way (Deprecated):

protected function testAuthenticatedRequest()
{
$this->makeRequest(
'GET',
'/pet/1',
200,
null,
null,
['Authorization' => 'Bearer token123']
);
}

New Way:

public function testAuthenticatedRequest()
{
$request = new \ByJG\ApiTools\ApiRequester();
$request
->withMethod('GET')
->withPath('/pet/1')
->withRequestHeader(['Authorization' => 'Bearer token123']);

$this->sendRequest($request);
}

Example 5: Complex Request with All Parameters

Old Way (Deprecated):

protected function testComplexRequest()
{
$response = $this->makeRequest(
'POST',
'/pet/1',
200,
['detailed' => 'true'],
['name' => 'Updated Name'],
['Authorization' => 'Bearer token123']
);
}

New Way:

public function testComplexRequest()
{
$request = new \ByJG\ApiTools\ApiRequester();
$response = $request
->withMethod('POST')
->withPath('/pet/1')
->withQuery(['detailed' => 'true'])
->withRequestBody(['name' => 'Updated Name'])
->withRequestHeader(['Authorization' => 'Bearer token123'])
->expectStatus(200);

$response = $this->sendRequest($request);
}

Additional Benefits of the New Approach

1. Better Assertions

Multiple Expectations

You can add multiple assertions to your request:

Example: Multiple expectations
$request = new \ByJG\ApiTools\ApiRequester();
$request
->withMethod('GET')
->withPath('/pet/1')
->expectStatus(200)
->expectHeaderContains('Content-Type', 'application/json')
->expectBodyContains('Fluffy');

$this->sendRequest($request);

2. Reusable Request Builders

Helper Methods

You can create helper methods that return configured requesters:

Example: Reusable authenticated request
protected function createAuthenticatedRequest(string $method, string $path): \ByJG\ApiTools\ApiRequester
{
$request = new \ByJG\ApiTools\ApiRequester();
return $request
->withMethod($method)
->withPath($path)
->withRequestHeader(['Authorization' => 'Bearer ' . $this->getToken()]);
}

public function testWithHelper()
{
$request = $this->createAuthenticatedRequest('GET', '/pet/1');
$this->sendRequest($request);
}

3. Response Inspection

Response Analysis

Both methods return the response, allowing you to inspect it further:

Example: Inspecting response data
$request = new \ByJG\ApiTools\ApiRequester();
$request
->withMethod('GET')
->withPath('/pet/1');

$response = $this->sendRequest($request);

// Inspect the response
$body = json_decode((string)$response->getBody(), true);
$this->assertEquals('Fluffy', $body['name']);

Timeline

Deprecation Timeline
  • Version 6.0:
    • Schema::getInstance() deprecated (use fromJson(), fromArray(), or fromFile())
    • assertRequest() deprecated (use sendRequest())
    • makeRequest() deprecated (use ApiRequester fluent interface)
  • Version 7.0: All deprecated methods will be removed

Need Help?

Getting Support

If you encounter issues during migration:

  1. Check the Troubleshooting Guide
  2. Review the API Reference
  3. Open an issue on GitHub