Skill api-test
Rédige des tests fonctionnels pour les endpoints API Platform en utilisant ApiTestCase afin de vérifier le CRUD, la validation, la sécurité et l'isolation multi-tenant.
- Étoiles GitHub
- 29
- Fichiers
- 1
- Dernier commit
- 22 oct. 2026
- Licence
- —
- Outils autorisés
- —
Que fait la skill api-test ?
api-test est une agent skill. Rédige des tests fonctionnels pour les endpoints API Platform en utilisant ApiTestCase afin de vérifier le CRUD, la validation, la sécurité et l'isolation multi-tenant.
Résumé généré à partir du SKILL.md de la skill.
À propos du skill api-test
La tâche principale des développeurs utilisant ce SKILL est la rédaction de tests fonctionnels pour les endpoints API Platform. Il automatise la création de suites de tests qui vérifient les opérations CRUD, la validation des données, les protocoles de sécurité et l'isolation multi-tenant. Un agent doit charger cet outil lorsqu'un utilisateur a besoin de tester une ressource API spécifique, de corriger des tests fonctionnels existants ou de reproduire des bugs identifiés sur un endpoint.
Le SKILL utilise ApiTestCase pour générer du code PHP pour les applications basées sur Symfony, en gérant des exigences complexes telles que la configuration des headers d'authentification ou la gestion des fixtures de base de données. Il offre également un support spécialisé pour les environnements Laravel via l'utilisation de ApiTestAssertionsTrait et RefreshDatabase. Que vous travailliez avec Doctrine ORM ou MongoDB, l'outil produit des fichiers de test structurés dans le répertoire approprié pour garantir l'intégrité des ressources et une gestion correcte du schéma.
Ce qu'un agent peut faire avec
- 1Vérifier les opérations CRUDGénérer des tests fonctionnels pour s'assurer que les requêtes GET, POST, PATCH et DELETE fonctionnent correctement pour une ressource spécifique.
- 2Valider les contraintes de donnéesCréer des tests qui vérifient si l'API renvoie un code statut 422 lorsqu'une donnée invalide est soumise.
- 3Appliquer la sécurité multi-tenantDévelopper des tests pour confirmer que les utilisateurs ne peuvent pas accéder à des ressources ou les modifier si elles appartiennent à une organisation différente.
Rédigé à partir du SKILL.md du skill. Chaque cas d'utilisation est vérifié par rapport à une citation de celui-ci.
Comment installer la skill api-test
Chaque commande copie le dossier de la skill dans le répertoire des skills du client. Redémarrez le client ou démarrez une nouvelle session pour la charger.Installer la skill api-test dans Plugin
/plugin marketplace add api-platform/skillset /plugin install api-platform@api-platform-skillset
Installer la skill api-test dans Claude Code
~/.claude/skills/api-test/SKILL.md
$ npx degit api-platform/skillset/skills/api-test ~/.claude/skills/api-testInstaller la skill api-test dans Claude Code (project)
.claude/skills/api-test/SKILL.md
$ npx degit api-platform/skillset/skills/api-test .claude/skills/api-testInstaller la skill api-test dans Codex
~/.agents/skills/api-test/SKILL.md
$ npx degit api-platform/skillset/skills/api-test ~/.agents/skills/api-testInstaller la skill api-test dans Gemini CLI
~/.gemini/skills/api-test/SKILL.md
$ npx degit api-platform/skillset/skills/api-test ~/.gemini/skills/api-testInstaller la skill api-test dans Claude.ai
npx degit api-platform/skillset/skills/api-test api-test && zip -r api-test.zip api-test # claude.ai → Customize → Skills → + → Create skill → Upload a skill → api-test.zip
SKILL.md
Voir sur GitHubTesting API Platform Endpoints
Use ApiPlatform\Symfony\Bundle\Test\ApiTestCase for functional API tests.
Base Test Class
Create a base class that handles database setup and authentication:
<?php
namespace App\Tests;
use ApiPlatform\Symfony\Bundle\Test\ApiTestCase as SymfonyApiTestCase;
use ApiPlatform\Symfony\Bundle\Test\Client;
class ApiTestCase extends SymfonyApiTestCase
{
protected function setUp(): void
{
parent::setUp();
// Reset database state for each test
$manager = static::getContainer()->get('doctrine')->getManager();
// For MongoDB: drop and recreate
// For ORM: use fixtures or transactions
}
/**
* Creates an authenticated client with test fixtures.
*/
public function createLoggedInClient(): Client
{
$manager = static::getContainer()->get('doctrine')->getManager();
// Create user, token, and required fixtures
$user = new User();
// ... set up user
$manager->persist($user);
$manager->flush();
// Return client with auth headers
return static::createClient([], [
'headers' => ['x-api-key' => 'test_token'],
]);
}
}
Basic CRUD Tests
class OrderTest extends ApiTestCase
{
public function testGetCollection(): void
{
$client = $this->createLoggedInClient();
$client->request('GET', '/orders');
$this->assertResponseIsSuccessful();
$this->assertResponseHeaderSame('content-type', 'application/ld+json; charset=utf-8');
}
public function testCreate(): void
{
$client = $this->createLoggedInClient();
$client->request('POST', '/orders', [
'headers' => ['Content-Type' => 'application/ld+json'],
'json' => ['name' => 'Test Order', 'total' => 99.99],
]);
$this->assertResponseStatusCodeSame(201);
$data = $client->getResponse()->toArray();
$this->assertSame('Test Order', $data['name']);
}
public function testUpdate(): void
{
$client = $this->createLoggedInClient();
// Create then update
$client->request('POST', '/orders', [
'headers' => ['Content-Type' => 'application/ld+json'],
'json' => ['name' => 'Original'],
]);
$order = $client->getResponse()->toArray();
$client->request('PATCH', '/orders/' . $order['id'], [
'headers' => ['Content-Type' => 'application/merge-patch+json'],
'json' => ['name' => 'Updated'],
]);
$this->assertResponseIsSuccessful();
$this->assertSame('Updated', $client->getResponse()->toArray()['name']);
}
public function testDelete(): void
{
$client = $this->createLoggedInClient();
// ... create resource first
$client->request('DELETE', '/orders/' . $id);
$this->assertResponseStatusCodeSame(204);
}
}
Testing Validation
public function testCreateWithInvalidData(): void
{
$client = $this->createLoggedInClient();
$client->request('POST', '/orders', [
'json' => ['email' => 'not-valid'],
]);
$this->assertResponseStatusCodeSame(422);
$this->assertJsonContains([
'violations' => [
['propertyPath' => 'email', 'message' => 'This value is not a valid email address.'],
],
]);
}
Testing Authentication
public function testRequiresAuthentication(): void
{
// No auth headers — use raw createClient
$client = static::createClient();
$client->request('GET', '/orders');
$this->assertResponseStatusCodeSame(401);
}
Multi-Tenant Isolation Tests
Test that users can only access their own resources:
public function testIsolationBetweenUsers(): void
{
$client1 = $this->createLoggedInClient(); // User 1, Org 1
$client2 = $this->createSecondUserClient(); // User 2, Org 2
// User 1 creates a resource
$client1->request('POST', '/accounts', [
'headers' => ['Content-Type' => 'application/ld+json'],
'json' => ['address' => 'user1@example.com', 'password' => 'Pass123!'],
]);
$account = $client1->getResponse()->toArray();
// User 2 cannot read it
$client2->request('GET', '/accounts/' . $account['id']);
$this->assertResponseStatusCodeSame(404);
// User 2 cannot update it
$client2->request('PATCH', '/accounts/' . $account['id'], [
'headers' => ['Content-Type' => 'application/merge-patch+json'],
'json' => ['isActive' => false],
]);
$this->assertResponseStatusCodeSame(404);
// User 2 cannot delete it
$client2->request('DELETE', '/accounts/' . $account['id']);
$this->assertResponseStatusCodeSame(404);
// Collections are isolated
$client2->request('GET', '/accounts');
$collection = $client2->getResponse()->toArray();
$ids = array_column($collection['member'], 'id');
$this->assertNotContains($account['id'], $ids);
}
Testing Filters
public function testFilterByStatus(): void
{
$client = $this->createLoggedInClient();
// ... create test data with different statuses
$client->request('GET', '/orders?isActive=true');
$this->assertResponseIsSuccessful();
$data = $client->getResponse()->toArray();
foreach ($data['member'] as $order) {
$this->assertTrue($order['isActive']);
}
}
Common Assertions
$this->assertResponseIsSuccessful();
$this->assertResponseStatusCodeSame(201);
$this->assertJsonContains(['name' => 'Expected']);
$this->assertMatchesResourceItemJsonSchema(Order::class);
$this->assertMatchesResourceCollectionJsonSchema(Order::class);
Resetting the Schema Between Tests (ORM)
For a clean database per test, drop and recreate the schema in setUp(). API
Platform's own suite uses an internal ApiPlatform\Tests\RecreateSchemaTrait —
that namespace is not autoloaded in your app, so copy the mechanism rather than
importing it:
use Doctrine\ORM\Tools\SchemaTool;
protected function setUp(): void
{
parent::setUp();
$manager = static::getContainer()->get('doctrine')->getManager();
$metadata = $manager->getMetadataFactory()->getAllMetadata();
$schemaTool = new SchemaTool($manager);
$schemaTool->dropDatabase();
$schemaTool->createSchema($metadata);
}
For MongoDB ODM, drop the collections via
$manager->getSchemaManager()->dropDocumentCollection(...) instead.
Test File Location
Place tests in tests/Functional/ following the naming convention {ResourceName}Test.php.
Laravel
Laravel uses its own HTTP test client (PHPUnit Tests\TestCase or Pest), not
ApiTestCase. API Platform ships ApiPlatform\Laravel\Test\ApiTestAssertionsTrait
(adds assertJsonContains(), assertArraySubset(), getIriFromResource()). Use
RefreshDatabase for isolation and model factories for fixtures (not Doctrine
SchemaTool/fixtures).
<?php
namespace Tests\Feature;
use ApiPlatform\Laravel\Test\ApiTestAssertionsTrait;
use App\Models\Book;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;
class BooksTest extends TestCase
{
use RefreshDatabase, ApiTestAssertionsTrait;
public function testCreate(): void
{
$response = $this->postJson('/api/books', ['isbn' => '0099740915', 'title' => 'X']);
$response->assertStatus(201);
$this->assertJsonContains(['title' => 'X'], $response->json());
$book = Book::factory()->create();
$this->getJson($this->getIriFromResource($book))->assertStatus(200);
}
}
Key deltas: request helpers are getJson/postJson/patchJson/deleteJson;
assertions are $response->assertStatus(...), $response->assertHeader(...),
$this->assertDatabaseMissing(...). assertJsonContains() takes the decoded body
($response->json()). Isolation/validation(422)/auth tests use the same status-code
assertions; auth uses Sanctum/actingAs(), not custom headers. Pest is the default
and wraps the same trait via uses(RefreshDatabase::class, ApiTestAssertionsTrait::class).
Fichiers de cette skill
1Questions sur la skill api-test
Comment installer la skill api-test dans Claude Code ?
Exécutez npx degit api-platform/skillset/skills/api-test ~/.claude/skills/api-test. Claude Code charge les skills depuis ~/.claude/skills (tous les projets) ou .claude/skills (un seul projet) et utilise une skill lorsque sa description correspond à la tâche.
Quels clients peuvent utiliser la skill api-test ?
Tout client qui lit le format Agent Skills : Claude Code, Codex, Gemini CLI et claude.ai (envoi sous forme de ZIP). Les scripts de la skill ne s'exécutent que si le client autorise l'exécution de code.
Ce SKILL prend-il en charge les tests Laravel ?
Oui, il fournit des directives pour Laravel en utilisant ApiTestAssertionsTrait, RefreshDatabase et les model factories à la place d'ApiTestCase.