You are here

class IntegrityCheckTest in Rules 8.3

Test the integrity check functionality during configuration time.

@group Rules

Hierarchy

Expanded class hierarchy of IntegrityCheckTest

File

tests/src/Unit/Integration/Engine/IntegrityCheckTest.php, line 16

Namespace

Drupal\Tests\rules\Unit\Integration\Engine
View source
class IntegrityCheckTest extends RulesEntityIntegrationTestBase {

  /**
   * Tests that the integrity check can be invoked.
   */
  public function testIntegrityCheck() {
    $rule = $this->rulesExpressionManager
      ->createRule();
    $rule
      ->addAction('rules_entity_save', ContextConfig::create()
      ->map('entity', 'entity'));
    $violation_list = RulesComponent::create($rule)
      ->addContextDefinition('entity', ContextDefinition::create('entity'))
      ->checkIntegrity();
    $this
      ->assertEquals(0, iterator_count($violation_list));
  }

  /**
   * Tests that a wrongly configured variable name triggers a violation.
   */
  public function testUnknownVariable() {
    $rule = $this->rulesExpressionManager
      ->createRule();
    $action = $this->rulesExpressionManager
      ->createAction('rules_entity_save', ContextConfig::create()
      ->map('entity', 'unknown_variable'));
    $rule
      ->addExpressionObject($action);
    $violation_list = RulesComponent::create($rule)
      ->checkIntegrity();
    $this
      ->assertEquals(1, iterator_count($violation_list));
    $violation = $violation_list[0];

    // The Exception message part of the output should be HTML-escaped.
    $this
      ->assertEquals("Data selector <em class=\"placeholder\">unknown_variable</em> for context <em class=\"placeholder\">Entity</em> is invalid. Unable to get variable &#039;unknown_variable&#039;; it is not defined.", (string) $violation
      ->getMessage());
    $this
      ->assertEquals($action
      ->getUuid(), $violation
      ->getUuid());
  }

  /**
   * Tests that the integrity check with UUID works.
   */
  public function testCheckUuid() {
    $rule = $this->rulesExpressionManager
      ->createRule();

    // Just use a rule with 2 dummy actions.
    $rule
      ->addAction('rules_entity_save', ContextConfig::create()
      ->map('entity', 'unknown_variable_1'));
    $second_action = $this->rulesExpressionManager
      ->createAction('rules_entity_save', ContextConfig::create()
      ->map('entity', 'unknown_variable_2'));
    $rule
      ->addExpressionObject($second_action);
    $all_violations = RulesComponent::create($rule)
      ->addContextDefinition('entity', ContextDefinition::create('entity'))
      ->checkIntegrity();
    $this
      ->assertEquals(2, iterator_count($all_violations));
    $uuid_violations = $all_violations
      ->getFor($second_action
      ->getUuid());
    $this
      ->assertEquals(1, count($uuid_violations));
    $violation = $uuid_violations[0];

    // The Exception message part of the output should be HTML-escaped.
    $this
      ->assertEquals("Data selector <em class=\"placeholder\">unknown_variable_2</em> for context <em class=\"placeholder\">Entity</em> is invalid. Unable to get variable &#039;unknown_variable_2&#039;; it is not defined.", (string) $violation
      ->getMessage());
    $this
      ->assertEquals($second_action
      ->getUuid(), $violation
      ->getUuid());
  }

  /**
   * Tests that an invalid condition plugin ID results in a violation.
   */
  public function testInvalidCondition() {
    $rule = $this->rulesExpressionManager
      ->createRule();
    $condition = $this->rulesExpressionManager
      ->createCondition('invalid_condition_id');
    $rule
      ->addExpressionObject($condition);
    $violations = RulesComponent::create($rule)
      ->checkIntegrity();
    $this
      ->assertEquals(1, iterator_count($violations));
    $this
      ->assertEquals('Condition plugin <em class="placeholder">invalid_condition_id</em> does not exist', (string) $violations[0]
      ->getMessage());
    $this
      ->assertEquals($condition
      ->getUuid(), $violations[0]
      ->getUuid());
  }

