You are here

class AllTermsArgumentTest in Search API 8

Tests whether the SearchApiAllTerms argument plugin works correctly.

@group search_api

@coversDefaultClass \Drupal\search_api\Plugin\views\argument\SearchApiAllTerms

Hierarchy

Expanded class hierarchy of AllTermsArgumentTest

File

tests/src/Unit/Views/AllTermsArgumentTest.php, line 22

Namespace

Drupal\Tests\search_api\Unit\Views
View source
class AllTermsArgumentTest extends UnitTestCase {
  use TaxonomyTestTrait;

  /**
   * The plugin under test.
   *
   * @var \Drupal\search_api\Plugin\views\argument\SearchApiAllTerms
   */
  protected $plugin;

  /**
   * The first condition group set on the query.
   *
   * @var \Drupal\search_api\Query\ConditionGroupInterface|null
   */
  protected $conditionGroup = NULL;

  /**
   * Whether or not the query has been aborted, or the abort message (if given).
   *
   * @var bool|string
   */
  protected $aborted = FALSE;

  /**
   * {@inheritdoc}
   */
  public function setUp() {
    parent::setUp();
    $this
      ->setupContainer();
    $this->plugin = new SearchApiAllTerms([], 'search_api_all_terms', [
      'vocabulary_fields' => [
        'voc_a' => [
          'field_voc_a',
        ],
        'voc_b' => [
          'field_voc_b_1',
          'field_voc_b_2',
        ],
      ],
    ]);
    $this->plugin->options['break_phrase'] = TRUE;
    $term_values = [
      1 => [
        'id' => 1,
        'label' => 'Term 1',
        'bundle' => 'voc_a',
      ],
      2 => [
        'id' => 2,
        'label' => 'Term 2',
        'bundle' => 'voc_a',
      ],
      3 => [
        'id' => 3,
        'label' => 'Term 3',
        'bundle' => 'voc_b',
      ],
      4 => [
        'id' => 4,
        'label' => 'Term 4',
        'bundle' => 'voc_c',
      ],
    ];
    $terms = [];
    foreach ($term_values as $tid => $values) {
      $term = $this
        ->createMock(TermInterface::class);
      foreach ($values as $field => $value) {
        $term
          ->method($field)
          ->willReturn($value);
      }
      $terms[$tid] = $term;
    }
    $this->termStorage
      ->method('loadMultiple')
      ->willReturnCallback(function (array $tids) use ($terms) : array {
      return array_intersect_key($terms, array_flip($tids));
    });
  }

  /**
   * Tests whether the contextual filter works correctly.
   *
   * @covers ::query
   */
  public function testConditionalFilter() {
    $query = $this
      ->createMock(SearchApiQuery::class);
    $query
      ->method('createConditionGroup')
      ->willReturnCallback(function (string $conjunction, array $tags) {
      Assert::assertEmpty($tags);
      if (isset($this->conditionGroup)) {
        return new ConditionGroup($conjunction);
      }
      return $this->conditionGroup = new ConditionGroup($conjunction);
    });
    $query
      ->method('addConditionGroup')
      ->willReturnCallback(function (ConditionGroupInterface $added_condition_group, $group = NULL) {
      Assert::assertNull($group);
      Assert::assertSame($this->conditionGroup, $added_condition_group);
    });
    $query
      ->method('abort')
      ->willReturnCallback(function ($message = NULL) {
      $this->aborted = TRUE;
      if ($message !== NULL) {
        if ($message instanceof TranslatableMarkup) {
          $message = strtr($message
            ->getUntranslatedString(), $message
            ->getArguments());
        }
        $this->aborted = $message;
      }
    });
    $this->plugin->query = $query;
    $this
      ->executePluginQuery('1,2,3');
    $this
      ->assertFalse($this->aborted);
    $this
      ->assertEquals('AND', $this->conditionGroup
      ->getConjunction());
    $expected = [
      new Condition('field_voc_a', 1),
      new Condition('field_voc_a', 2),
      (new ConditionGroup('OR'))
        ->addCondition('field_voc_b_1', 3)
        ->addCondition('field_voc_b_2', 3),
    ];
    $this
      ->assertEquals($expected, $this->conditionGroup
      ->getConditions());
    $this
      ->executePluginQuery('1+2+3');
    $this
      ->assertFalse($this->aborted);
    $this
      ->assertEquals('OR', $this->conditionGroup
      ->getConjunction());
    $expected = [
      new Condition('field_voc_a', [
        1,
        2,
      ], 'IN'),
      new Condition('field_voc_b_1', [
        3,
      ], 'IN'),
      new Condition('field_voc_b_2', [
        3,
      ], 'IN'),
    ];
    $this
      ->assertEquals($expected, $this->conditionGroup
      ->getConditions());

    // Set the filter to negated.
    $this->plugin->options['not'] = TRUE;
    $this
      ->executePluginQuery('1,2,3');
    $this
      ->assertFalse($this->aborted);
    $this
      ->assertEquals('OR', $this->conditionGroup
      ->getConjunction());
    $expected = [
      new Condition('field_voc_a', 1, '<>'),
      new Condition('field_voc_a', 2, '<>'),
      (new ConditionGroup('AND'))
        ->addCondition('field_voc_b_1', 3, '<>')
        ->addCondition('field_voc_b_2', 3, '<>'),
    ];
    $this
      ->assertEquals($expected, $this->conditionGroup
      ->getConditions());
    $this
      ->executePluginQuery('1+2+3');
    $this
      ->assertFalse($this->aborted);
    $this
      ->assertEquals('AND', $this->conditionGroup
      ->getConjunction());
    $expected = [
      new Condition('field_voc_a', [
        1,
        2,
      ], 'NOT IN'),
      new Condition('field_voc_b_1', [
        3,
      ], 'NOT IN'),
      new Condition('field_voc_b_2', [
        3,
      ], 'NOT IN'),
    ];
    $this
      ->assertEquals($expected, $this->conditionGroup
      ->getConditions());

    // Check various error conditions.
    $this->plugin->options['not'] = FALSE;
    $this
      ->executePluginQuery('1,2,foo');
    $this
      ->assertEquals('Invalid taxonomy term ID given for "All taxonomy term fields" contextual filter.', $this->aborted);
    $this
      ->executePluginQuery('1+2+foo');
    $this
      ->assertFalse($this->aborted);
    $this
      ->assertEquals('OR', $this->conditionGroup
      ->getConjunction());
    $expected = [
      new Condition('field_voc_a', [
        1,
        2,
      ], 'IN'),
    ];
    $this
      ->assertEquals($expected, $this->conditionGroup
      ->getConditions());
    $this
      ->executePluginQuery('1,2,4');
    $this
      ->assertEquals('"All taxonomy term fields" contextual filter could not be applied as taxonomy term Term 4 (ID: 4) belongs to vocabulary voc_c, not contained in any indexed fields.', $this->aborted);
    $this
      ->executePluginQuery('1+2+4');
    $this
      ->assertFalse($this->aborted);
    $this
      ->assertEquals('OR', $this->conditionGroup
      ->getConjunction());
    $expected = [
      new Condition('field_voc_a', [
        1,
        2,
      ], 'IN'),
    ];
    $this
      ->assertEquals($expected, $this->conditionGroup
      ->getConditions());
    $this->plugin->options['not'] = TRUE;
    $this
      ->executePluginQuery('1+2+4');
    $this
      ->assertEquals('"All taxonomy term fields" contextual filter could not be applied as taxonomy term Term 4 (ID: 4) belongs to vocabulary voc_c, not contained in any indexed fields.', $this->aborted);
    $this
      ->executePluginQuery('1,2,4');
    $this
      ->assertFalse($this->aborted);
    $this
      ->assertEquals('OR', $this->conditionGroup
      ->getConjunction());
    $expected = [
      new Condition('field_voc_a', 1, '<>'),
      new Condition('field_voc_a', 2, '<>'),
    ];
    $this
      ->assertEquals($expected, $this->conditionGroup
      ->getConditions());
    $this->plugin->options['not'] = FALSE;
    $this->plugin->options['break_phrase'] = FALSE;
    $this
      ->executePluginQuery('1,2,3');
    $this
      ->assertEquals('No valid taxonomy term IDs given for "All taxonomy term fields" contextual filter.', $this->aborted);
    $this->plugin->options['not'] = TRUE;
    $this
      ->executePluginQuery('1,2,3');
    $this
      ->assertFalse($this->aborted);
  }

