. */ declare(strict_types=1); namespace SP\Tests\Domain\Notification\Services; use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\MockObject\MockObject; use RuntimeException; use SP\Core\Events\Event; use SP\Core\Events\EventMessage; use SP\Core\Messages\MailMessage; use SP\Domain\Config\Adapters\ConfigData; use SP\Domain\Config\Ports\ConfigFileService; use SP\Domain\Http\Ports\RequestService; use SP\Domain\Notification\Ports\MailService; use SP\Domain\Notification\Services\MailEvent; use SP\Tests\Generators\ConfigDataGenerator; use SP\Tests\UnitaryTestCase; /** * Class MailHandlerTest */ #[Group('unitary')] class MailEventTest extends UnitaryTestCase { private MockObject|MailService $mailService; private RequestService|MockObject $requestService; private MailEvent $mailEvent; private ConfigData $configData; public function testUpdate() { $eventMessage = EventMessage::factory() ->addDescription('a_description') ->addDetail('a_detail', 'a_value') ->setExtra('email', ['an_email']); $event = new Event($this, $eventMessage); $this->requestService ->expects($this->once()) ->method('getClientAddress') ->with(true) ->willReturn(self::$faker->ipv4()); $this->mailService ->expects($this->once()) ->method('send') ->with( 'a_description', ['an_email'], self::callback(static function (MailMessage $mailMessage) { $matches = preg_match( '/\na_description
a_detail: a_value\n\nPerformed by: [\w.]+ \([\w.]+\)\nIP Address: [\d.]+/', $mailMessage->composeText() ); return empty($mailMessage->getTitle()) && empty($mailMessage->getFooter()) && $matches === 1; }) ); $this->mailEvent->update('test_a.update', $event); } public function testUpdateWithConfiguredEmail() { $this->configData->setMailRecipients(['an_email']); $eventMessage = EventMessage::factory() ->addDescription('a_description') ->addDetail('a_detail', 'a_value'); $event = new Event($this, $eventMessage); $this->requestService ->expects($this->once()) ->method('getClientAddress') ->with(true) ->willReturn(self::$faker->ipv4()); $this->mailService ->expects($this->once()) ->method('send') ->with( 'a_description', ['an_email'], self::callback(static function (MailMessage $mailMessage) { $matches = preg_match( '/\na_description
a_detail: a_value\n\nPerformed by: [\w.]+ \([\w.]+\)\nIP Address: [\d.]+/', $mailMessage->composeText() ); return empty($mailMessage->getTitle()) && empty($mailMessage->getFooter()) && $matches === 1; }) ); $this->mailEvent->update('test_a.update', $event); } public function testUpdateWithNoEmail() { $eventMessage = EventMessage::factory() ->addDescription('a_description') ->addDetail('a_detail', 'a_value'); $event = new Event($this, $eventMessage); $this->mailService ->expects($this->never()) ->method('send'); $this->mailEvent->update('test_a.update', $event); } public function testUpdateWithNoDescriptionAndDetails() { $eventMessage = EventMessage::factory()->setExtra('email', ['an_email']); $event = new Event($this, $eventMessage); $this->requestService ->expects($this->once()) ->method('getClientAddress') ->with(true) ->willReturn(self::$faker->ipv4()); $this->mailService ->expects($this->once()) ->method('send') ->with( 'test_a.update', ['an_email'], self::callback(static function (MailMessage $mailMessage) { $matches = preg_match( '/\nEvent: test_a.update\n\nPerformed by: [\w.]+ \([\w.]+\)\nIP Address: [\d.]+/', $mailMessage->composeText() ); return empty($mailMessage->getTitle()) && empty($mailMessage->getFooter()) && $matches === 1; }) ); $this->mailEvent->update('test_a.update', $event); } public function testUpdateWithEmptyRecipients() { $eventMessage = EventMessage::factory() ->addDescription('a_description') ->addDetail('a_detail', 'a_value') ->setExtra('email', ['an_email', '']); $event = new Event($this, $eventMessage); $this->requestService ->expects($this->once()) ->method('getClientAddress') ->with(true) ->willReturn(self::$faker->ipv4()); $this->mailService ->expects($this->once()) ->method('send') ->with( 'a_description', ['an_email'], self::callback(static function (MailMessage $mailMessage) { $matches = preg_match( '/\na_description
a_detail: a_value\n\nPerformed by: [\w.]+ \([\w.]+\)\nIP Address: [\d.]+/', $mailMessage->composeText() ); return empty($mailMessage->getTitle()) && empty($mailMessage->getFooter()) && $matches === 1; }) ); $this->mailEvent->update('test_a.update', $event); } public function testUpdateWithException() { $eventMessage = EventMessage::factory() ->addDescription('a_description') ->addDetail('a_detail', 'a_value') ->addExtra('email', ['an_email']); $event = new Event($this, $eventMessage); $this->mailService ->expects($this->once()) ->method('send') ->willThrowException(new RuntimeException('test')); $this->mailEvent->update('test_a.update', $event); } public function testGetEventsString() { $expected = 'test_a\.|test_b\.|clear\.eventlog|refresh\.masterPassword|update\.masterPassword\.start|update\.masterPassword\.end|request\.account|edit\.user\.password|save\.config\.|create\.tempMasterPassword'; $out = $this->mailEvent->getEvents(); $this->assertEquals($expected, $out); } public function testGetEventsStringWithNoConfiguredEvents() { $expected = 'clear\.eventlog|refresh\.masterPassword|update\.masterPassword\.start|update\.masterPassword\.end|request\.account|edit\.user\.password|save\.config\.|create\.tempMasterPassword'; $this->configData->setMailEvents([]); $databaseHandler = new MailEvent($this->application, $this->mailService, $this->requestService); $out = $databaseHandler->getEvents(); $this->assertEquals($expected, $out); } protected function buildConfig(): ConfigFileService { $this->configData = ConfigDataGenerator::factory()->buildConfigData(); $this->configData->setMailEvents(['test_a.', 'test_b.']); $config = $this->createMock(ConfigFileService::class); $config->method('getConfigData')->willReturn($this->configData); return $config; } protected function setUp(): void { parent::setUp(); $this->mailService = $this->createMock(MailService::class); $this->requestService = $this->createMock(RequestService::class); $this->mailEvent = new MailEvent($this->application, $this->mailService, $this->requestService); } }