Apply RED-GREEN-REFACTOR with Pest PHP for Symfony; use Foundry factories, functional tests with WebTestCase, verify failures before implementation
/plugin marketplace add MakFly/superpowers-symfony/plugin install makfly-superpowers-symfony@MakFly/superpowers-symfonyThis skill inherits all available tools. When active, it can use any tool Claude has access to.
composer require pestphp/pest --dev --with-all-dependencies
composer require pestphp/pest-plugin-symfony --dev
composer require zenstruck/foundry --dev
# Initialize Pest
./vendor/bin/pest --init
# Docker
docker compose exec php ./vendor/bin/pest --parallel
# Host
./vendor/bin/pest --parallel
# Single file
./vendor/bin/pest tests/Unit/Service/OrderServiceTest.php
# With filter
./vendor/bin/pest --filter "creates order"
# With coverage
./vendor/bin/pest --coverage --min=80
Write tests before implementation. Use Foundry for factories.
<?php
// tests/Unit/Service/OrderServiceTest.php
use App\Service\OrderService;
use App\Entity\Order;
use App\Entity\User;
use function Zenstruck\Foundry\Persistence\persist;
beforeEach(function () {
$this->orderService = $this->getContainer()->get(OrderService::class);
});
it('creates an order for a user', function () {
// Arrange
$user = persist(User::class, [
'email' => 'test@example.com',
]);
// Act
$order = $this->orderService->createOrder($user->object(), [
['productId' => 1, 'quantity' => 2],
]);
// Assert
expect($order)
->toBeInstanceOf(Order::class)
->and($order->getCustomer())->toBe($user->object())
->and($order->getItems())->toHaveCount(1);
});
it('throws exception for empty items', function () {
$user = persist(User::class);
$this->orderService->createOrder($user->object(), []);
})->throws(InvalidArgumentException::class, 'Order must have at least one item');
<?php
// tests/Functional/Api/OrderTest.php
use App\Entity\User;
use function Zenstruck\Foundry\Persistence\persist;
it('creates an order via API', function () {
// Arrange
$user = persist(User::class, ['email' => 'test@example.com']);
// Act
$response = $this->client
->loginUser($user->object())
->request('POST', '/api/orders', [
'json' => [
'items' => [
['productId' => 1, 'quantity' => 2],
],
],
]);
// Assert
expect($response->getStatusCode())->toBe(201)
->and($response->toArray())->toHaveKey('id');
});
it('requires authentication', function () {
$response = $this->client->request('POST', '/api/orders', [
'json' => ['items' => []],
]);
expect($response->getStatusCode())->toBe(401);
});
Write the simplest code to pass. No extras. No premature optimization.
<?php
// src/Service/OrderService.php
class OrderService
{
public function createOrder(User $user, array $items): Order
{
if (empty($items)) {
throw new \InvalidArgumentException('Order must have at least one item');
}
$order = new Order();
$order->setCustomer($user);
$order->setStatus(OrderStatus::PENDING);
foreach ($items as $item) {
$orderItem = new OrderItem();
$orderItem->setProductId($item['productId']);
$orderItem->setQuantity($item['quantity']);
$order->addItem($orderItem);
}
$this->em->persist($order);
$this->em->flush();
return $order;
}
}
Once green, improve:
<?php
// tests/Factory/UserFactory.php
namespace App\Tests\Factory;
use App\Entity\User;
use Zenstruck\Foundry\Persistence\PersistentProxyObjectFactory;
final class UserFactory extends PersistentProxyObjectFactory
{
public static function class(): string
{
return User::class;
}
protected function defaults(): array
{
return [
'email' => self::faker()->unique()->email(),
'password' => 'hashed_password',
'roles' => ['ROLE_USER'],
];
}
public function admin(): self
{
return $this->with(['roles' => ['ROLE_ADMIN']]);
}
}
Usage:
use App\Tests\Factory\UserFactory;
// Single user
$user = UserFactory::createOne();
// With specific attributes
$admin = UserFactory::createOne()->admin();
// Multiple
$users = UserFactory::createMany(5);
// Without persisting
$user = UserFactory::new()->withoutPersisting()->create();
// Basic
expect($value)->toBe($expected);
expect($value)->toEqual($expected);
expect($value)->toBeTrue();
expect($value)->toBeFalse();
expect($value)->toBeNull();
expect($value)->toBeEmpty();
// Types
expect($value)->toBeInstanceOf(Order::class);
expect($value)->toBeArray();
expect($value)->toBeString();
expect($value)->toBeInt();
// Arrays
expect($array)->toHaveCount(3);
expect($array)->toHaveKey('id');
expect($array)->toContain($item);
// Strings
expect($string)->toContain('substring');
expect($string)->toStartWith('prefix');
expect($string)->toMatch('/pattern/');
// Chaining
expect($order)
->toBeInstanceOf(Order::class)
->and($order->getStatus())->toBe(OrderStatus::PENDING)
->and($order->getItems())->toHaveCount(2);
Applies Anthropic's official brand colors and typography to any sort of artifact that may benefit from having Anthropic's look-and-feel. Use it when brand colors or style guidelines, visual formatting, or company design standards apply.
Creating algorithmic art using p5.js with seeded randomness and interactive parameter exploration. Use this when users request creating art using code, generative art, algorithmic art, flow fields, or particle systems. Create original algorithmic art rather than copying existing artists' work to avoid copyright violations.
Create beautiful visual art in .png and .pdf documents using design philosophy. You should use this skill when the user asks to create a poster, piece of art, design, or other static piece. Create original visual designs, never copying existing artists' work to avoid copyright violations.