diff --git a/core/datamodel.core.xml b/core/datamodel.core.xml index bea18700c..9e599eb2b 100644 --- a/core/datamodel.core.xml +++ b/core/datamodel.core.xml @@ -355,20 +355,30 @@ } } - if ($bIsAsync === true) { - AsyncSendNewsroom::AddToQueue($this->GetKey(), $oTrigger->GetKey(), $aRecipientsIds, $sMessage, $sTitle, $sUrl, $iObjectId, $sObjectClass); - } else { - foreach ($aRecipientsIds as $iRecipientId) { - $oEvent = Combodo\iTop\Service\Notification\Event\EventNotificationNewsroomService::MakeEventFromAction($this, $iRecipientId, $oTrigger->GetKey(), $sMessage, $sTitle, $sUrl, $iObjectId, $sObjectClass); - try { - $oEvent->DBInsertNoReload(); - } catch(CoreCannotSaveObjectException $e) { - ExceptionLog::LogException($e); - $oEvent = Combodo\iTop\Service\Notification\Event\EventNotificationNewsroomService::MakeEventFromAction($this, $iRecipientId, $oTrigger->GetKey(), Dict::Format('Core:EventNotificationNewsroom:ErrorOnDBInsert'), Dict::Format('Core:EventNotificationNewsroom:ErrorNotificationNotSent'), $sUrl, $iObjectId, $sObjectClass); - $oEvent->DBInsertNoReload(); - } - } - } + try { + if ($bIsAsync === true) { + AsyncSendNewsroom::AddToQueue($this->GetKey(), $oTrigger->GetKey(), $aRecipientsIds, $sMessage, $sTitle, $sUrl, $iObjectId, $sObjectClass); + } else { + foreach ($aRecipientsIds as $iRecipientId) { + $oEvent = Combodo\iTop\Service\Notification\Event\EventNotificationNewsroomService::MakeEventFromAction($this, $iRecipientId, $oTrigger->GetKey(), $sMessage, $sTitle, $sUrl, $iObjectId, $sObjectClass); + $oEvent->DBInsertNoReload(); + } + } + } catch (CoreCannotSaveObjectException $e) { + ExceptionLog::LogException($e); + foreach($aRecipientsIds as $iRecipientId) { + $oEvent = Combodo\iTop\Service\Notification\Event\EventNotificationNewsroomService::MakeEventFromAction($this, + $iRecipientId, + $oTrigger->GetKey(), + Dict::S('Core:EventNotificationNewsroom:ErrorOnDBInsert'), + Dict::S('Core:EventNotificationNewsroom:ErrorNotificationNotSent'), + $sUrl, + $iObjectId, + $sObjectClass + ); + $oEvent->DBInsertNoReload(); + } + } $this->SetNotificationLanguage($sPreviousLanguage, $aPreviousPluginProperties['language_code'] ?? null); } diff --git a/tests/php-unit-tests/src/BaseTestCase/ItopDataTestCase.php b/tests/php-unit-tests/src/BaseTestCase/ItopDataTestCase.php index c682070cf..c48f5d695 100644 --- a/tests/php-unit-tests/src/BaseTestCase/ItopDataTestCase.php +++ b/tests/php-unit-tests/src/BaseTestCase/ItopDataTestCase.php @@ -18,6 +18,8 @@ use CMDBObject; use CMDBSource; use Combodo\iTop\Service\Events\EventService; use Contact; +use CoreException; +use CoreUnexpectedValue; use DBObject; use DBObjectSet; use DBSearch; @@ -29,6 +31,9 @@ use lnkContactToFunctionalCI; use lnkContactToTicket; use lnkFunctionalCIToTicket; use MetaModel; +use MissingQueryArgument; +use MySQLException; +use MySQLHasGoneAwayException; use Person; use PluginManager; use Server; @@ -1439,4 +1444,24 @@ abstract class ItopDataTestCase extends ItopTestCase self::markTestSkipped("Test skipped: module '$sModule' is not present"); } } + + /** + * @throws CoreException + * @throws CoreUnexpectedValue + * @throws ArchivedObjectException + * @throws MissingQueryArgument + * @throws MySQLException + * @throws MySQLHasGoneAwayException + * @throws Exception + */ + protected function AssertUniqueObjectInDB(string $sClass, array $aCriteria, string $sMessage = ''): void + { + $oSearch = new \DBObjectSearch($sClass); + foreach($aCriteria as $sAttCode => $value) + { + $oSearch->AddCondition($sAttCode, $value); + } + $oSet = new DBObjectSet($oSearch); + $this->assertEquals(1, $oSet->Count(), $sMessage); + } } diff --git a/tests/php-unit-tests/unitary-tests/core/ActionNewsroomTest.php b/tests/php-unit-tests/unitary-tests/core/ActionNewsroomTest.php new file mode 100644 index 000000000..d630736e3 --- /dev/null +++ b/tests/php-unit-tests/unitary-tests/core/ActionNewsroomTest.php @@ -0,0 +1,160 @@ + +// + +namespace Combodo\iTop\Test\UnitTest\Core; + +use ArchivedObjectException; +use Combodo\iTop\Test\UnitTest\ItopDataTestCase; +use CoreException; +use CoreUnexpectedValue; +use DBObjectSearch; +use DBObjectSet; +use Exception; +use MetaModel; +use MissingQueryArgument; +use MySQLException; +use MySQLHasGoneAwayException; + + +class ActionNewsroomTest extends ItopDataTestCase +{ + const CREATE_TEST_ORG = true; + private int $iTrigger; + private int $iRecipientId; + + protected function setUp(): void + { + parent::setUp(); + $this->iTrigger = $this->GivenObjectInDB('TriggerOnObjectCreate', + array( + 'description' => '[TEST] TriggerOnObjectCreate', + 'target_class' => 'UserRequest', + ) + ); + $this->iRecipientId = $this->GivenPersonInDB(1); + } + + private function ActionNewsroomProvider(): array + { + return [ + 'With Sync ActionNewsroom' => ['bIsAsynchronous' => false], + 'With Async ActionNewsroom' => ['bIsAsynchronous' => true] + ]; + } + + /** + * @throws CoreException + * @throws MissingQueryArgument + * @throws CoreUnexpectedValue + * @throws ArchivedObjectException + * @throws MySQLException + * @throws MySQLHasGoneAwayException + * @throws Exception + */ + public function testActionNewsroomRecordsEvent() + { + $iActionNewsroomId = $this->GivenActionNewsroomInDB(false, 'Body of the notification'); + + $this->CreateUserRequest(1, + [ + 'title' => '[TEST] ActionNewsroom', + 'org_id' => $this->getTestOrgId(), + 'caller_id' => $this->iRecipientId, + 'description' => 'PHPUnit Test', + ] + ); + + $this->AssertUniqueObjectInDB( + 'EventNotificationNewsroom', + [ + 'action_id' => $iActionNewsroomId, + 'message' => 'Body of the notification', + 'title' => 'Title' + ] + ); + } + + /** + * @dataProvider ActionNewsroomProvider + * @return void + * @throws Exception + */ + public function testActionNewsroomRecordsSpecificEventIfAMandatoryFieldIsEmpty(bool $bIsAsynchronous) + { + $iActionNewsroomId = $this->GivenActionNewsroomInDB($bIsAsynchronous, '$this->service_name$'); + + $this->CreateUserRequest(1, + [ + 'title' => '[TEST] ActionNewsroom', + 'org_id' => $this->getTestOrgId(), + 'caller_id' => $this->iRecipientId, + 'description' => 'PHPUnit Test', + 'service_id' => 0 + ] + ); + + $this->AssertUniqueObjectInDB( + 'EventNotificationNewsroom', + [ + 'action_id' => $iActionNewsroomId, + 'title' => 'Notification not sent', + 'message' => 'An error occurred while saving the notification' + ] + ); + } + + /** + * @throws Exception + */ + private function GivenActionNewsroomInDB(bool $bIsAsynchronous, string $sMessage): int + { + $this->GivenObjectInDB('UserLocal', [ + 'login' => 'demo_test_'.uniqid(__CLASS__, true), + 'password' => 'admin_123', + 'language' => 'EN US', + 'profile_list' => ['profileid:'.self::$aURP_Profiles['Administrator']], + 'contactid' => $this->iRecipientId + ]); + + return $this->GivenObjectInDB('ActionNewsroom', [ + 'name' => 'ActionNewsroom TriggerOnObjectCreate', + 'status' => 'test', + 'test_recipient_id' => $this->iRecipientId, + 'title' => 'Title', + 'message' => $sMessage, + 'recipients' => "SELECT Person WHERE id = $this->iRecipientId", + 'asynchronous' => $bIsAsynchronous ? 'yes' : 'no', + 'trigger_list' => [ + "trigger_id:$this->iTrigger" + ], + ]); + } + + /** + * @throws Exception + */ + private function GivenService(string $sName): int + { + return $this->GivenObjectInDB('Service', [ + 'name' => $sName, + 'org_id' => $this->getTestOrgId() + ] + ); + } +} \ No newline at end of file