Add email helper to new form test helper
authorEileen McNaughton <emcnaughton@wikimedia.org>
Sat, 9 Sep 2023 23:39:16 +0000 (11:39 +1200)
committerEileen McNaughton <emcnaughton@wikimedia.org>
Sun, 10 Sep 2023 04:43:37 +0000 (16:43 +1200)
Civi/Test/FormWrapper.php
tests/phpunit/CRM/Event/Form/ParticipantTest.php
tests/phpunit/CRM/Event/Form/Registration/ConfirmTest.php

index f9af7110a122b7bd385ca76fcad54f192a553c66..737ebb9389dd0d94a01b44ac8648476df6987ffd 100644 (file)
@@ -36,10 +36,32 @@ class FormWrapper {
 
   private $mail;
 
+  /**
+   * @return null|array
+   */
+  public function getMail(): ?array {
+    return $this->mail;
+  }
+
+  /**
+   * @return array
+   */
+  public function getFirstMail(): array {
+    return $this->mail ? (array) reset($this->mail) : [];
+  }
+
+  public function getFirstMailBody() : string {
+    return $this->getFirstMail()['body'] ?? '';
+  }
+
   private $redirects;
 
+  private $mailSpoolID;
+
   private $validation;
 
+  private $originalMailSetting;
+
   public const CONSTRUCTED = 0;
   public const PREPROCESSED = 1;
   public const BUILT = 3;
@@ -79,12 +101,7 @@ class FormWrapper {
       $this->validation = $this->form->validate();
     }
     if ($state > self::VALIDATED) {
-      $this->form->postProcess();
-      foreach ($this->subsequentForms as $form) {
-        $form->preProcess();
-        $form->buildForm();
-        $form->postProcess();
-      }
+      $this->postProcess();
     }
     return $this;
   }
@@ -138,7 +155,14 @@ class FormWrapper {
    * @return $this
    */
   public function postProcess(): self {
+    $this->startTrackingMail();
     $this->form->postProcess();
+    foreach ($this->subsequentForms as $form) {
+      $form->preProcess();
+      $form->buildForm();
+      $form->postProcess();
+    }
+    $this->stopTrackingMail();
     return $this;
   }
 
@@ -289,4 +313,30 @@ class FormWrapper {
     }
   }
 
+  /**
+   * Start tracking any emails sent by this form.
+   *
+   * @noinspection PhpUnhandledExceptionInspection
+   */
+  private function startTrackingMail(): void {
+    $this->originalMailSetting = \Civi::settings()->get('mailing_backend');
+    \Civi::settings()
+      ->set('mailing_backend', array_merge((array) $this->originalMailSetting, ['outBound_option' => \CRM_Mailing_Config::OUTBOUND_OPTION_REDIRECT_TO_DB]));
+    $this->mailSpoolID = (int) \CRM_Core_DAO::singleValueQuery('SELECT MAX(id) FROM civicrm_mailing_spool');
+  }
+
+  /**
+   * Store any mails sent & revert to pre-test behaviour.
+   *
+   * @noinspection PhpUnhandledExceptionInspection
+   */
+  private function stopTrackingMail(): void {
+    $dao = \CRM_Core_DAO::executeQuery('SELECT headers, body FROM civicrm_mailing_spool WHERE id > ' . $this->mailSpoolID . ' ORDER BY id');
+    \CRM_Core_DAO::executeQuery('DELETE FROM civicrm_mailing_spool WHERE id > ' . $this->mailSpoolID);
+    while ($dao->fetch()) {
+      $this->mail[] = ['headers' => $dao->headers, 'body' => $dao->body];
+    }
+    \Civi::settings()->set('mailing_backend', $this->originalMailSetting);
+  }
+
 }
index c8074316022d45b07df4100ef0f816fd0592b12a..6c2fe8f3b6e80dd354593edd0fe618214ba859f5 100644 (file)
@@ -37,29 +37,12 @@ class CRM_Event_Form_ParticipantTest extends CiviUnitTestCase {
     $form = $this->getForm([], [
       'register_date' => date('Ymd'),
       'status_id' => 1,
-      'role_id' => 1,
+      'role_id' => [CRM_Core_PseudoConstant::getKey('CRM_Event_BAO_Participant', 'role_id', 'Attendee')],
     ])->postProcess();
     $this->assertEquals($this->getEventID(), $form->getEventID());
     $this->callAPISuccessGetSingle('Participant', ['id' => $form->getParticipantID()]);
   }
 
