establishmentRepository = new InMemoryEstablishmentRepository(); $createHandler = new CreateEstablishmentHandler($this->establishmentRepository, $clock); $security = $this->createMock(Security::class); $security->method('getUser')->willReturn(new SecuritySuperAdmin( SuperAdminId::fromString(self::SUPER_ADMIN_ID), 'superadmin@classeo.fr', 'hashed', )); $this->provisionCommand = null; $commandBus = $this->createMock(MessageBusInterface::class); $commandBus->method('dispatch') ->willReturnCallback(function (object $message): Envelope { if ($message instanceof ProvisionEstablishmentCommand) { $this->provisionCommand = $message; } return new Envelope($message); }); $processor = new CreateEstablishmentProcessor($createHandler, $security, $commandBus); $input = new EstablishmentResource(); $input->name = 'École Test'; $input->subdomain = 'ecole-test'; $input->adminEmail = 'admin@ecole-test.fr'; $processor->process($input, new Post()); // Phase 2: Provisioning handler processes the command self::assertNotNull($this->provisionCommand); $this->userRepository = new InMemoryUserRepository(); $this->dispatchedEvents = []; $eventBus = $this->createMock(MessageBusInterface::class); $eventBus->method('dispatch') ->willReturnCallback(function (object $message): Envelope { $this->dispatchedEvents[] = $message; return new Envelope($message); }); $provisioner = $this->createMock(TenantProvisioner::class); $switcher = new SpyDatabaseSwitcher(); $provisionHandler = new ProvisionEstablishmentHandler( tenantProvisioner: $provisioner, inviteUserHandler: new InviteUserHandler($this->userRepository, $clock), userRepository: $this->userRepository, clock: $clock, databaseSwitcher: $switcher, establishmentRepository: $this->establishmentRepository, eventBus: $eventBus, logger: new NullLogger(), masterDatabaseUrl: self::MASTER_URL, ); $provisionHandler($this->provisionCommand); } #[Test] public function processorCreatesEstablishmentInProvisioningStatus(): void { $this->runFullFlow(); $establishments = $this->establishmentRepository->findAll(); self::assertCount(1, $establishments); self::assertSame('École Test', $establishments[0]->name); } #[Test] public function processorDispatchesProvisioningCommandWithAdminEmail(): void { $this->runFullFlow(); self::assertNotNull($this->provisionCommand); self::assertSame('admin@ecole-test.fr', $this->provisionCommand->adminEmail); self::assertSame('ecole-test', $this->provisionCommand->subdomain); } #[Test] public function provisioningCreatesAdminUserWithCorrectRole(): void { $this->runFullFlow(); $users = $this->userRepository->findAllByTenant( TenantId::fromString($this->provisionCommand->establishmentTenantId), ); self::assertCount(1, $users); self::assertSame('admin@ecole-test.fr', (string) $users[0]->email); self::assertSame(Role::ADMIN, $users[0]->role); } #[Test] public function provisioningActivatesEstablishmentAndDispatchesEvent(): void { $this->runFullFlow(); $establishments = $this->establishmentRepository->findAll(); self::assertSame(EstablishmentStatus::ACTIF, $establishments[0]->status); self::assertCount(1, $this->dispatchedEvents); self::assertInstanceOf(UtilisateurInvite::class, $this->dispatchedEvents[0]); } }