add test batches
This commit is contained in:
@@ -0,0 +1,87 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Feature\Api\V1\FullSurface;
|
||||
|
||||
use Illuminate\Routing\Route as LaravelRoute;
|
||||
use Tests\Feature\Api\V1\FullSurface\Support\FullSurfaceE2EContractCase;
|
||||
|
||||
class ApiDestructiveActionSafeguardContractTest extends FullSurfaceE2EContractCase
|
||||
{
|
||||
public function test_delete_routes_handle_missing_and_foreign_ids_without_crashing(): void
|
||||
{
|
||||
foreach ($this->deleteRoutes() as $route) {
|
||||
$uri = $this->replaceAllPlaceholdersWithMissingId($route->uri());
|
||||
$response = $this->requestAs($this->actorFor($route->uri()), 'DELETE', $uri);
|
||||
|
||||
$this->assertStatusIn($response, [200, 202, 204, 302, 400, 401, 403, 404, 405, 409, 419, 422], "DELETE missing $uri");
|
||||
$this->assertNoServerError($response, "DELETE missing $uri");
|
||||
}
|
||||
}
|
||||
|
||||
public function test_bulk_delete_style_routes_require_explicit_targets(): void
|
||||
{
|
||||
foreach ($this->bulkDestructiveRoutes() as $route) {
|
||||
$method = $this->primaryMethod($route);
|
||||
$uri = $route->uri();
|
||||
$response = $this->requestAs($this->actorFor($uri), $method, $uri, [
|
||||
'ids' => [],
|
||||
'confirm' => false,
|
||||
]);
|
||||
|
||||
$this->assertStatusIn($response, [200, 202, 204, 302, 400, 401, 403, 404, 405, 409, 419, 422], "$method $uri empty bulk destructive payload");
|
||||
$this->assertNoServerError($response, "$method $uri empty bulk destructive payload");
|
||||
|
||||
if ($response->getStatusCode() >= 200 && $response->getStatusCode() < 300) {
|
||||
$this->assertTrue(
|
||||
in_array($response->getStatusCode(), [200, 202, 204], true),
|
||||
"$method $uri may succeed only as an explicit no-op, never by deleting an unspecified set."
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function test_archive_remove_cancel_and_void_routes_are_idempotent_or_conflict_safe(): void
|
||||
{
|
||||
foreach ($this->softDestructiveRoutes() as $route) {
|
||||
$method = $this->primaryMethod($route);
|
||||
$uri = $route->uri();
|
||||
$first = $this->requestAs($this->actorFor($uri), $method, $uri, $this->payloadFor($method, $uri));
|
||||
$second = $this->requestAs($this->actorFor($uri), $method, $uri, $this->payloadFor($method, $uri));
|
||||
|
||||
$this->assertControlled($first, $method, $uri);
|
||||
$this->assertControlled($second, $method, $uri);
|
||||
$this->assertNoServerError($first, "$method $uri first soft destructive attempt");
|
||||
$this->assertNoServerError($second, "$method $uri second soft destructive attempt");
|
||||
}
|
||||
}
|
||||
|
||||
/** @return list<LaravelRoute> */
|
||||
private function deleteRoutes(): array
|
||||
{
|
||||
return array_slice(array_filter($this->apiRoutes(), fn (LaravelRoute $route): bool => $this->primaryMethod($route) === 'DELETE'), 0, 80);
|
||||
}
|
||||
|
||||
/** @return list<LaravelRoute> */
|
||||
private function bulkDestructiveRoutes(): array
|
||||
{
|
||||
return array_slice(array_filter($this->apiRoutes(), function (LaravelRoute $route): bool {
|
||||
$uri = $route->uri();
|
||||
|
||||
return in_array($this->primaryMethod($route), ['POST', 'DELETE'], true)
|
||||
&& preg_match('/bulk|batch|mass|selected|purge|delete/i', $uri) === 1;
|
||||
}), 0, 60);
|
||||
}
|
||||
|
||||
/** @return list<LaravelRoute> */
|
||||
private function softDestructiveRoutes(): array
|
||||
{
|
||||
return array_slice(array_filter($this->apiRoutes(), function (LaravelRoute $route): bool {
|
||||
return preg_match('/archive|remove|cancel|void|resolve|close|reopen|restore/i', $route->uri()) === 1;
|
||||
}), 0, 80);
|
||||
}
|
||||
|
||||
private function replaceAllPlaceholdersWithMissingId(string $uri): string
|
||||
{
|
||||
return preg_replace('/\{[^}]+\}/', '999999999', $uri) ?? $uri;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user