apiRoutes(), fn ($route) => $this->primaryMethod($route) === 'GET' && ! str_contains($route->uri(), '{')), 0, 120); foreach ($routes as $route) { $uri = $route->uri(); $response = $this->actingAs($this->actorFor($uri), 'api')->getJson($this->materializePath($uri)); $this->assertControlled($response, 'GET', $uri); $this->assertNoServerError($response, 'collection envelope '.$uri); if ($response->getStatusCode() !== 200 || ! $this->isJsonString($response->getContent())) { continue; } $payload = $response->json(); $this->assertTrue( is_array($payload) && ( array_is_list($payload) || array_key_exists('data', $payload) || array_key_exists('items', $payload) || array_key_exists('results', $payload) || array_key_exists('message', $payload) || array_key_exists('status', $payload) ), $uri.' should keep a predictable collection/read envelope.' ); } } public function test_successful_detail_endpoints_keep_identifier_or_data_keys(): void { $routes = array_slice(array_filter($this->apiRoutes(), fn ($route) => $this->primaryMethod($route) === 'GET' && str_contains($route->uri(), '{')), 0, 100); foreach ($routes as $route) { $uri = $route->uri(); $response = $this->actingAs($this->actorFor($uri), 'api')->getJson($this->materializePath($uri)); $this->assertControlled($response, 'GET', $uri); $this->assertNoServerError($response, 'detail envelope '.$uri); if ($response->getStatusCode() !== 200 || ! $this->isJsonString($response->getContent())) { continue; } $payload = $response->json(); $this->assertTrue( data_get($payload, 'id') !== null || data_get($payload, 'data.id') !== null || data_get($payload, 'message') !== null || data_get($payload, 'status') !== null, $uri.' should keep an identifier, data wrapper, or explicit status/message contract.' ); } } }