'Test action', 'status' => 'disabled', 'from' => 'unit-test@openitop.org', 'subject' => 'Test subject', 'body' => 'Test body', ]); $sHtml = << HTML ; static::$oActionEmail->DBInsert(); static::$oDocument = new \ormDocument($sHtml, 'text/html', 'sample.html'); static::$oUserRequest = MetaModel::NewObject('UserRequest', [ 'title' => 'Test UserRequest', 'description' => '

Multi-line
description

', ]); static::$aWarningMessages = [ 'warning-missing-content' => Dict::Format('ActionEmail:content_placeholder_missing', '$content$', Dict::S('Class:ActionEmail/Attribute:body')), ]; } /** * @covers \ActionEmail::GenerateIdentifierForHeaders * @dataProvider GenerateIdentifierForHeadersProvider * @throws \Exception */ public function testGenerateIdentifierForHeaders(string $sHeaderName) { // Retrieve object $oObject = MetaModel::GetObject('Organization', $this->getTestOrgId(), true, true); $sObjClass = get_class($oObject); $sObjId = $oObject->GetKey(); try { $sTestedIdentifier = $this->InvokeNonPublicMethod('\ActionEmail', 'GenerateIdentifierForHeaders', static::$oActionEmail, [$oObject, $sHeaderName]); } catch (Exception $oException) { $sTestedIdentifier = null; } $sAppName = utils::Sanitize(ITOP_APPLICATION_SHORT, '', utils::ENUM_SANITIZATION_FILTER_VARIABLE_NAME); $sEnvironmentHash = MetaModel::GetEnvironmentId(); switch ($sHeaderName) { case ActionEmail::ENUM_HEADER_NAME_MESSAGE_ID: // Note: For this test we can't use the more readable sprintf test as the generated timestamp will never be the same as the one generated during the call of the tested method // $sTimestamp = microtime(true /* get as float*/); // $sExpectedIdentifier = sprintf('%s_%s_%d_%f@%s.openitop.org', $sAppName, $sObjClass, $sObjId, $sTimestamp, $sEnvironmentHash); $this->assertEquals(1, preg_match('/'.$sAppName.'_'.$sObjClass.'_'.$sObjId.'_[\d]+\.[\d]+@'.$sEnvironmentHash.'.openitop.org/', $sTestedIdentifier), "Identifier doesn't match regexp for header $sHeaderName, got $sTestedIdentifier"); break; case ActionEmail::ENUM_HEADER_NAME_REFERENCES: $sExpectedIdentifier = '<'.sprintf('%s_%s_%d@%s.openitop.org', $sAppName, $sObjClass, $sObjId, $sEnvironmentHash).'>'; $this->assertEquals($sExpectedIdentifier, $sTestedIdentifier); break; default: $sExpectedIdentifier = null; $this->assertEquals($sExpectedIdentifier, $sTestedIdentifier); break; } } public function GenerateIdentifierForHeadersProvider() { return [ 'Message-ID' => ['Message-ID'], 'References' => ['References'], 'IncorrectHeaderName' => ['IncorrectHeaderName'], ]; } /** * @dataProvider prepareMessageContentProvider */ public function testPrepareMessageContent($sCurrentUserLanguage, $aActionFields, $aFieldsToCheck) { \Dict::SetUserLanguage($sCurrentUserLanguage); $aContext = ['this->object()' => static::$oUserRequest]; $oActionEmail = MetaModel::NewObject('ActionEmail', [ 'name' => 'Test action', 'status' => 'disabled', 'from' => 'unit-test@openitop.org', 'subject' => 'Test subject', 'body' => 'Test body', ]); foreach ($aActionFields as $sCode => $value) { if ($sCode === 'html_template') { // special case since the data provider cannot create ormDocument objects $oActionEmail->Set($sCode, static::$oDocument); } else { $oActionEmail->Set($sCode, $value); } } $oActionEmail->DBInsert(); $oOrg = $this->CreateOrganization('testPrepareMessageContent'); $oContact1 = MetaModel::NewObject('Person', [ 'name' => 'Person 1', 'first_name' => 'PrepareMessageContent', 'org_id' => $oOrg->GetKey(), 'email' => 'some.valid@email.com', 'notify' => 'yes', ]); $oContact1->DBInsert(); $oContact2 = MetaModel::NewObject('Person', [ 'name' => 'Person 2', 'first_name' => 'PrepareMessageContent', 'org_id' => $oOrg->GetKey(), 'email' => 'some.valid2@email.com', 'notify' => 'no', ]); $oContact2->DBInsert(); $oLog = null; $aEmailContent = $this->InvokeNonPublicMethod('\ActionEmail', 'PrepareMessageContent', $oActionEmail, [$aContext, &$oLog]); // Normalize the content of the body to simplify the comparison, useful when status == test $aEmailContent['body'] = preg_replace('/title="[^"]+"/', 'title="****"', $aEmailContent['body']); $aEmailContent['body'] = preg_replace('/class="object-ref-link" href="[^"]+"/', 'class="object-ref-link" href="****"', $aEmailContent['body']); $aEmailContent['body'] = preg_replace('/References: <[^>]+>/', 'References: ****', $aEmailContent['body']); foreach ($aFieldsToCheck as $sCode => $expectedValue) { $this->assertEquals($expectedValue, $aEmailContent[$sCode]); } } public function prepareMessageContentProvider() { return [ 'subject-no-placeholder' => [ 'EN US', ['subject' => 'This is a test'], ['subject' => 'This is a test'], ], 'subject-with-placeholder' => [ 'EN US', ['subject' => 'Ticket "$this->title$" created'], ['subject' => 'Ticket "Test UserRequest" created'], ], 'simple-to-oql' => [ 'EN US', ['to' => "SELECT Person WHERE email='some.valid@email.com'"], ['to' => 'some.valid@email.com'], ], 'simple-to-oql_ignoring_ignore_notify' => [ 'EN US', ['to' => "SELECT Person WHERE email='some.valid2@email.com'"], ['to' => 'some.valid2@email.com'], // contact2 has 'notify' set to 'no' BUT by default when don't care ], 'simple-to-oql-not-bypassing-notify' => [ 'EN US', ['to' => "SELECT Person WHERE email='some.valid2@email.com'", 'ignore_notify' => 'no'], ['to' => ''], // contact2 has 'notify' set to 'no' ], 'subject-with-localized-placeholder (default behavior)' => [ 'EN US', ['subject' => 'Ticket in state "$this->label(status)$" created'], ['subject' => 'Ticket in state "New" created'], ], 'subject-with-localized-placeholder (default behavior 2)' => [ 'FR FR', ['subject' => 'Ticket in state "$this->label(status)$" created'], ['subject' => 'Ticket in state "Nouveau" created'], ], 'subject-with-localized-placeholder (new behavior)' => [ 'FR FR', ['subject' => 'Ticket in state "$this->label(status)$" created', 'language' => 'EN US'], ['subject' => 'Ticket in state "New" created'], ], 'simple-body-with-placeholder' => [ 'EN US', ['body' => '

Ticket "$this->title$" created.

'], ['body' => '

Ticket "Test UserRequest" created.

'], ], 'simple-body-with-placeholder-TEST-mode' => [ 'EN US', ['body' => '

Ticket "$this->title$" created.

', 'status' => 'test'], ['body' => <<

Ticket "Test UserRequest" created.

Testing email notification Test action

The email should be sent with the following properties

HTML , 'subject' => 'TEST[Test subject]', ], ], 'more-complex-body-and-title-with-placeholder' => [ 'EN US', ['subject' => 'Ticket "$this->title$" created'], ['subject' => 'Ticket "Test UserRequest" created'], ['body' => '

Ticket "$this->title$" created.

Description: $this->html(description)

'], ['body' => '

Ticket "Test UserRequest" created.

Description:

Multi-line
description

'], ], 'simple-body-with-placeholder_and_template' => [ 'EN US', ['body' => '

Ticket "$this->title$" created.

', 'html_template' => true], ['body' => <<
Formatted eMail
\$content\$
HTML ], ], ]; } /** * @dataProvider doCheckToWriteProvider * @param string $sBody * @param string $sHtmlTemplate * @param string[] $aExpectedWarnings */ public function testDoCheckToWrite(string $sBody, ?string $sHtmlTemplate, $expectedWarnings) { $oActionEmail = new ActionEmail(); // Set mandatory fields $oActionEmail->Set('name', 'test'); $oActionEmail->Set('subject', 'Ga Bu Zo Meu'); // Set the fields for testing $oActionEmail->Set('body', $sBody); if ($sHtmlTemplate !== null) { $oDoc = new \ormDocument($sHtmlTemplate, 'text/html', 'template.html'); $oActionEmail->Set('html_template', $oDoc); } $oActionEmail->DoCheckToWrite(); $aWarnings = $this->GetNonPublicProperty($oActionEmail, 'm_aCheckWarnings'); if ($expectedWarnings === null) { $this->assertEquals($aWarnings, $expectedWarnings); } else { // The warning messages are localized, but the provider functions does not // have access to the Dict class, so let's replace the value given by the // provider by a statically precomputed and localized message foreach ($expectedWarnings as $index => $sMessageKey) { $expectedWarnings[$index] = static::$aWarningMessages[$sMessageKey]; } $this->assertEquals($aWarnings, $expectedWarnings); } } public function doCheckToWriteProvider() { return [ 'no warnings' => [ '

Some text here

', '
$content$
', null, ], '$content$ missing' => [ '

Some text here

', '
no placeholder
', [ 'warning-missing-content' ], ], ]; } /** * @dataProvider asynchronousValuesContentProvider */ public function testAsynchronousValues($sActionAsyncValue, $sConfigAsyncValue, $sExpectedValue) { $oConfig = utils::GetConfig(); $sCurrentEmailAsync = $oConfig->Get('email_asynchronous'); $oConfig->Set('email_asynchronous', $sConfigAsyncValue); $oActionEmail = MetaModel::NewObject('ActionEmail', [ 'name' => 'Test action', 'status' => 'disabled', 'from' => 'unit-test@openitop.org', 'subject' => 'Test subject', 'body' => 'Test body', 'asynchronous' => $sActionAsyncValue, ]); self::assertEquals($sExpectedValue, $oActionEmail->IsAsynchronous()); $oConfig->Set('email_asynchronous', $sCurrentEmailAsync); } public function asynchronousValuesContentProvider() { return [ 'ActionEmail is asynchronous' => [ 'yes', false, true, ], 'ActionEmail is not asynchronous' => [ 'no', true, false, ], 'ActionEmail is asynchronous and config is asynchronous' => [ 'yes', true, true, ], 'ActionEmail is not asynchronous and config is not asynchronous' => [ 'no', false, false, ], 'ActionEmail follows global settings, config is not asynchronous' => [ 'use_global_setting', false, false, ], 'ActionEmail follows global settings, config is asynchronous' => [ 'use_global_setting', true, true, ], ]; } }
Formatted eMail