  /**
   * Executes the plugin's query() method, after resetting the original state.
   *
   * @param string $argument
   *   The argument string to set on the plugin.
   */
  protected function executePluginQuery(string $argument) {
    $this->conditionGroup = NULL;
    $this->aborted = FALSE;
    $this->plugin->value = NULL;
    $this->plugin->argument_validated = NULL;
    $this->plugin->argument = $argument;
    $this->plugin
      ->query();
  }

}

Members

Namesort descending Modifiers Type Description Overrides
AllTermsArgumentTest::$aborted protected property Whether or not the query has been aborted, or the abort message (if given).
AllTermsArgumentTest::$conditionGroup protected property The first condition group set on the query.
AllTermsArgumentTest::$plugin protected property The plugin under test.
AllTermsArgumentTest::executePluginQuery protected function Executes the plugin's query() method, after resetting the original state.
AllTermsArgumentTest::setUp public function Overrides UnitTestCase::setUp
AllTermsArgumentTest::testConditionalFilter public function Tests whether the contextual filter works correctly.
PhpunitCompatibilityTrait::getMock Deprecated public function Returns a mock object for the specified class using the available method.
PhpunitCompatibilityTrait::setExpectedException Deprecated public function Compatibility layer for PHPUnit 6 to support PHPUnit 4 code.
TaxonomyTestTrait::$container protected property The test container.
TaxonomyTestTrait::$entityRepository protected property The mock entity repository service.
TaxonomyTestTrait::$termStorage protected property The mock term storage.
TaxonomyTestTrait::setupContainer public function Sets up the container with necessary services.
UnitTestCase::$randomGenerator protected property The random generator.
UnitTestCase::$root protected property The app root. 1
UnitTestCase::assertArrayEquals protected function Asserts if two arrays are equal by sorting them first.
UnitTestCase::getBlockMockWithMachineName Deprecated protected function Mocks a block with a block plugin. 1
UnitTestCase::getClassResolverStub protected function Returns a stub class resolver.
UnitTestCase::getConfigFactoryStub public function Returns a stub config factory that behaves according to the passed array.
UnitTestCase::getConfigStorageStub public function Returns a stub config storage that returns the supplied configuration.
UnitTestCase::getContainerWithCacheTagsInvalidator protected function Sets up a container with a cache tags invalidator.
UnitTestCase::getRandomGenerator protected function Gets the random generator for the utility methods.
UnitTestCase::getStringTranslationStub public function Returns a stub translation manager that just returns the passed string.
UnitTestCase::randomMachineName public function Generates a unique random string containing letters and numbers.