5e35fefd69
API CI/CD / Validate (composer + pint) (push) Successful in 2m47s
API CI/CD / Test (PHPUnit) (push) Failing after 3m8s
API CI/CD / Build frontend assets (push) Failing after 5m22s
API CI/CD / Security audit (push) Failing after 34s
API CI/CD / Deploy to shared hosting (PHP) (push) Has been skipped
67 lines
2.5 KiB
PHP
67 lines
2.5 KiB
PHP
<?php
|
|
|
|
namespace Tests\Feature\Api\V1\FullSurface;
|
|
|
|
use Tests\Feature\Api\V1\FullSurface\Support\FullSurfaceE2EContractCase;
|
|
|
|
class ApiMutationReadAfterWriteConsistencyContractTest extends FullSurfaceE2EContractCase
|
|
{
|
|
public function test_created_resources_return_identifier_or_location_to_support_follow_up_reads(): void
|
|
{
|
|
foreach ($this->apiRoutes() as $route) {
|
|
$method = $this->primaryMethod($route);
|
|
|
|
if ($method !== 'POST') {
|
|
continue;
|
|
}
|
|
|
|
$uri = $route->uri();
|
|
|
|
if (str_contains($uri, 'logout') || str_contains($uri, 'login') || str_contains($uri, 'export') || str_contains($uri, 'download')) {
|
|
continue;
|
|
}
|
|
|
|
if (preg_match('/send|notify|dispatch|evaluate|expire|seed|process|scan|preview|form|placement\\/level|below-sixty/i', $uri) === 1) {
|
|
continue;
|
|
}
|
|
|
|
$response = $this->requestAs($this->actorFor($uri), 'POST', $uri, $this->payloadFor('POST', $uri));
|
|
$this->assertControlled($response, 'POST', $uri);
|
|
|
|
if (! in_array($response->getStatusCode(), [200, 201, 202], true) || ! $this->isJsonString($response->getContent())) {
|
|
continue;
|
|
}
|
|
|
|
$json = $response->json();
|
|
$encoded = json_encode($json, JSON_THROW_ON_ERROR);
|
|
|
|
$this->assertTrue(
|
|
str_contains($encoded, '"id"') || str_contains($encoded, '"data"') || $response->headers->has('Location'),
|
|
"POST {$uri} succeeded but returned no id/data/location for read-after-write follow-up."
|
|
);
|
|
}
|
|
}
|
|
|
|
public function test_update_successes_preserve_resource_identity_when_identity_is_present(): void
|
|
{
|
|
foreach ($this->apiRoutes() as $route) {
|
|
$method = $this->primaryMethod($route);
|
|
|
|
if (! in_array($method, ['PUT', 'PATCH'], true)) {
|
|
continue;
|
|
}
|
|
|
|
$uri = $route->uri();
|
|
$response = $this->requestAs($this->actorFor($uri), $method, $uri, $this->payloadFor($method, $uri));
|
|
$this->assertControlled($response, $method, $uri);
|
|
|
|
if (! in_array($response->getStatusCode(), [200, 202], true) || ! $this->isJsonString($response->getContent())) {
|
|
continue;
|
|
}
|
|
|
|
$body = $response->getContent();
|
|
$this->assertStringNotContainsString('"id":null', $body, "{$method} {$uri} returned null id after successful update.");
|
|
}
|
|
}
|
|
}
|