payload; } } class StubEmailController extends EmailController { public function __construct(private readonly bool $result) { } public function sendEmail( string $recipient, string $subject, string $htmlMessage, ?string $profile = null, ?string $replyToEmail = null, ?string $replyToName = null, array $attachments = [] ): bool { return $this->result; } } class TestableContactController extends ContactController { private ?EmailController $emailController = null; public function __construct() { // Skip the parent bootstrap so we control dependencies manually. } public function setEmailController(EmailController $emailController): void { $this->emailController = $emailController; } protected function createEmailController(): EmailController { return $this->emailController ?? parent::createEmailController(); } } class ContactControllerTest extends CIUnitTestCase { private TestableContactController $controller; protected function setUp(): void { parent::setUp(); Services::resetSingle('validation'); $this->controller = new TestableContactController(); } public function testSubmitReturnsErrorWhenJsonMissing() { $this->setRequestPayload(null); $response = $this->controller->submit(); $this->assertFalse($response['status']); $this->assertSame(400, $response['code']); $this->assertSame('Invalid request data', $response['message']); } public function testSubmitReturnsValidationErrors() { $this->setRequestPayload([ 'name' => 'Al', 'email' => 'invalid', 'subject' => 'Hi', 'message' => 'short', ]); $response = $this->controller->submit(); $this->assertFalse($response['status']); $this->assertSame(422, $response['code']); $this->assertSame('Validation failed', $response['message']); $this->assertArrayHasKey('errors', $response); $this->assertNotEmpty($response['errors']); } public function testSubmitReturnsSuccessWhenEmailSent() { $this->controller->setEmailController(new StubEmailController(true)); $this->setRequestPayload($this->validPayload()); $response = $this->controller->submit(); $this->assertTrue($response['status']); $this->assertSame('Thank you for contacting us! We will get back to you soon.', $response['message']); $this->assertNull($response['data']); } public function testSubmitReturnsErrorWhenEmailFails() { $this->controller->setEmailController(new StubEmailController(false)); $this->setRequestPayload($this->validPayload()); $response = $this->controller->submit(); $this->assertFalse($response['status']); $this->assertSame(500, $response['code']); $this->assertSame('There was an error sending your message. Please try again later.', $response['message']); } private function setRequestPayload(?array $payload): void { $request = new FakeJsonRequest($payload); self::setPrivateProperty($this->controller, 'request', $request); } private function validPayload(): array { return [ 'name' => 'Alia Ahmed', 'email' => 'alia@alrahmaisgl.org', 'subject' => 'Support request', 'message' => str_repeat('Please assist. ', 5), ]; } }