Add app:stripe:sync command to sync Stripe status for all organizers
Fetches charges_enabled and payouts_enabled from Stripe API for each organizer with a connected account and updates the local database. Also adds retrieveAccountStatus() to StripeService for testability. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
130
tests/Command/StripeSyncCommandTest.php
Normal file
130
tests/Command/StripeSyncCommandTest.php
Normal file
@@ -0,0 +1,130 @@
|
||||
<?php
|
||||
|
||||
namespace App\Tests\Command;
|
||||
|
||||
use App\Command\StripeSyncCommand;
|
||||
use App\Entity\User;
|
||||
use App\Service\StripeService;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Doctrine\ORM\EntityRepository;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\Console\Application;
|
||||
use Symfony\Component\Console\Tester\CommandTester;
|
||||
|
||||
class StripeSyncCommandTest extends TestCase
|
||||
{
|
||||
private function createOrganizer(string $stripeId, bool $charges = false, bool $payouts = false): User
|
||||
{
|
||||
$user = new User();
|
||||
$user->setEmail('orga-'.uniqid().'@test.fr');
|
||||
$user->setFirstName('Test');
|
||||
$user->setLastName('Orga');
|
||||
$user->setPassword('hashed');
|
||||
$user->setRoles(['ROLE_ORGANIZER']);
|
||||
$user->setStripeAccountId($stripeId);
|
||||
$user->setStripeChargesEnabled($charges);
|
||||
$user->setStripePayoutsEnabled($payouts);
|
||||
$user->setCompanyName('Asso Test');
|
||||
|
||||
return $user;
|
||||
}
|
||||
|
||||
private function createCommandTester(array $users, StripeService $stripeService): CommandTester
|
||||
{
|
||||
$repo = $this->createMock(EntityRepository::class);
|
||||
$repo->method('findAll')->willReturn($users);
|
||||
|
||||
$em = $this->createMock(EntityManagerInterface::class);
|
||||
$em->method('getRepository')->willReturn($repo);
|
||||
|
||||
$command = new StripeSyncCommand($em, $stripeService);
|
||||
$app = new Application();
|
||||
$app->addCommand($command);
|
||||
|
||||
return new CommandTester($app->find('app:stripe:sync'));
|
||||
}
|
||||
|
||||
public function testSyncUpdatesStripeStatus(): void
|
||||
{
|
||||
$user = $this->createOrganizer('acct_123');
|
||||
|
||||
$stripeService = $this->createMock(StripeService::class);
|
||||
$stripeService->method('retrieveAccountStatus')
|
||||
->with('acct_123')
|
||||
->willReturn(['charges_enabled' => true, 'payouts_enabled' => true]);
|
||||
|
||||
$tester = $this->createCommandTester([$user], $stripeService);
|
||||
$tester->execute([]);
|
||||
|
||||
self::assertTrue($user->isStripeChargesEnabled());
|
||||
self::assertTrue($user->isStripePayoutsEnabled());
|
||||
self::assertStringContainsString('1 synced', $tester->getDisplay());
|
||||
self::assertSame(0, $tester->getStatusCode());
|
||||
}
|
||||
|
||||
public function testSyncDetectsChanges(): void
|
||||
{
|
||||
$user = $this->createOrganizer('acct_456', true, true);
|
||||
|
||||
$stripeService = $this->createMock(StripeService::class);
|
||||
$stripeService->method('retrieveAccountStatus')
|
||||
->willReturn(['charges_enabled' => true, 'payouts_enabled' => false]);
|
||||
|
||||
$tester = $this->createCommandTester([$user], $stripeService);
|
||||
$tester->execute([]);
|
||||
|
||||
self::assertTrue($user->isStripeChargesEnabled());
|
||||
self::assertFalse($user->isStripePayoutsEnabled());
|
||||
self::assertStringContainsString('UPDATED', $tester->getDisplay());
|
||||
}
|
||||
|
||||
public function testSyncWithNoOrganizers(): void
|
||||
{
|
||||
$stripeService = $this->createMock(StripeService::class);
|
||||
|
||||
$tester = $this->createCommandTester([], $stripeService);
|
||||
$tester->execute([]);
|
||||
|
||||
self::assertStringContainsString('No organizers', $tester->getDisplay());
|
||||
self::assertSame(0, $tester->getStatusCode());
|
||||
}
|
||||
|
||||
public function testSyncHandlesStripeError(): void
|
||||
{
|
||||
$user = $this->createOrganizer('acct_bad');
|
||||
|
||||
$stripeService = $this->createMock(StripeService::class);
|
||||
$stripeService->method('retrieveAccountStatus')
|
||||
->willThrowException(new \RuntimeException('Account not found'));
|
||||
|
||||
$tester = $this->createCommandTester([$user], $stripeService);
|
||||
$tester->execute([]);
|
||||
|
||||
self::assertStringContainsString('1 error', $tester->getDisplay());
|
||||
self::assertSame(1, $tester->getStatusCode());
|
||||
}
|
||||
|
||||
public function testSyncSkipsOrganizersWithoutStripeAccount(): void
|
||||
{
|
||||
$userWithStripe = $this->createOrganizer('acct_ok');
|
||||
|
||||
$userWithoutStripe = new User();
|
||||
$userWithoutStripe->setEmail('no-stripe@test.fr');
|
||||
$userWithoutStripe->setFirstName('No');
|
||||
$userWithoutStripe->setLastName('Stripe');
|
||||
$userWithoutStripe->setPassword('hashed');
|
||||
$userWithoutStripe->setRoles(['ROLE_ORGANIZER']);
|
||||
|
||||
$stripeService = $this->createMock(StripeService::class);
|
||||
$stripeService->method('retrieveAccountStatus')
|
||||
->willReturn(['charges_enabled' => true, 'payouts_enabled' => false]);
|
||||
|
||||
$tester = $this->createCommandTester([$userWithStripe, $userWithoutStripe], $stripeService);
|
||||
$tester->execute([]);
|
||||
|
||||
self::assertStringContainsString('Syncing 1 organizer', $tester->getDisplay());
|
||||
self::assertStringContainsString('1 synced', $tester->getDisplay());
|
||||
self::assertTrue($userWithStripe->isStripeChargesEnabled());
|
||||
self::assertFalse($userWithStripe->isStripePayoutsEnabled());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user