xero_sync-8.x-1.x-dev/tests/src/Unit/QueueJobTest.php

tests/src/Unit/QueueJobTest.php
<?php

namespace Drupal\Tests\xero_sync\Unit;

use Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException;
use Drupal\Component\Plugin\Exception\PluginNotFoundException;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityStorageInterface;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Entity\EntityTypeBundleInfoInterface;
use Drupal\Core\Entity\Query\QueryInterface;
use Drupal\Tests\UnitTestCase;
use Drupal\xero\TypedData\XeroComplexItemInterface;
use Drupal\xero_sync\XeroSyncEntityHandlerInterface;
use Drupal\xero_sync\XeroSyncSynchronizer;
use Drupal\xero_sync\XeroSyncQueueJobTrait;
use Psr\Log\LoggerInterface;
use Drupal\xero_sync\Exception\SyncFailureException;
use Symfony\Component\Serializer\SerializerInterface;

/**
 * @coversDefaultClass \Drupal\xero_sync\XeroSyncEntityHandler
 * @group xero_sync
 */
class QueueJobTest extends UnitTestCase {

  use XeroSyncQueueJobTrait;

  /**
   * The Xero Sync Synchronizer.
   *
   * @var \Drupal\xero_sync\XeroSyncSynchronizer
   */
  protected $synchronizer;

  /**
   * The logger.
   *
   * @var \Psr\Log\LoggerInterface
   */
  protected $logger;

  /**
   * The entity type manager.
   *
   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
   */
  protected $entityTypeManager;

  /**
   * The entity type manager.
   *
   * @var \Drupal\Core\Entity\EntityTypeBundleInfoInterface
   */
  protected $entityTypeBundleInfo;

  /**
   * The serializer.
   *
   * @var \Symfony\Component\Serializer\SerializerInterface
   */
  protected $serializer;

  /**
   * The entity type object.
   *
   * @var \Drupal\Core\Entity\EntityTypeInterface
   */
  protected $entityType;

  /**
   * The entity storage.
   *
   * @var \Drupal\Core\Entity\EntityStorageInterface
   */
  protected $storage;

  /**
   * The id of the queue being tested.
   *
   * @var string
   */
  protected $queueId;

  /**
   * A Xero item.
   *
   * @var \Drupal\xero\TypedData\XeroComplexItemInterface
   */
  protected $item;

  /**
   * An entity.
   *
   * @var \Drupal\Core\Entity\EntityInterface
   */
  protected $entity;

  /**
   * {@inheritdoc}
   */
  public function setUp(): void {
    parent::setUp();
    $this->synchronizer = $this->createMock(XeroSyncSynchronizer::class);
    $this->logger = $this->createMock(LoggerInterface::class);
    $this->item = $this->createMock(XeroComplexItemInterface::class);
    $this->entity = $this->createMock(EntityInterface::class);
    $this->storage = $this->createMock(EntityStorageInterface::class);
    $this->entityTypeManager = $this->createMock(EntityTypeManagerInterface::class);
    $this->entityTypeBundleInfo = $this->createMock(EntityTypeBundleInfoInterface::class);
    $this->serializer = $this->createMock(SerializerInterface::class);
    $this->entityType = $this->createMock(EntityTypeInterface::class);
    $this->entityHandler = $this->createMock(XeroSyncEntityHandlerInterface::class);
  }