  /**
   * Tests that a missing condition plugin ID results in a violation.
   */
  public function testMissingCondition() {
    $rule = $this->rulesExpressionManager
      ->createRule();
    $condition = $this->rulesExpressionManager
      ->createCondition('');
    $rule
      ->addExpressionObject($condition);
    $violations = RulesComponent::create($rule)
      ->checkIntegrity();
    $this
      ->assertEquals(1, iterator_count($violations));
    $this
      ->assertEquals('Condition plugin ID is missing', (string) $violations[0]
      ->getMessage());
    $this
      ->assertEquals($condition
      ->getUuid(), $violations[0]
      ->getUuid());
  }

  /**
   * Tests that an invalid action plugin ID results in a violation.
   */
  public function testInvalidAction() {
    $rule = $this->rulesExpressionManager
      ->createRule();
    $action = $this->rulesExpressionManager
      ->createAction('invalid_action_id');
    $rule
      ->addExpressionObject($action);
    $violations = RulesComponent::create($rule)
      ->checkIntegrity();
    $this
      ->assertEquals(1, iterator_count($violations));
    $this
      ->assertEquals('Action plugin <em class="placeholder">invalid_action_id</em> does not exist', (string) $violations[0]
      ->getMessage());
    $this
      ->assertEquals($action
      ->getUuid(), $violations[0]
      ->getUuid());
  }

  /**
   * Tests that a missing action plugin ID results in a violation.
   */
  public function testMissingAction() {
    $rule = $this->rulesExpressionManager
      ->createRule();
    $action = $this->rulesExpressionManager
      ->createAction('');
    $rule
      ->addExpressionObject($action);
    $violations = RulesComponent::create($rule)
      ->checkIntegrity();
    $this
      ->assertEquals(1, iterator_count($violations));
    $this
      ->assertEquals('Action plugin ID is missing', (string) $violations[0]
      ->getMessage());
    $this
      ->assertEquals($action
      ->getUuid(), $violations[0]
      ->getUuid());
  }

  /**
   * Tests invalid characters in provided variables.
   */
  public function testInvalidProvidedName() {
    $rule = $this->rulesExpressionManager
      ->createRule();

    // The condition provides a "provided_text" variable.
    $condition = $this->rulesExpressionManager
      ->createCondition('rules_test_provider', ContextConfig::create()
      ->provideAs('provided_text', 'invalid_näme'));
    $rule
      ->addExpressionObject($condition);
    $violation_list = RulesComponent::create($rule)
      ->checkIntegrity();
    $this
      ->assertEquals(1, iterator_count($violation_list));
    $this
      ->assertEquals('Provided variable name <em class="placeholder">invalid_näme</em> contains not allowed characters.', (string) $violation_list[0]
      ->getMessage());
    $this
      ->assertEquals($condition
      ->getUuid(), $violation_list[0]
      ->getUuid());
  }

  /**
   * Tests the input restriction on contexts.
   */
  public function testInputRestriction() {
    $rule = $this->rulesExpressionManager
      ->createRule();
    $action = $this->rulesExpressionManager
      ->createAction('rules_entity_fetch_by_id', ContextConfig::create()
      ->map('type', 'variable_1')
      ->setValue('entity_id', 1));
    $rule
      ->addExpressionObject($action);
    $violation_list = RulesComponent::create($rule)
      ->addContextDefinition('variable_1', ContextDefinition::create('string'))
      ->checkIntegrity();
    $this
      ->assertEquals(1, iterator_count($violation_list));
    $this
      ->assertEquals('The context <em class="placeholder">Entity type</em> may not be configured using a selector.', (string) $violation_list[0]
      ->getMessage());
    $this
      ->assertEquals($action
      ->getUuid(), $violation_list[0]
      ->getUuid());
  }

  /**
   * Tests the data selector restriction on contexts.
   */
  public function testSelectorRestriction() {
    $rule = $this->rulesExpressionManager
      ->createRule();
    $action = $this->rulesExpressionManager
      ->createAction('rules_data_set', ContextConfig::create()
      ->setValue('data', 'some value')
      ->setValue('value', 'some new value'));
    $rule
      ->addExpressionObject($action);
    $violation_list = RulesComponent::create($rule)
      ->checkIntegrity();
    $this
      ->assertEquals(1, iterator_count($violation_list));
    $this
      ->assertEquals('The context <em class="placeholder">Data</em> may only be configured using a selector.', (string) $violation_list[0]
      ->getMessage());
    $this
      ->assertEquals($action
      ->getUuid(), $violation_list[0]
      ->getUuid());
  }

  /**
   * Tests that a primitive context is assigned something that matches.
   */
  public function testPrimitiveTypeViolation() {
    $rule = $this->rulesExpressionManager
      ->createRule();

    // The condition expects a string but we pass a list, which will trigger the
    // violation.
    $condition = $this->rulesExpressionManager
      ->createCondition('rules_test_string_condition', ContextConfig::create()
      ->map('text', 'list_variable'));
    $rule
      ->addExpressionObject($condition);
    $violation_list = RulesComponent::create($rule)
      ->addContextDefinition('list_variable', ContextDefinition::create('list'))
      ->checkIntegrity();
    $this
      ->assertEquals(1, iterator_count($violation_list));
    $this
      ->assertEquals('Expected a string data type for context <em class="placeholder">Text to compare</em> but got a list data type instead.', (string) $violation_list[0]
      ->getMessage());
    $this
      ->assertEquals($condition
      ->getUuid(), $violation_list[0]
      ->getUuid());
  }

  /**
   * Tests that a list context is assigned something that matches.
   */
  public function testListTypeViolation() {
    $rule = $this->rulesExpressionManager
      ->createRule();

    // The condition expects a list for the type context but we pass a node
    // which will trigger the violation.
    $condition = $this->rulesExpressionManager
      ->createCondition('rules_node_is_of_type', ContextConfig::create()
      ->map('node', 'node')
      ->map('types', 'node'));
    $rule
      ->addExpressionObject($condition);
    $violation_list = RulesComponent::create($rule)
      ->addContextDefinition('node', ContextDefinition::create('entity:node'))
      ->checkIntegrity();
    $this
      ->assertEquals(1, iterator_count($violation_list));
    $this
      ->assertEquals('Expected a list data type for context <em class="placeholder">Content types</em> but got a entity:node data type instead.', (string) $violation_list[0]
      ->getMessage());
    $this
      ->assertEquals($condition
      ->getUuid(), $violation_list[0]
      ->getUuid());
  }

  /**
   * Tests that a complex data context is assigned something that matches.
   */
  public function testComplexTypeViolation() {
    $rule = $this->rulesExpressionManager
      ->createRule();

    // The condition expects a node context but gets a list instead which cause
    // the violation.
    $condition = $this->rulesExpressionManager
      ->createCondition('rules_node_is_of_type', ContextConfig::create()
      ->map('node', 'list_variable')
      ->map('types', 'list_variable'));
    $rule
      ->addExpressionObject($condition);
    $violation_list = RulesComponent::create($rule)
      ->addContextDefinition('list_variable', ContextDefinition::create('list'))
      ->checkIntegrity();
    $this
      ->assertEquals(1, iterator_count($violation_list));
    $this
      ->assertEquals('Expected a entity:node data type for context <em class="placeholder">Node</em> but got a list data type instead.', (string) $violation_list[0]
      ->getMessage());
    $this
      ->assertEquals($condition
      ->getUuid(), $violation_list[0]
      ->getUuid());
  }

  /**
   * Tests that an absent required context triggers a violation.
   */
  public function testMissingRequiredContext() {
    $rule = $this->rulesExpressionManager
      ->createRule();

    // The condition is completely un-configured, missing 2 required contexts.
    $condition = $this->rulesExpressionManager
      ->createCondition('rules_node_is_of_type');
    $rule
      ->addExpressionObject($condition);
    $violation_list = RulesComponent::create($rule)
      ->checkIntegrity();
    $this
      ->assertEquals(2, iterator_count($violation_list));
    $this
      ->assertEquals('The required context <em class="placeholder">Node</em> is missing.', (string) $violation_list[0]
      ->getMessage());
    $this
      ->assertEquals('The required context <em class="placeholder">Content types</em> is missing.', (string) $violation_list[1]
      ->getMessage());
    $this
      ->assertEquals($condition
      ->getUuid(), $violation_list[0]
      ->getUuid());
    $this
      ->assertEquals($condition
      ->getUuid(), $violation_list[1]
      ->getUuid());
  }

  /**
   * Make sure that nested expression violations have the correct UUID.
   */
  public function testNestedExpressionUuids() {
    $rule = $this->rulesExpressionManager
      ->createRule();
    $action_set = $this->rulesExpressionManager
      ->createInstance('rules_action_set');

    // The most inner action will trigger a violation for an unknown variable.
    $action = $this->rulesExpressionManager
      ->createAction('rules_entity_save', ContextConfig::create()
      ->map('entity', 'unknown_variable'));
    $action_set
      ->addExpressionObject($action);
    $rule
      ->addExpressionObject($action_set);
    $violation_list = RulesComponent::create($rule)
      ->checkIntegrity();
    $this
      ->assertEquals(1, iterator_count($violation_list));

    // UUID must be that of the most inner action.
    $this
      ->assertEquals($action
      ->getUuid(), $violation_list[0]
      ->getUuid());
  }

  /**
   * Tests using provided variables in sub-sequent actions passes checks.
   */
  public function testUsingProvidedVariables() {
    $rule = $this->rulesExpressionManager
      ->createRule();
    $rule
      ->addAction('rules_variable_add', ContextConfig::create()
      ->setValue('type', 'any')
      ->setValue('value', 'foo'));
    $rule
      ->addAction('rules_variable_add', ContextConfig::create()
      ->setValue('type', 'any')
      ->map('value', 'variable_added'));
    $violation_list = RulesComponent::create($rule)
      ->checkIntegrity();
    $this
      ->assertEquals(0, iterator_count($violation_list));
  }

  /**
   * Tests that refined context is respected when checking context.
   */
  public function testRefinedContextViolation() {
    $rule = $this->rulesExpressionManager
      ->createRule();
    $rule
      ->addAction('rules_variable_add', ContextConfig::create()
      ->setValue('type', 'integer')
      ->map('value', 'text'));
    $violation_list = RulesComponent::create($rule)
      ->addContextDefinition('text', ContextDefinition::create('string'))
      ->checkIntegrity();
    $this
      ->assertEquals(1, iterator_count($violation_list));
  }

  /**
   * Tests context can be refined based upon mapped context.
   */
  public function testRefiningContextBasedonMappedContext() {

    // DataComparision condition refines context based on selected data. Thus
    // it for the test and ensure checking integrity passes when the comparison
    // value is of a compatible type and fails else.
    $rule = $this->rulesExpressionManager
      ->createRule();
    $rule
      ->addCondition('rules_data_comparison', ContextConfig::create()
      ->map('data', 'text')
      ->map('value', 'text2'));
    $violation_list = RulesComponent::create($rule)
      ->addContextDefinition('text', ContextDefinition::create('string'))
      ->addContextDefinition('text2', ContextDefinition::create('string'))
      ->checkIntegrity();
    $this
      ->assertEquals(0, iterator_count($violation_list));
    $violation_list = RulesComponent::create($rule)
      ->addContextDefinition('text', ContextDefinition::create('string'))
      ->addContextDefinition('text2', ContextDefinition::create('integer'))
      ->checkIntegrity();
    $this
      ->assertEquals(1, iterator_count($violation_list));
  }

  /**
   * Tests using provided variables with refined context.
   */
  public function testUsingRefinedProvidedVariables() {
    $rule = $this->rulesExpressionManager
      ->createRule();
    $rule
      ->addAction('rules_variable_add', ContextConfig::create()
      ->setValue('type', 'string')
      ->setValue('value', 'foo'));
    $rule
      ->addAction('rules_system_message', ContextConfig::create()
      ->map('message', 'variable_added')
      ->setValue('type', MessengerInterface::TYPE_STATUS));

    // The message action requires a string, thus if the context is not refined
    // it will end up as "any" and integrity check would fail.
    $violation_list = RulesComponent::create($rule)
      ->checkIntegrity();
    $this
      ->assertEquals(0, iterator_count($violation_list));
  }

}

Members

Namesort descending Modifiers Type Description Overrides
IntegrityCheckTest::testCheckUuid public function Tests that the integrity check with UUID works.
IntegrityCheckTest::testComplexTypeViolation public function Tests that a complex data context is assigned something that matches.
IntegrityCheckTest::testInputRestriction public function Tests the input restriction on contexts.
IntegrityCheckTest::testIntegrityCheck public function Tests that the integrity check can be invoked.
IntegrityCheckTest::testInvalidAction public function Tests that an invalid action plugin ID results in a violation.
IntegrityCheckTest::testInvalidCondition public function Tests that an invalid condition plugin ID results in a violation.
IntegrityCheckTest::testInvalidProvidedName public function Tests invalid characters in provided variables.
IntegrityCheckTest::testListTypeViolation public function Tests that a list context is assigned something that matches.
IntegrityCheckTest::testMissingAction public function Tests that a missing action plugin ID results in a violation.
IntegrityCheckTest::testMissingCondition public function Tests that a missing condition plugin ID results in a violation.
IntegrityCheckTest::testMissingRequiredContext public function Tests that an absent required context triggers a violation.
IntegrityCheckTest::testNestedExpressionUuids public function Make sure that nested expression violations have the correct UUID.
IntegrityCheckTest::testPrimitiveTypeViolation public function Tests that a primitive context is assigned something that matches.
IntegrityCheckTest::testRefinedContextViolation public function Tests that refined context is respected when checking context.
IntegrityCheckTest::testRefiningContextBasedonMappedContext public function Tests context can be refined based upon mapped context.
IntegrityCheckTest::testSelectorRestriction public function Tests the data selector restriction on contexts.
IntegrityCheckTest::testUnknownVariable public function Tests that a wrongly configured variable name triggers a violation.
IntegrityCheckTest::testUsingProvidedVariables public function Tests using provided variables in sub-sequent actions passes checks.
IntegrityCheckTest::testUsingRefinedProvidedVariables public function Tests using provided variables with refined context.
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.
RulesEntityIntegrationTestBase::$entityAccess protected property The mocked entity access handler.
RulesEntityIntegrationTestBase::$fieldTypeManager protected property The field type manager.
RulesEntityIntegrationTestBase::$languageManager protected property The language manager mock.
RulesEntityIntegrationTestBase::getContextDefinitionFor protected function Helper to mock a context definition with a mocked data definition.
RulesEntityIntegrationTestBase::setUp protected function Overrides RulesIntegrationTestBase::setUp 33
RulesIntegrationTestBase::$actionManager protected property
RulesIntegrationTestBase::$cacheBackend protected property
RulesIntegrationTestBase::$classResolver protected property The class resolver mock for the typed data manager.
RulesIntegrationTestBase::$conditionManager protected property
RulesIntegrationTestBase::$container protected property The Drupal service container.
RulesIntegrationTestBase::$dataFetcher protected property The data fetcher service.
RulesIntegrationTestBase::$dataFilterManager protected property The data filter manager.
RulesIntegrationTestBase::$enabledModules protected property Array object keyed with module names and TRUE as value.
RulesIntegrationTestBase::$entityFieldManager protected property
RulesIntegrationTestBase::$entityTypeBundleInfo protected property
RulesIntegrationTestBase::$entityTypeManager protected property
RulesIntegrationTestBase::$logger protected property A mocked Rules logger.channel.rules_debug service. 6
RulesIntegrationTestBase::$messenger protected property The messenger service.
RulesIntegrationTestBase::$moduleHandler protected property
RulesIntegrationTestBase::$namespaces protected property All setup'ed namespaces.
RulesIntegrationTestBase::$placeholderResolver protected property The placeholder resolver service.
RulesIntegrationTestBase::$rulesDataProcessorManager protected property
RulesIntegrationTestBase::$rulesExpressionManager protected property
RulesIntegrationTestBase::$typedDataManager protected property
RulesIntegrationTestBase::constructModulePath protected function Determines the path to a module's class files.
RulesIntegrationTestBase::enableModule protected function Fakes the enabling of a module and adds its namespace for plugin loading.
RulesIntegrationTestBase::getTypedData protected function Returns a typed data object.
RulesIntegrationTestBase::prophesizeEntity protected function Helper method to mock irrelevant cache methods on entities.
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.