-  /**
-   * Test an unpaid event, test role displays in receipt
-   */
-  public function testSubmitUnPaidEvent(): void {
-    $this->getForm(['is_monetary' => FALSE], [
-      'status_id' => 1,
-      'send_receipt' => 1,
-      'from_email_address' => 'admin@example.com',
-      'register_date' => date('Y-m-d H:i:s'),
-      'role_id' => [
-        CRM_Core_PseudoConstant::getKey('CRM_Event_BAO_Participant', 'role_id', 'Volunteer'),
-        CRM_Core_PseudoConstant::getKey('CRM_Event_BAO_Participant', 'role_id', 'Speaker'),
-      ],
-    ])->postProcess();
-    $this->callAPISuccessGetCount('Participant', [], 1);
-  }
-
   /**
    * Test financial items pending transaction is later altered.
    *
@@ -268,7 +251,6 @@ class CRM_Event_Form_ParticipantTest extends CiviUnitTestCase {
     $this->setCurrencySeparators($thousandSeparator);
     $this->swapMessageTemplateForTestTemplate('event_offline_receipt', 'text');
     $this->swapMessageTemplateForTestTemplate('event_offline_receipt');
-    $mut = new CiviMailUtils($this, TRUE);
     // Create an email associated with the logged in contact
     $loggedInContactID = $this->createLoggedInUser();
     $email = $this->callAPISuccess('Email', 'create', [
@@ -299,11 +281,11 @@ class CRM_Event_Form_ParticipantTest extends CiviUnitTestCase {
     $_REQUEST['mode'] = 'Live';
     $submitParams = $this->getSubmitParamsForCreditCardPayment($paymentProcessorID);
     $submitParams['from_email_address'] = $email['id'];
-    $this->submitForm(['is_monetary' => 1, 'financial_type_id' => 1, 'pay_later_receipt' => 'pay us'], $submitParams, TRUE);
+    $message = $this->submitForm(['is_monetary' => 1, 'financial_type_id' => 1, 'pay_later_receipt' => 'pay us'], $submitParams, TRUE)->getFirstMail();
     $participantID = Participant::get()->addWhere('event_id', '=', $this->getEventID('PaidEvent'))->execute()->first()['id'];
     //Check if type is correctly populated in mails.
     //Also check the string email is present not numeric from.
-    $mut->checkMailLog([
+    $this->assertStringContainsStrings($message['headers'] . $message['body'], [
       'contactID:::' . $this->getContactID(),
       'contact.id:::' . $this->getContactID(),
       'eventID:::' . $this->getEventID('PaidEvent'),
@@ -340,6 +322,12 @@ London,',
     $this->callAPISuccess('Email', 'delete', ['id' => $email['id']]);
   }
 
+  public function assertStringContainsStrings($string, $expectedStrings) {
+    foreach ($expectedStrings as $expectedString) {
+      $this->assertStringContainsString($expectedString, $string);
+    }
+  }
+
   /**
    * Get prepared form object.
    *
@@ -349,7 +337,8 @@ London,',
    *
    * @return \Civi\Test\FormWrappers\EventFormParticipant
    *
-   * @throws \CRM_Core_Exception
+   *
+   * @noinspection PhpDocMissingThrowsInspection
    */
   protected function getForm(array $eventParams = [], array $submittedValues = [], bool $isQuickConfig = FALSE): EventFormParticipant {
     $submittedValues['contact_id'] = $this->ids['Contact']['event'] = $this->individualCreate();
@@ -379,11 +368,12 @@ London,',
    * @param array $submittedValues
    * @param bool $isQuickConfig
    *
-   * @throws \CRM_Core_Exception
+   * @return \Civi\Test\FormWrappers\EventFormParticipant
    */
-  protected function submitForm(array $eventParams = [], array $submittedValues = [], bool $isQuickConfig = FALSE): void {
+  protected function submitForm(array $eventParams = [], array $submittedValues = [], bool $isQuickConfig = FALSE): EventFormParticipant {
     $form = $this->getForm($eventParams, $submittedValues, $isQuickConfig);
     $form->postProcess();
+    return $form;
   }
 
   /**
@@ -509,8 +499,7 @@ London,',
    * @throws \CRM_Core_Exception
    */
   public function testSubmitPartialPayment(bool $isQuickConfig): void {
-    $mailUtil = new CiviMailUtils($this, TRUE);
-    $this->submitForm(['is_monetary' => 1, 'start_date' => '2023-02-15 15:00', 'end_date' => '2023-02-15 18:00'], [
+    $email = $this->submitForm(['is_monetary' => 1, 'start_date' => '2023-02-15 15:00', 'end_date' => '2023-02-15 18:00'], [
       'contribution_status_id' => CRM_Core_PseudoConstant::getKey('CRM_Contribute_BAO_Contribution', 'contribution_status_id', 'Completed'),
       'total_amount' => '20',
       'send_receipt' => '1',
@@ -520,8 +509,8 @@ London,',
       'status_id' => CRM_Core_PseudoConstant::getKey('CRM_Event_BAO_Participant', 'status_id', 'Partially paid'),
       'source' => 'I wrote this',
       'note' => 'I wrote a note',
-    ], $isQuickConfig);
-    $this->assertPartialPaymentResult($isQuickConfig, $mailUtil);
+    ], $isQuickConfig)->getFirstMail();
+    $this->assertPartialPaymentResult($isQuickConfig, $email);
   }
 
   /**
@@ -534,15 +523,14 @@ London,',
    * @throws \CRM_Core_Exception
    */
   public function testSubmitPendingPartiallyPaidAddPayment(bool $isQuickConfig): void {
-    $mailUtil = new CiviMailUtils($this, TRUE);
-    $this->submitForm(['is_monetary' => 1, 'start_date' => '2023-02-15 15:00', 'end_date' => '2023-02-15 18:00'], [], $isQuickConfig);
+    $message = $this->submitForm(['is_monetary' => 1, 'start_date' => '2023-02-15 15:00', 'end_date' => '2023-02-15 18:00'], [], $isQuickConfig)->getFirstMail();
     $this->callAPISuccess('Payment', 'create', [
       'contribution_id' => $this->callAPISuccessGetValue('Contribution', ['return' => 'id']),
       'total_amount'  => 20,
       'check_number' => 879,
       'payment_instrument_id' => CRM_Core_PseudoConstant::getKey('CRM_Contribute_BAO_Contribution', 'payment_instrument_id', 'Check'),
     ]);
-    $this->assertPartialPaymentResult($isQuickConfig, $mailUtil, FALSE);
+    $this->assertPartialPaymentResult($isQuickConfig, $message, FALSE);
   }
 
   /**
@@ -557,24 +545,23 @@ London,',
    * @throws \CRM_Core_Exception
    */
   public function testSubmitPendingAddPayment(bool $isQuickConfig): void {
-    $mailUtil = new CiviMailUtils($this, TRUE);
-    $this->submitForm(['is_monetary' => 1, 'start_date' => '2023-02-15 15:00', 'end_date' => '2023-02-15 18:00'], [], $isQuickConfig);
+    $message = $this->submitForm(['is_monetary' => 1, 'start_date' => '2023-02-15 15:00', 'end_date' => '2023-02-15 18:00'], [], $isQuickConfig)->getFirstMail();
     $this->callAPISuccess('Payment', 'create', [
       'contribution_id' => $this->callAPISuccessGetValue('Contribution', ['return' => 'id']),
       'total_amount'  => 20,
       'check_number' => 879,
       'payment_instrument_id' => CRM_Core_PseudoConstant::getKey('CRM_Contribute_BAO_Contribution', 'payment_instrument_id', 'Check'),
     ]);
-    $this->assertPartialPaymentResult($isQuickConfig, $mailUtil, FALSE);
+    $this->assertPartialPaymentResult($isQuickConfig, $message, FALSE);
   }
 
   /**
    * @param bool $isQuickConfig
-   * @param \CiviMailUtils $mut
+   * @param array $message
    * @param bool $isAmountPaidOnForm
    *   Was the amount paid entered on the form (if so this should be on the receipt)
    */
-  protected function assertPartialPaymentResult(bool $isQuickConfig, CiviMailUtils $mut, bool $isAmountPaidOnForm = TRUE): void {
+  protected function assertPartialPaymentResult(bool $isQuickConfig, array $message, bool $isAmountPaidOnForm = TRUE): void {
     $paymentInstrumentID = CRM_Core_PseudoConstant::getKey('CRM_Contribute_BAO_Contribution', 'payment_instrument_id', 'Check');
     $contribution = $this->callAPISuccessGetSingle('Contribution', []);
     $expected = [
@@ -647,7 +634,7 @@ London,',
       'financial_account_id' => 4,
     ], $financialItem);
 
-    $mut->checkMailLog([
+    $this->assertStringContainsStrings($message['headers'] . $message['body'], [
       'From: "FIXME" <info@EXAMPLE.ORG>',
       'To: "Mr. Anthony Anderson II" <anthony_anderson@civicrm.org>',
       'Subject: Event Confirmation - Annual CiviCRM meet - Mr. Anthony Anderson II',
@@ -720,7 +707,7 @@ London,',
       'hidden_custom' => '1',
       'hidden_custom_group_count' => ['' => 1],
       'register_date' => '2020-01-31 00:50:00',
-      'role_id' => [0 => CRM_Core_PseudoConstant::getKey('CRM_Event_BAO_Participant', 'role_id', 'Attendee')],
+      'role_id' => [CRM_Core_PseudoConstant::getKey('CRM_Event_BAO_Participant', 'role_id', 'Attendee')],
       'status_id' => CRM_Core_PseudoConstant::getKey('CRM_Event_BAO_Participant', 'status_id', $participantStatus),
       'source' => 'I wrote this',
       'note' => 'I wrote a note',
@@ -733,7 +720,6 @@ London,',
    * @throws \CRM_Core_Exception
    */
   public function testTransferParticipantRegistration(): void {
-    $mut = new CiviMailUtils($this);
     $this->swapMessageTemplateForInput('event_online_receipt', '{domain.name} {contact.first_name}');
 
     $this->createEventOrder();
@@ -744,14 +730,13 @@ London,',
     $contribution = $this->callAPISuccessGetSingle('Contribution', ['return' => 'id']);
     $toContactID = $this->individualCreate([], 'to');
     $participantId = CRM_Core_DAO::getFieldValue('CRM_Event_BAO_ParticipantPayment', $contribution['id'], 'participant_id', 'contribution_id');
-    $this->getTestForm('CRM_Event_Form_SelfSvcTransfer', [
+    $mail = $this->getTestForm('CRM_Event_Form_SelfSvcTransfer', [
       'contact_id' => $toContactID,
     ], [
       'pid' => $participantId,
       'is_backoffice' => 1,
-    ])->processForm();
-    $mut->checkAllMailLog(['Default Domain Name Anthony']);
-    $mut->clearMessages();
+    ])->processForm()->getFirstMailBody();
+    $this->assertStringContainsString('Default Domain Name Anthony', $mail);
     $this->revertTemplateToReservedTemplate();
 
     //Assert participant is transferred to $toContactId.
index a6d6c79502d4c47cd475084ba61d7848feb50856..b529b561af2f97ae3e8371cb09e143a6be0b661b 100644 (file)
@@ -292,12 +292,10 @@ class CRM_Event_Form_Registration_ConfirmTest extends CiviUnitTestCase {
    */
   public function testTaxMultipleParticipant(): void {
     $this->swapMessageTemplateForTestTemplate('event_online_receipt', 'text');
-
-    $mut = new CiviMailUtils($this);
     $this->createLoggedInUser();
     $this->eventCreatePaid();
     $this->addTaxAccountToFinancialType(CRM_Core_PseudoConstant::getKey('CRM_Contribute_BAO_Contribution', 'financial_type_id', 'Event Fee'));
-    $this->getTestForm('CRM_Event_Form_Registration_Register', [
+    $form = $this->getTestForm('CRM_Event_Form_Registration_Register', [
       'first_name' => 'Participant1',
       'last_name' => 'LastName',
       'email-Primary' => 'participant1@example.com',
@@ -336,23 +334,23 @@ class CRM_Event_Form_Registration_ConfirmTest extends CiviUnitTestCase {
     $this->assertContains(' (multiple participants)', $contribution['amount_level']);
     $this->assertEquals(90, $contribution['tax_amount'], 'Invalid Tax amount.');
     $this->assertEquals(990, $contribution['total_amount'], 'Invalid Tax amount.');
-    $mailSent = $mut->getAllMessages();
+    $mailSent = $form->getMail();
     $this->assertCount(3, $mailSent, 'Three mails should have been sent to the 3 participants.');
-    $this->assertStringContainsString('contactID:::' . $contribution['contact_id'], $mailSent[0]);
-    $this->assertStringContainsString('contactID:::' . ($contribution['contact_id'] + 1), $mailSent[1]);
-
+    $this->assertStringContainsString('contactID:::' . $contribution['contact_id'], $mailSent[0]['body']);
+    $this->assertStringContainsString('contactID:::' . ($contribution['contact_id'] + 1), $mailSent[1]['body']);
+    $mut = new CiviMailUtils($this);
     $this->validateAllContributions();
     $this->validateAllPayments();
     $this->callAPISuccess('Payment', 'create', ['total_amount' => 990, 'payment_type_id' => 'Cash', 'contribution_id' => $contribution['id']]);
     $mailSent = $mut->getAllMessages();
-    $this->assertCount(6, $mailSent);
+    $this->assertCount(3, $mailSent);
 
-    $this->assertStringContainsString('participant_status:::Registered', $mailSent[3]);
-    $this->assertStringContainsString('Dear Participant2', $mailSent[3]);
+    $this->assertStringContainsString('participant_status:::Registered', $mailSent[0]);
+    $this->assertStringContainsString('Dear Participant2', $mailSent[0]);
 
-    $this->assertStringContainsString('contactID:::' . ($contribution['contact_id'] + 1), $mailSent[3]);
-    $this->assertStringContainsString('contactID:::' . ($contribution['contact_id'] + 2), $mailSent[4]);
-    $this->assertStringContainsString('contactID:::' . $contribution['contact_id'], $mailSent[5]);
+    $this->assertStringContainsString('contactID:::' . ($contribution['contact_id'] + 1), $mailSent[0]);
+    $this->assertStringContainsString('contactID:::' . ($contribution['contact_id'] + 2), $mailSent[1]);
+    $this->assertStringContainsString('contactID:::' . $contribution['contact_id'], $mailSent[2]);
   }
 
   /**