eca-1.0.x-dev/modules/queue/tests/src/Kernel/EnqueueTaskDelayedTest.php
modules/queue/tests/src/Kernel/EnqueueTaskDelayedTest.php
<?php
namespace Drupal\Tests\eca_queue\Kernel;
use Drupal\KernelTests\KernelTestBase;
use Drupal\eca\Entity\Eca;
use Drupal\eca_queue\Plugin\Action\EnqueueTaskDelayed;
use Drupal\eca_queue\Task;
use Drupal\user\Entity\User;
use Drupal\user\UserInterface;
use PHPUnit\Framework\Attributes\Group;
/**
* Kernel tests for the "eca_enqueue_task_delayed" action plugin.
*/
#[Group('eca')]
#[Group('eca_queue')]
class EnqueueTaskDelayedTest extends KernelTestBase {
/**
* {@inheritdoc}
*/
protected static $modules = [
'system',
'user',
'field',
'eca',
'eca_queue',
];
/**
* {@inheritdoc}
*
* @throws \Drupal\Core\Entity\EntityStorageException
*/
public function setUp(): void {
parent::setUp();
$this->installEntitySchema('user');
$this->installConfig(static::$modules);
User::create(['uid' => 0, 'name' => 'anonymous'])->save();
User::create(['uid' => 1, 'name' => 'admin'])->save();
}
/**
* Tests EnqueueTaskDelayed.
*
* @throws \Drupal\Component\Plugin\Exception\PluginException
* @throws \Drupal\Core\Entity\EntityStorageException
* @throws \Exception
*/
public function testEnqueueTaskDelayed(): void {
/** @var \Drupal\Core\Action\ActionManager $action_manager */
$action_manager = \Drupal::service('plugin.manager.action');
/** @var \Drupal\eca\Token\TokenInterface $token_services */
$token_services = \Drupal::service('eca.token_services');
$queue = \Drupal::queue('eca_task', TRUE);
$token_services->addTokenData('entity', User::load(0));
$token_services->addTokenData('admin', User::load(1));
// Create an action for enqueuing a task.
$defaults = [
'task_name' => 'delayed_task',
'task_value' => '',
'tokens' => '',
'delay_value' => '2',
'delay_unit' => EnqueueTaskDelayed::DELAY_MINUTES,
];
/** @var \Drupal\eca_queue\Plugin\Action\EnqueueTask $action */
$action = $action_manager->createInstance('eca_enqueue_task_delayed', [] + $defaults);
$this->assertTrue($action->access(NULL, User::load(0)), 'Access must be granted.');
$this->assertTrue($action->access(NULL, User::load(1)), 'Access must be granted.');
$this->assertSame(0, $queue->numberOfItems(), 'Queue must be empty before execution.');
$action->execute();
$this->assertSame(1, $queue->numberOfItems(), 'Queue must have exactly one item after execution.');
$queue->deleteItem($queue->claimItem());
// Repeat the same thing.
$action = $action_manager->createInstance('eca_enqueue_task_delayed', [] + $defaults);
$this->assertTrue($action->access(NULL, User::load(0)), 'Access must be granted.');
$this->assertTrue($action->access(NULL, User::load(1)), 'Access must be granted.');
$this->assertSame(0, $queue->numberOfItems(), 'Queue must be empty before execution.');
$action->execute();
$this->assertSame(1, $queue->numberOfItems(), 'Queue must have exactly one item after execution.');
// One more time, without clearing beforehand.
$action = $action_manager->createInstance('eca_enqueue_task_delayed', [] + $defaults);
$this->assertSame(1, $queue->numberOfItems(), 'Queue must be unchanged before execution.');
$action->execute();
$this->assertSame(2, $queue->numberOfItems(), 'Queue must have exactly two items after execution.');
$queue->deleteItem($queue->claimItem());
$queue->deleteItem($queue->claimItem());
// Now create a task, that is to be processed via ECA. The delay of that
// task it to be set 0 (immediately due). That ECA config will just create
// another queue item and we assert that this item is then stored in queue.
$action = $action_manager->createInstance('eca_enqueue_task_delayed', [
'delay_value' => '0',
'delay_unit' => EnqueueTaskDelayed::DELAY_SECONDS,
] + $defaults);
$this->assertSame(0, $queue->numberOfItems(), 'Queue must be empty before execution.');
$action->execute();
$this->assertSame(1, $queue->numberOfItems(), 'Queue must have exactly one item after execution.');
$eca_config_values = [
'langcode' => 'en',
'status' => TRUE,
'id' => 'queue_process_delayed',
'label' => 'ECA queue worker',
'modeller' => 'fallback',
'version' => '1.0.0',
'events' => [
'event_queue' => [
'plugin' => 'eca_queue:processing_task',
'label' => 'ECA processing task',
'configuration' => [
'task_name' => 'delayed_task',
'task_value' => '',
],
'successors' => [
['id' => 'action_enqueue', 'condition' => ''],
],
],
],
'conditions' => [],
'gateways' => [],
'actions' => [
'action_enqueue' => [
'plugin' => 'eca_enqueue_task_delayed',
'label' => 'Enqueue another item',
'configuration' => [
'task_name' => 'another_task',
'task_value' => 'delayed_task_value',
'tokens' => '',
'delay_value' => '100',
'delay_unit' => EnqueueTaskDelayed::DELAY_SECONDS,
],
'successors' => [],
],
],
];
$ecaConfig = Eca::create($eca_config_values);
$ecaConfig->trustData()->save();
/** @var \Drupal\Core\Queue\QueueWorkerManagerInterface $queue_worker_manager */
$queue_worker_manager = \Drupal::service('plugin.manager.queue_worker');
/** @var \Drupal\eca_queue\Plugin\QueueWorker\TaskWorker $queue_worker */
$queue_worker = $queue_worker_manager->createInstance('eca_task');
$item = $queue->claimItem();
/** @var \Drupal\eca_queue\Task $task */
$task = $item->data;
$this->assertInstanceOf(Task::class, $task, 'Task item must be a task object.');
$this->assertTrue($task->isDueForProcessing(), 'Task must be due for processing, because delay is set to 0.');
$queue_worker->processItem($item->data);
$queue->deleteItem($item);
$this->assertSame(1, $queue->numberOfItems(), 'Queue must have exactly one item (newly created by ECA configuration).');
$item = $queue->claimItem();
/** @var \Drupal\eca_queue\Task $task */
$task = $item->data;
$this->assertInstanceOf(Task::class, $task, 'Newly created queue item must be a Task object.');
$this->assertEquals('another_task', $task->getTaskName(), 'Task name must match with the one added via ECA configuration.');
$this->assertEquals('delayed_task_value', $task->getTaskValue(), 'Task value must match with the one added via ECA configuration.');
$this->assertFalse($task->hasData('entity'), 'No entity data must have been passed to the task.');
$this->assertFalse($task->hasData('admin'), 'No user data must have been passed to the task.');
// When the queue worker works on the newly created item, the ECA config
// will react upon that again. But it must not execute its action on that
// event, because it has a different event name. That's why the number of
// queue items must remain the same.
$exception = NULL;
try {
$queue_worker->processItem($task);
}
catch (\Exception $e) {
$exception = $e;
}
finally {
$this->assertTrue(isset($exception));
$this->assertEquals('Task is not yet due for processing.', $exception->getMessage());
}
$this->assertSame(1, $queue->numberOfItems(), 'Queue must be unchanged.');
// Now create another ECA config, that one will react upon the name of
// the newly created task item, but it is not yet due for processing and
// therefore the queue must remain unchanged.
$eca_config_values['id'] .= '_2';
$eca_config_values['events']['event_queue']['configuration']['task_name'] = 'another_task';
Eca::create($eca_config_values)->trustData()->save();
$this->assertSame(1, $queue->numberOfItems(), 'Queue must be unchanged.');
$exception = NULL;
try {
$queue_worker->processItem($task);
}
catch (\Exception $e) {
$exception = $e;
}
finally {
$this->assertTrue(isset($exception));
$this->assertEquals('Task is not yet due for processing.', $exception->getMessage());
}
$this->assertSame(1, $queue->numberOfItems(), 'Queue must be unchanged.');
$queue->deleteItem($item);
while ($item = $queue->claimItem()) {
$queue->deleteItem($item);
}
$this->assertSame(0, $queue->numberOfItems(), 'Queue must be empty.');
/** @var \Drupal\eca_queue\Plugin\Action\EnqueueTask $action */
$action = $action_manager->createInstance('eca_enqueue_task_delayed', [
'task_name' => 'user_task',
'task_value' => '[entity:account-name]',
'tokens' => "entity",
'delay_value' => '100',
'delay_unit' => EnqueueTaskDelayed::DELAY_SECONDS,
] + $defaults);
$action->execute();
$item = $queue->claimItem();
/** @var \Drupal\eca_queue\Task $task */
$task = $item->data;
$this->assertInstanceOf(Task::class, $task, 'Newly created queue item must be a Task object.');
$this->assertEquals('user_task', $task->getTaskName(), 'Task name must match with the one defined via plugin configuration.');
$this->assertEquals('anonymous', $task->getTaskValue(), 'Task value must match with the one defined via plugin configuration.');
$this->assertTrue($task->hasData('entity'), 'Entity data must have been passed to the task.');
$this->assertInstanceOf(UserInterface::class, $task->getData('entity'), 'The passed entity Token must be a user.');
$this->assertSame('0', (string) $task->getData('entity')->id(), 'The loaded entity be the anonymous user.');
$this->assertFalse($task->hasData('admin'), 'No admin user data must have been passed to the task.');
$this->assertFalse($task->isDueForProcessing(), 'Task must not be due for processing.');
$queue->deleteItem($item);
/** @var \Drupal\eca_queue\Plugin\Action\EnqueueTask $action */
$action = $action_manager->createInstance('eca_enqueue_task_delayed', [
'task_name' => 'user_task',
'task_value' => '[admin:uid]',
'tokens' => "entity,\nadmin",
'delay_value' => '0',
'delay_unit' => EnqueueTaskDelayed::DELAY_SECONDS,
] + $defaults);
$action->execute();
$item = $queue->claimItem();
/** @var \Drupal\eca_queue\Task $task */
$task = $item->data;
$this->assertInstanceOf(Task::class, $task, 'Newly created queue item must be a Task object.');
$this->assertEquals('user_task', $task->getTaskName(), 'Task name must match with the one defined via plugin configuration.');
$this->assertEquals('1', $task->getTaskValue(), 'Task value must match with the one defined via plugin configuration.');
$this->assertTrue($task->hasData('entity'), 'Entity data must have been passed to the task.');
$this->assertInstanceOf(UserInterface::class, $task->getData('entity'), 'The passed entity Token must be a user.');
$this->assertSame('0', (string) $task->getData('entity')->id(), 'The loaded entity must be the anonymous user ID.');
$this->assertTrue($task->hasData('admin'), 'Admin user data must have been passed to the task.');
$this->assertSame('1', (string) $task->getData('admin')->id(), 'The loaded admin user must be the admin user account, as it was defined in the Token environment.');
$this->assertTrue($task->isDueForProcessing(), 'Task must be due for processing.');
$queue->deleteItem($item);
}
}