  /**
   * Test the doProcessItem method from XeroSyncQueueJobTrait.
   *
   * @param string $queueId
   *   The id of the queue being tested.
   * @param string $synchronizerCall
   *   The synchronizer method that is expected to be called.
   * @param array $data
   *   The test data to provide to doProcessItem.
   * @param string|false $exception
   *   The exception to expect to be thrown, or FALSE if none expected.
   * @param bool $hasItem
   *   Whether the synchronizer call should expect an item to be passed.
   * @param array $flagsPassedOn
   *   The create & update flags expected to be passed to the synchronizer call.
   *
   * @dataProvider doProcessItemProvider
   */
  public function testDoProcessItem($queueId, $synchronizerCall, array $data, $exception, $hasItem, array $flagsPassedOn) {
    $this->queueId = $queueId;

    // @todo When #2570593 lands, expand test to test for (a) no bundle in data,
    // (b) invalid bundle, (c) no bundle class, (d) bundle class.
    $this->entityTypeBundleInfo->expects($this->any())
      ->method('getBundleInfo')
      ->with('valid')
      ->willReturn(NULL);

    if (isset($data['entity_type'])) {

      if ($data['entity_type'] !== 'valid') {
        if (isset($data['entity'])) {
          $this->entityTypeManager->expects($this->once())
            ->method('getDefinition', TRUE)
            ->with('invalid')
            ->willThrowException(new PluginNotFoundException('invalid'));
        }
        else {
          $this->entityTypeManager->expects($this->once())
            ->method('getStorage')
            ->with('invalid')
            ->willThrowException(new InvalidPluginDefinitionException('invalid'));
        }
      }
      else {
        // Has set and valid entity type.
        $this->entity->expects($this->any())
          ->method('getEntityTypeId')
          ->willReturn('valid');
        $entityType = $this->createMock(EntityTypeInterface::class);
        $this->entity->expects($this->any())
          ->method('getEntityType')
          ->willReturn($entityType);

        // Setup doProcessXeroSyncUnsync.
        $query = $this->createMock(QueryInterface::class);
        $query->expects($this->any())
          ->method('accessCheck')
          ->willReturn($query);
        $query->expects($this->any())
          ->method('condition');
        $query->expects($this->any())
          ->method('execute')
          ->willReturn([]);
        $this->storage->expects($this->any())
          ->method('getQuery')
          ->willReturn($query);
        $this->entityHandler->expects($this->any())
          ->method('getFieldName')
          ->willReturn('xero_sync');

        $this->entityTypeManager->expects($this->any())
          ->method('getStorage')
          ->with('valid')
          ->willReturn($this->storage);

        if (isset($data['entity'])) {
          $this->entityType->expects($this->once())
            ->method('getClass')
            ->willReturn('fqcn');
          $this->entityTypeManager->expects($this->once())
            ->method('getDefinition')
            ->with('valid')
            ->willReturn($this->entityType);
          $this->serializer->expects($this->once())
            ->method('deserialize')
            ->with($data['entity'], 'fqcn', 'json')
            ->willReturn($this->entity);
        }

        else {
          // Entity needs loading, not serialized.
          if (isset($data['entity_id'])) {
            if ($data['entity_id'] === 'valid') {
              $this->storage->expects($this->once())
                ->method('load')
                ->with('valid')
                ->willReturn($this->entity);
            }
            else {
              $this->storage->expects($this->once())
                ->method('load')
                ->with('invalid')
                ->willReturn(NULL);
            }
          }

        }
      }
    }

    $item = NULL;
    if ($hasItem) {
      $item = $this->item;
    }

    if ($exception) {
      $this->expectException($exception);
    }

    if ($exception === \InvalidArgumentException::class) {
      $this->synchronizer->expects($this->never())
        ->method($synchronizerCall);
    }
    else {
      if ($synchronizerCall === 'syncEntityWithItem') {
        if ($exception) {
          $this->synchronizer->expects($this->once())
            ->method($synchronizerCall)
            ->with($this->entity, $item, $flagsPassedOn['create'], $flagsPassedOn['update'], NULL)
            ->willThrowException(new $exception());
        }
        else {
          $this->synchronizer->expects($this->once())
            ->method($synchronizerCall)
            ->with($this->entity, $item, $flagsPassedOn['create'], $flagsPassedOn['update'], NULL);
        }
      }
      else {
        if ($exception) {
          $this->synchronizer->expects($this->once())
            ->method($synchronizerCall)
            ->with($this->entity, $item)
            ->willThrowException(new $exception());
        }
        else {
          $this->synchronizer->expects($this->once())
            ->method($synchronizerCall)
            ->with($this->entity, $item);
        }
      }
    }

    $this->doProcessItem($data);

  }

