Testing - Add more examples of tests which register listeners
authorTim Otten <totten@civicrm.org>
Wed, 26 May 2021 04:27:54 +0000 (21:27 -0700)
committerTim Otten <totten@civicrm.org>
Wed, 26 May 2021 23:52:14 +0000 (16:52 -0700)
tests/phpunit/Civi/Test/ExampleHookTest.php
tests/phpunit/Civi/Test/ExampleSubscriberTest.php [new file with mode: 0644]

index b84d80ceac972881f43d903583e28563e0993b03..2dda38d483b428f40efbc06509ce0b53fb8fdab9 100644 (file)
@@ -4,7 +4,16 @@ namespace Civi\Test;
 use Civi\Angular\Page\Main;
 
 /**
- * This is an example of a barebones test which uses a hook (based on CiviTestListener).
+ * This is an example of a barebones test which implements `HookInterface`. Methods are automatically scanned to
+ * find event-listeners based on a naming convention:
+ *
+ * - `function hook_*($arg1, &$arg2, ...)`: Bind to eponymous hook. Receive a list of ordered parameters.
+ * - 'function on_*($event)`: Bind to eponymous Symfony event. Receive an event object.
+ *
+ * The underlying mechanism behind this is:
+ *
+ * - When booting headless Civi, `CRM_Utils_System_UnitTests::initialize()` looks up the active test object.
+ * - It uses `EventScanner` to check the interfaces & methods for any listeners.
  *
  * @group headless
  */
@@ -15,6 +24,8 @@ class ExampleHookTest extends \PHPUnit\Framework\TestCase implements HeadlessInt
    */
   protected $contact;
 
+  protected $tracker;
+
   public function setUpHeadless() {
     return \Civi\Test::headless()->apply();
   }
@@ -25,6 +36,7 @@ class ExampleHookTest extends \PHPUnit\Framework\TestCase implements HeadlessInt
     ]);
     $session = \CRM_Core_Session::singleton();
     $session->set('userID', $this->contact->id);
+    $this->tracker = ['civi.api.resolve' => [], 'civi.api.prepare' => []];
   }
 
   protected function tearDown(): void {
@@ -32,10 +44,39 @@ class ExampleHookTest extends \PHPUnit\Framework\TestCase implements HeadlessInt
   }
 
   /**
+   * Listen to hook_civicrm_alterContent in traditional hook format.
+   *
    * @see \CRM_Utils_Hook::alterContent
    */
   public function hook_civicrm_alterContent(&$content, $context, $tplName, &$object) {
-    $content .= "zzzyyyxxx";
+    $content .= ' ' . __FUNCTION__;
+  }
+
+  /**
+   * Listen to hook_civicrm_alterContent in Symfony event format.
+   *
+   * @see \CRM_Utils_Hook::alterContent
+   */
+  public function on_hook_civicrm_alterContent(\Civi\Core\Event\GenericHookEvent $event) {
+    $event->content .= ' ' . __FUNCTION__;
+  }
+
+  /**
+   * Listen to `civi.api.resolve` in Symfony event format.
+   *
+   * @see \Civi\API\Event\ResolveEvent
+   */
+  public function on_civi_api_resolve(\Civi\API\Event\ResolveEvent $event) {
+    $this->tracker['civi.api.resolve'][__FUNCTION__] = TRUE;
+  }
+
+  /**
+   * Listen to `civi.api.resolve` in Symfony event format.
+   *
+   * @see \Civi\API\Event\PrepareEvent
+   */
+  public function on_civi_api_prepare(\Civi\API\Event\PrepareEvent $event) {
+    $this->tracker['civi.api.prepare'][__FUNCTION__] = TRUE;
   }
 
   public function testPageOutput() {
@@ -44,7 +85,15 @@ class ExampleHookTest extends \PHPUnit\Framework\TestCase implements HeadlessInt
     $p->run();
     $content = ob_get_contents();
     ob_end_clean();
-    $this->assertRegExp(';zzzyyyxxx;', $content);
+    $this->assertRegExp('; hook_civicrm_alterContent on_hook_civicrm_alterContent;', $content);
+  }
+
+  public function testGetFields() {
+    $this->assertEquals([], $this->tracker['civi.api.resolve']);
+    $this->assertEquals([], $this->tracker['civi.api.prepare']);
+    \civicrm_api3('Contact', 'getfields', []);
+    $this->assertEquals(['on_civi_api_resolve' => TRUE], $this->tracker['civi.api.resolve']);
+    $this->assertEquals(['on_civi_api_prepare' => TRUE], $this->tracker['civi.api.prepare']);
   }
 
 }
