RulesEngineTest.php

Namespace

Drupal\Tests\rules\Kernel

File

tests/src/Kernel/RulesEngineTest.php

View source
<?php

namespace Drupal\Tests\rules\Kernel;

use Drupal\rules\Core\ConditionManager;
use Drupal\rules\Context\ContextConfig;
use Drupal\rules\Context\ContextDefinition;
use Drupal\rules\Context\ExecutionState;
use Drupal\rules\Engine\RulesComponent;
// cspell:ignore valuetest

/**
 * Test using the Rules API to create and evaluate rules.
 *
 * @group Rules
 */
class RulesEngineTest extends RulesKernelTestBase {
    
    /**
     * {@inheritdoc}
     */
    protected function setUp() : void {
        parent::setUp();
        $this->installEntitySchema('user');
        // The global CurrentUserContext doesn't work properly without a
        // fully-installed user module.
        // @see https://www.drupal.org/project/rules/issues/2989417
        $this->container
            ->get('module_handler')
            ->loadInclude('user', 'install');
        user_install();
    }
    
    /**
     * Tests creating a rule and iterating over the rule elements.
     */
    public function testRuleCreation() {
        // Create an 'and' condition container and add conditions to it.
        $and = $this->expressionManager
            ->createAnd()
            ->addCondition('rules_test_false')
            ->addCondition('rules_test_true', ContextConfig::create()->negateResult())
            ->negate();
        // Test that the 'and' condition container evaluates to TRUE.
        $this->assertTrue($and->execute());
        // Create an 'or' condition container and add conditions to it, including
        // the previously created 'and' condition container.
        $or = $this->expressionManager
            ->createOr()
            ->addCondition('rules_test_true', ContextConfig::create()->negateResult())
            ->addCondition('rules_test_false')
            ->addExpressionObject($and);
        // Test that the 'or' condition container evaluates to TRUE.
        $this->assertTrue($or->execute());
        // Create a rule and add conditions to it, including the previously created
        // 'or' condition container.
        $rule = $this->expressionManager
            ->createRule();
        $rule->addCondition('rules_test_true')
            ->addCondition('rules_test_true')
            ->addExpressionObject($or);
        // Test that the rule's condition container evaluates to TRUE.
        $this->assertTrue($rule->getConditions()
            ->execute());
        // Add an action to it and execute the rule.
        $rule->addAction('rules_test_debug_log');
        $rule->execute();
        // Test that the action logged something.
        $this->assertRulesDebugLogEntryExists('action called');
    }
    
    /**
     * Tests passing a string context to a condition.
     */
    public function testContextPassing() {
        $rule = $this->expressionManager
            ->createRule();
        $rule->addCondition('rules_test_string_condition', ContextConfig::create()->map('text', 'test'));
        $rule->addAction('rules_test_debug_log');
        RulesComponent::create($rule)->addContextDefinition('test', ContextDefinition::create('string'))
            ->setContextValue('test', 'test value')
            ->execute();
        // Test that the action logged something.
        $this->assertRulesDebugLogEntryExists('action called');
    }
    
    /**
     * Tests that a condition can provide a value and another one can consume it.
     */
    public function testProvidedVariables() {
        $rule = $this->expressionManager
            ->createRule();
        // The first condition provides a "provided_text" variable.
        $rule->addCondition('rules_test_provider');
        // The second condition consumes the variable.
        $rule->addCondition('rules_test_string_condition', ContextConfig::create()->map('text', 'provided_text'));
        $rule->addAction('rules_test_debug_log');
        $component = RulesComponent::create($rule);
        $violations = $component->checkIntegrity();
        $this->assertCount(0, $violations);
        $component->execute();
        // Test that the action logged something.
        $this->assertRulesDebugLogEntryExists('action called');
    }
    
    /**
     * Tests that provided variables can be renamed with configuration.
     */
    public function testRenamingOfProvidedVariables() {
        $rule = $this->expressionManager
            ->createRule();
        // The condition provides a "provided_text" variable.
        $rule->addCondition('rules_test_provider', ContextConfig::create()->provideAs('provided_text', 'newname'));
        $state = ExecutionState::create();
        $rule->executeWithState($state);
        // Check that the newly named variable exists and has the provided value.
        $variable = $state->getVariable('newname');
        $this->assertEquals($variable->getValue(), 'test value');
    }
    
    /**
     * Tests that multiple actions can consume and provide context variables.
     */
    public function testActionProvidedContext() {
        // @todo Convert the test to make use of actions instead of conditions.
        $rule = $this->expressionManager
            ->createRule();
        // The condition provides a "provided_text" variable.
        $rule->addCondition('rules_test_provider');
        // The action provides a "concatenated" variable.
        $rule->addAction('rules_test_string', ContextConfig::create()->map('text', 'provided_text'));
        // Add the same action again which will provide a "concatenated2" variable
        // now.
        $rule->addAction('rules_test_string', ContextConfig::create()->map('text', 'concatenated')
            ->provideAs('concatenated', 'concatenated2'));
        $state = ExecutionState::create();
        $rule->executeWithState($state);
        // Check that the created variables exists and have the provided values.
        $concatenated = $state->getVariable('concatenated');
        $this->assertEquals($concatenated->getValue(), 'test valuetest value');
        $concatenated2 = $state->getVariable('concatenated2');
        $this->assertEquals($concatenated2->getValue(), 'test valuetest valuetest valuetest value');
    }
    
    /**
     * Verifies swapping out core services works.
     */
    public function testSwappedCoreServices() {
        $condition_manager = $this->container
            ->get('plugin.manager.condition');
        $this->assertInstanceOf(ConditionManager::class, $condition_manager);
    }

}

Classes

Title Deprecated Summary
RulesEngineTest Test using the Rules API to create and evaluate rules.