SearchKit - Add unit test for SearchDisplay::run
authorColeman Watts <coleman@civicrm.org>
Wed, 31 Mar 2021 19:50:19 +0000 (15:50 -0400)
committerColeman Watts <coleman@civicrm.org>
Mon, 5 Apr 2021 19:14:51 +0000 (15:14 -0400)
ext/search/Civi/Api4/Action/SearchDisplay/Run.php
ext/search/phpunit.xml.dist [new file with mode: 0644]
ext/search/tests/phpunit/api/v4/SearchDisplay/SearchRunTest.php [new file with mode: 0644]
ext/search/tests/phpunit/bootstrap.php [new file with mode: 0644]

index 1d736be0c85027d114999df4873eea21ad1ed11f..5a8d5504ef81977445c2f161a4294527bfbee219 100644 (file)
@@ -32,7 +32,7 @@ class Run extends \Civi\Api4\Generic\AbstractAction {
    * Array of fields to use for ordering the results
    * @var array
    */
-  protected $sort;
+  protected $sort = [];
 
   /**
    * Should this api call return a page of results or the row_count or the ids
diff --git a/ext/search/phpunit.xml.dist b/ext/search/phpunit.xml.dist
new file mode 100644 (file)
index 0000000..1990cb6
--- /dev/null
@@ -0,0 +1,18 @@
+<?xml version="1.0"?>
+<phpunit backupGlobals="false" backupStaticAttributes="false" colors="true" convertErrorsToExceptions="true" convertNoticesToExceptions="true" convertWarningsToExceptions="true" processIsolation="false" stopOnFailure="false" bootstrap="tests/phpunit/bootstrap.php">
+  <testsuites>
+    <testsuite name="SearchKit Test Suite">
+      <directory>./tests/phpunit</directory>
+    </testsuite>
+  </testsuites>
+  <filter>
+    <whitelist>
+      <directory suffix=".php">./</directory>
+    </whitelist>
+  </filter>
+  <listeners>
+    <listener class="Civi\Test\CiviTestListener">
+      <arguments/>
+    </listener>
+  </listeners>
+</phpunit>
diff --git a/ext/search/tests/phpunit/api/v4/SearchDisplay/SearchRunTest.php b/ext/search/tests/phpunit/api/v4/SearchDisplay/SearchRunTest.php
new file mode 100644 (file)
index 0000000..6ffb579
--- /dev/null
@@ -0,0 +1,105 @@
+<?php
+namespace api\v4\SearchDisplay;
+
+use Civi\Api4\Contact;
+use Civi\Test\HeadlessInterface;
+use Civi\Test\TransactionalInterface;
+
+/**
+ * @group headless
+ */
+class SearchRunTest extends \PHPUnit\Framework\TestCase implements HeadlessInterface, TransactionalInterface {
+
+  public function setUpHeadless() {
+    // Civi\Test has many helpers, like install(), uninstall(), sql(), and sqlFile().
+    // See: https://docs.civicrm.org/dev/en/latest/testing/phpunit/#civitest
+    return \Civi\Test::headless()
+      ->installMe(__DIR__)
+      ->apply();
+  }
+
+  public function setUp() {
+    parent::setUp();
+  }
+
+  public function tearDown() {
+    parent::tearDown();
+  }
+
+  /**
+   * Test running a searchDisplay with various filters.
+   */
+  public function testRunDisplay() {
+    $lastName = uniqid(__FUNCTION__);
+    $sampleData = [
+      ['first_name' => 'One', 'last_name' => $lastName],
+      ['first_name' => 'Two', 'last_name' => $lastName],
+      ['first_name' => 'Three', 'last_name' => $lastName],
+      ['first_name' => 'Four', 'last_name' => $lastName],
+    ];
+    Contact::save(FALSE)->setRecords($sampleData)->execute();
+
+    $params = [
+      'checkPermissions' => FALSE,
+      'return' => 'page:1',
+      'savedSearch' => [
+        'api_entity' => 'Contact',
+        'api_params' => [
+          'version' => 4,
+          'select' => ['id', 'first_name', 'last_name'],
+          'where' => [],
+        ],
+      ],
+      'display' => [
+        'type' => 'table',
+        'label' => '',
+        'settings' => [
+          'limit' => 20,
+          'pager' => TRUE,
+          'columns' => [
+            [
+              'key' => 'id',
+              'label' => 'Contact ID',
+              'dataType' => 'Integer',
+              'type' => 'field',
+            ],
+            [
+              'key' => 'first_name',
+              'label' => 'First Name',
+              'dataType' => 'String',
+              'type' => 'field',
+            ],
+            [
+              'key' => 'last_name',
+              'label' => 'Last Name',
+              'dataType' => 'String',
+              'type' => 'field',
+            ],
+          ],
+          'sort' => [
+            ['id', 'ASC'],
+          ],
+        ],
+      ],
+      'filters' => ['last_name' => $lastName],
+      'afform' => NULL,
+    ];
+
+    $result = civicrm_api4('SearchDisplay', 'run', $params);
+    $this->assertCount(4, $result);
+
+    $params['filters']['first_name'] = ['One', 'Two'];
+    $result = civicrm_api4('SearchDisplay', 'run', $params);
+    $this->assertCount(2, $result);
+    $this->assertEquals('One', $result[0]['first_name']);
+    $this->assertEquals('Two', $result[1]['first_name']);
+
+    $params['filters'] = ['id' => ['>' => $result[0]['id'], '<=' => $result[1]['id'] + 1]];
+    $params['sort'] = [['first_name', 'ASC']];
+    $result = civicrm_api4('SearchDisplay', 'run', $params);
+    $this->assertCount(2, $result);
+    $this->assertEquals('Three', $result[0]['first_name']);
+    $this->assertEquals('Two', $result[1]['first_name']);
+  }
+
+}
diff --git a/ext/search/tests/phpunit/bootstrap.php b/ext/search/tests/phpunit/bootstrap.php
new file mode 100644 (file)
index 0000000..a5b4925
--- /dev/null
@@ -0,0 +1,63 @@
+<?php
+
+ini_set('memory_limit', '2G');
+ini_set('safe_mode', 0);
+// phpcs:disable
+eval(cv('php:boot --level=classloader', 'phpcode'));
+// phpcs:enable
+// Allow autoloading of PHPUnit helper classes in this extension.
+$loader = new \Composer\Autoload\ClassLoader();
+$loader->add('CRM_', __DIR__);
+$loader->add('Civi\\', __DIR__);
+$loader->add('api_', __DIR__);
+$loader->add('api\\', __DIR__);
+$loader->register();
+
+/**
+ * Call the "cv" command.
+ *
+ * @param string $cmd
+ *   The rest of the command to send.
+ * @param string $decode
+ *   Ex: 'json' or 'phpcode'.
+ * @return string
+ *   Response output (if the command executed normally).
+ * @throws \RuntimeException
+ *   If the command terminates abnormally.
+ */
+function cv($cmd, $decode = 'json') {
+  $cmd = 'cv ' . $cmd;
+  $descriptorSpec = array(0 => array("pipe", "r"), 1 => array("pipe", "w"), 2 => STDERR);
+  $oldOutput = getenv('CV_OUTPUT');
+  putenv("CV_OUTPUT=json");
+
+  // Execute `cv` in the original folder. This is a work-around for
+  // phpunit/codeception, which seem to manipulate PWD.
+  $cmd = sprintf('cd %s; %s', escapeshellarg(getenv('PWD')), $cmd);
+
+  $process = proc_open($cmd, $descriptorSpec, $pipes, __DIR__);
+  putenv("CV_OUTPUT=$oldOutput");
+  fclose($pipes[0]);
+  $result = stream_get_contents($pipes[1]);
+  fclose($pipes[1]);
+  if (proc_close($process) !== 0) {
+    throw new RuntimeException("Command failed ($cmd):\n$result");
+  }
+  switch ($decode) {
+    case 'raw':
+      return $result;
+
+    case 'phpcode':
+      // If the last output is /*PHPCODE*/, then we managed to complete execution.
+      if (substr(trim($result), 0, 12) !== "/*BEGINPHP*/" || substr(trim($result), -10) !== "/*ENDPHP*/") {
+        throw new \RuntimeException("Command failed ($cmd):\n$result");
+      }
+      return $result;
+
+    case 'json':
+      return json_decode($result, 1);
+
+    default:
+      throw new RuntimeException("Bad decoder format ($decode)");
+  }
+}