diff --git a/tests/phpunit/Civi/Test/ExampleSubscriberTest.php b/tests/phpunit/Civi/Test/ExampleSubscriberTest.php
new file mode 100644 (file)
index 0000000..d1aa4f5
--- /dev/null
@@ -0,0 +1,87 @@
+<?php
+namespace Civi\Test;
+
+use Civi\Angular\Page\Main;
+use Civi\Core\Event\GenericHookEvent;
+use Symfony\Component\EventDispatcher\EventSubscriberInterface;
+
+/**
+ * This is an example of a barebones test which implements `EventSubscriberInterface`. The method `getSubscribedEvents()` is
+ * used to get a list of listeners.
+ *
+ * The underlying mechanism behind this is:
+ *
+ * - When booting headless Civi, `CRM_Utils_System_UnitTests::initialize()` looks up the active test object.
+ * - It uses `EventScanner` to check the interfaces & methods for any listeners.
+ *
+ * @group headless
+ */
+class ExampleSubscriberTest extends \PHPUnit\Framework\TestCase implements HeadlessInterface, EventSubscriberInterface {
+
+  /**
+   * @var \CRM_Contact_DAO_Contact
+   */
+  protected $contact;
+
+  protected $tracker;
+
+  public function setUpHeadless() {
+    return \Civi\Test::headless()->apply();
+  }
+
+  protected function setUp(): void {
+    $this->contact = \CRM_Core_DAO::createTestObject('CRM_Contact_DAO_Contact', [
+      'contact_type' => 'Individual',
+    ]);
+    $session = \CRM_Core_Session::singleton();
+    $session->set('userID', $this->contact->id);
+    $this->tracker = ['civi.api.resolve' => [], 'civi.api.prepare' => []];
+  }
+
+  protected function tearDown(): void {
+    $this->contact->delete();
+  }
+
+  public static function getSubscribedEvents() {
+    return [
+      'civi.api.resolve' => 'myCiviApiResolve',
+      'civi.api.prepare' => ['myCiviApiPrepare', 1234],
+      'hook_civicrm_alterContent' => ['myAlterContentObject', -7000],
+      '&hook_civicrm_alterContent' => ['myAlterContentParams', -8000],
+    ];
+  }
+
+  public function myCiviApiResolve(\Civi\API\Event\ResolveEvent $event) {
+    $this->tracker['civi.api.resolve'][__FUNCTION__] = TRUE;
+  }
+
+  public function myCiviApiPrepare(\Civi\API\Event\PrepareEvent $event) {
+    $this->tracker['civi.api.prepare'][__FUNCTION__] = TRUE;
+  }
+
+  public function myAlterContentObject(GenericHookEvent $event) {
+    $event->content .= ' ' . __FUNCTION__;
+  }
+
+  public function myAlterContentParams(&$content, $context, $tplName, &$object) {
+    $content .= ' ' . __FUNCTION__;
+  }
+
+  public function testPageOutput() {
+    ob_start();
+    $p = new Main();
+    $p->run();
+    $content = ob_get_contents();
+    ob_end_clean();
+    $this->assertRegExp(';myAlterContentObject myAlterContentParams;', $content);
+  }
+
+  public function testGetFields() {
+    $this->assertEquals([], $this->tracker['civi.api.resolve']);
+    $this->assertEquals([], $this->tracker['civi.api.prepare']);
+    \civicrm_api3('Contact', 'getfields', []);
+    $this->assertEquals(['myCiviApiResolve' => TRUE], $this->tracker['civi.api.resolve']);
+    $this->assertEquals(['myCiviApiPrepare' => TRUE], $this->tracker['civi.api.prepare']);
+  }
+
+}