  /**
   * Data provider for testDoProcessItem.
   */
  public function doProcessItemProvider() {
    $queues = [
      [
        'id' => 'xero_sync_sync',
        'synchronizer_call' => 'syncEntityWithItem',
      ],
      [
        'id' => 'xero_sync_unsync',
        'synchronizer_call' => 'unsyncEntityWithItem',
      ],
    ];

    $entity_args = [
      [
        'data' => [
          'entity_type' => 'valid',
          'entity_id' => 'valid',
        ],
        'exception' => FALSE,
      ],
      [
        'data' => [
          'entity_type' => 'invalid',
          'entity_id' => 'valid',
        ],
        'exception' => \InvalidArgumentException::class,
      ],
      [
        'data' => [
          'entity_type' => 'valid',
          'entity_id' => 'invalid',
        ],
        'exception' => \InvalidArgumentException::class,
      ],
      [
        'data' => [
          'entity_type' => 'invalid',
          'entity_id' => 'invalid',
        ],
        'exception' => \InvalidArgumentException::class,
      ],
      [
        'data' => [
          'entity_id' => 'invalid',
        ],
        'exception' => \InvalidArgumentException::class,
      ],
      [
        'data' => [
          'entity_type' => 'valid',
        ],
        'exception' => \InvalidArgumentException::class,
      ],
      [
        'data' => [],
        'exception' => \InvalidArgumentException::class,
      ],
      [
        'data' => [
          'entity_type' => 'valid',
          'entity_id' => 'valid',
          'entity' => ['serialized entity'],
        ],
        'exception' => FALSE,
      ],
      [
        'data' => [
          'entity_type' => 'valid',
          'entity_id' => 'valid',
          'entity_bundle' => 'valid',
          'entity' => ['serialized entity'],
        ],
        'exception' => FALSE,
      ],
      [
        'data' => [
          'entity_type' => 'valid',
          'entity' => ['serialized entity'],
        ],
        'exception' => FALSE,
      ],
      [
        'data' => [
          'entity_type' => 'invalid',
          'entity' => ['serialized entity'],
        ],
        'exception' => \InvalidArgumentException::class,
      ],
      [
        'data' => [
          'entity' => ['serialized entity'],
        ],
        'exception' => \InvalidArgumentException::class,
      ],
    ];

    $item_args = [
      [
        'data' => [
          'item_type' => 'some item',
          'item_guid' => 'some guid',
        ],
        'has_item' => TRUE,
      ],
      [
        'data' => [
          'item_type' => 'some item',
        ],
        'has_item' => FALSE,
      ],
      [
        'data' => [
          'item_type' => 'some item',
        ],
        'has_item' => FALSE,
      ],
      [
        'data' => [],
        'has_item' => FALSE,
      ],
    ];

    // 'data' is what is set in the job data array for a create/update flag.
    // 'flag_passed_on' is whether the flag is passed to the synchronizer.
    $flag_versions =
      [
        [
          'data' => TRUE,
          'flag_passed_on' => TRUE,
        ],
        [
          'data' => FALSE,
          'flag_passed_on' => FALSE,
        ],
        [
          'data' => NULL,
          'flag_passed_on' => TRUE,
        ],
        [
          'data' => 'missing',
          'flag_passed_on' => TRUE,
        ],
      ];

    $flag_args = [];
    foreach ($flag_versions as $create_version) {
      foreach ($flag_versions as $update_version) {
        $flags_supplied = [];
        if ($create_version['data'] !== 'missing') {
          $flags_supplied['create'] = $create_version['data'];
        }
        if ($update_version['data'] !== 'missing') {
          $flags_supplied['update'] = $update_version['data'];
        }
        $flags_passed_on = [
          'create' => $create_version['flag_passed_on'],
          'update' => $update_version['flag_passed_on'],
        ];
        $flag_args[] = [
          'data' => $flags_supplied,
          'flags_passed_on' => $flags_passed_on,
        ];
      }
    }

    $synchronizer_exceptions = [
      SyncFailureException::class,
      FALSE,
    ];

    $tests = [];
    foreach ($queues as $queue) {
      foreach ($entity_args as $entity_arg) {
        foreach ($item_args as $item_arg) {
          foreach ($flag_args as $flag_arg) {
            foreach ($synchronizer_exceptions as $synchronizer_exception) {
              $data = [] + $entity_arg['data'] + $item_arg['data'] + $flag_arg['data'];
              $exception = $entity_arg['exception'] ? $entity_arg['exception'] : $synchronizer_exception;
              $tests[] = [
                'queue_id' => $queue['id'],
                'synchronizer_call' => $queue['synchronizer_call'],
                'data' => $data,
                'exception' => $exception,
                'has_item' => $item_arg['has_item'],
                'flags_passed_on' => $flag_arg['flags_passed_on'],
              ];
            }
          }
        }
      }
    }
    return $tests;

  }

  /**
   * {@inheritDoc}
   */
  protected function buildXeroItemWithId($itemType, $itemId) {
    // Override buildXeroItemWithId from XeroSyncUtilitiesTrait, so
    // that we don't need to mock the Typed Data Manager.
    return $this->item;
  }

  /**
   * Identify which queue we are simulating being within.
   *
   * @return string
   *   The queue plugin id.
   */
  protected function getPluginId() {
    return $this->queueId;
  }

}

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc