class IntegrityCheckTest

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 18

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->assertCount(0, $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->assertCount(1, $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->assertCount(2, $all_violations);
        $uuid_violations = $all_violations->getFor($second_action->getUuid());
        $this->assertCount(1, $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->assertCount(1, $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->assertCount(1, $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->assertCount(1, $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->assertCount(1, $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->assertCount(1, $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->assertCount(1, $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->assertCount(1, $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->assertCount(1, $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->assertCount(1, $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->assertCount(1, $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->assertCount(2, $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->assertCount(1, $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->assertCount(0, $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->assertCount(1, $violation_list);
    }
    
    /**
     * Tests context can be refined based upon mapped context.
     */
    public function testRefiningContextBasedOnMappedContext() {
        // DataComparison 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->assertCount(0, $violation_list);
        $violation_list = RulesComponent::create($rule)->addContextDefinition('text', ContextDefinition::create('string'))
            ->addContextDefinition('text2', ContextDefinition::create('integer'))
            ->checkIntegrity();
        $this->assertCount(1, $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->assertCount(0, $violation_list);
    }

}

Members

Title Sort descending Deprecated Modifiers Object type Summary Overriden Title 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.
PhpUnitWarnings::$deprecationWarnings private static property Deprecation warnings from PHPUnit to raise with @trigger_error().
PhpUnitWarnings::addWarning public function Converts PHPUnit deprecation warnings to E_USER_DEPRECATED.
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::$fieldTypeCategoryManager protected property The field type category info plugin manager.
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&#039;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&#039;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 Deprecated protected function Asserts if two arrays are equal by sorting them first.
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.
UnitTestCase::setUpBeforeClass public static function