commerce_xero-8.x-1.x-dev/tests/src/Unit/CommerceXeroDataTestTrait.php

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

namespace Drupal\Tests\commerce_xero\Unit;

use Drupal\Component\Plugin\Discovery\AttributeClassDiscovery;
use Drupal\Component\FileCache\FileCacheFactory;
use Drupal\Core\TypedData\Attribute\DataType;
use Drupal\Core\TypedData\ComplexDataDefinitionInterface;
use Drupal\Core\TypedData\DataDefinition;
use Drupal\Core\TypedData\DataDefinitionInterface;
use Drupal\Core\TypedData\ListDataDefinition;
use Drupal\Core\TypedData\Plugin\DataType\Any;
use Drupal\xero\TypedData\Definition\AccountDefinition;
use Drupal\xero\TypedData\Definition\AddressDefinition;
use Drupal\xero\TypedData\Definition\BankTransactionDefinition;
use Drupal\xero\TypedData\Definition\ContactDefinition;
use Drupal\xero\TypedData\Definition\InvoiceDefinition;
use Drupal\xero\TypedData\Definition\LineItemDefinition;
use Drupal\xero\TypedData\Definition\PaymentDefinition;
use Drupal\xero\TypedData\Definition\PhoneDefinition;
use Drupal\xero\TypedData\Definition\TrackingCategoryDefinition;
use Drupal\xero\TypedData\Definition\TrackingCategoryOptionDefinition;
use Drupal\xero\TypedData\Definition\TrackingOptionDefinition;
use Drupal\xero\TypedData\Definition\XeroDefinitionInterface;
use Prophecy\Argument;

/**
 * Provides Typed Data Manager mocking capabilities for Xero API.
 *
 * @deprecated in commerce_xero:8.x-1.0 and is removed from commerce_xero:2.0.0.
 *             Use XeroDataTestTrait instead once that version is fixed. There
 *             are still issues in the test trait in xero:3.1.x that need to be
 *             resolved.
 * @see https://www.drupal.org/project/xero/issues/3156903
 *
 * Note that the above URL is not actually an issue, but it needs to be an issue
 * because of drupal coder "standards".
 *
 * @internal
 */
trait CommerceXeroDataTestTrait {

  /**
   * The prophesized typed data manager.
   *
   * @var \Prophecy\Prophecy\ObjectProphecy
   */
  protected $typedDataManagerProphet;

  /**
   * Attribute discovery class.
   *
   * @var \Drupal\Component\Plugin\Discovery\AttributeClassDiscovery
   */
  protected $discovery;

  /**
   * Creates the typed data manager prophecy on the object.
   */
  protected function createTypedDataProphet() {
    $this->typedDataManagerProphet = $this->prophesize('\Drupal\Core\TypedData\TypedDataManagerInterface');

    FileCacheFactory::setPrefix(FileCacheFactory::DISABLE_CACHE);
    // There is no good method to figure out the app root so make two educated
    // guesses: directly under modules or under modules/contrib (qa.drupal.org).
    // @todo this no longer works on GitLab CI due to directory changes.
    $root = dirname(substr(__DIR__, 0, -strlen(__NAMESPACE__)));
    if (!realpath($root . '/core')) {
      $root = dirname($root);
    }

    $this->discovery = new AttributeClassDiscovery(
      [
        '\Drupal\xero\Plugin\DataType' => [
          __DIR__ . '/../../../../xero/src/Plugin/DataType/',
          '/builds/project/commerce_xero/web/modules/contrib/xero/src/Plugin/DataType/',
          '/builds/project/commerce_xero/web/modules/custom/xero/src/Plugin/DataType/',
        ],
        '\Drupal\Core\TypedData\Plugin\DataType' => [
          $root . '/core/lib/Drupal/Core/TypedData/Plugin/DataType/',
          '/builds/project/commerce_xero/web/core/lib/Drupal/Core/TypedData/Plugin/DataType/',
        ],
      ],
      DataType::class,
    );

    $this->typedDataManagerProphet
      ->getDefinitions()
      ->willReturn($this->discovery->getDefinitions());
  }

  /**
   * Mock xero and primitive data types recursively.
   *
   * @param string $type
   *   The plugin id.
   * @param mixed $value
   *   The data value to set (not typed data).
   * @param string|int|null $name
   *   An optional property name depending on the typed data to mock.
   * @param \Drupal\Core\TypedData\DataDefinitionInterface|null $itemDefinition
   *   An optional data definition interface for a list.
   *
   * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
   * @throws \Drupal\Core\TypedData\Exception\ReadOnlyException
   */
  protected function mockTypedData(string $type, mixed $value, string|int|null $name = NULL, ?DataDefinitionInterface $itemDefinition = NULL) {
    // Create typed data stub from the given type.
    switch ($type) {

      case 'xero_account':
        $definition = new AccountDefinition(
          [
            'id' => 'xero_account',
            'definition_class' => '\Drupal\xero\TypedData\Definition\AccountDefinition',
          ]
        );
        $class = '\Drupal\xero\Plugin\DataType\Account';

        $this->mockTypedDataProperties($definition, $value);
        break;

      case 'xero_address':
        $definition = new AddressDefinition(
          [
            'id' => 'xero_address',
            'definition_class' => '\Drupal\xero\TypedData\Definition\AddressDefinition',
            'list_class' => '\Drupal\xero\Plugin\DataType\XeroItemList',
          ]
        );
        $class = '\Drupal\xero\Plugin\DataType\Address';
        $this->mockTypedDataProperties($definition, $value);
        break;

      case 'xero_contact':
        $definition = new ContactDefinition([
          'id' => 'xero_contact',
          'definition_class' => '\Drupal\xero\TypedData\Definition\ContactDefinition',
          'list_class' => '\Drupal\xero\Plugin\DataType\XeroItemList',
        ]);

        $class = '\Drupal\xero\Plugin\DataType\Contact';
        $this->mockTypedDataProperties($definition, $value);
        break;

      case 'xero_phone':
        $definition = new PhoneDefinition(
          [
            'id' => 'xero_phone',
            'definition_class' => '\Drupal\xero\TypedData\Definition\PhoneDefinition',
            'list_class' => '\Drupal\xero\Plugin\DataType\XeroItemList',
          ]
        );
        $class = '\Drupal\xero\Plugin\DataType\Phone';
        $this->mockTypedDataProperties($definition, $value);
        break;

      case 'xero_tracking':
        $definition = new TrackingCategoryDefinition(
          [
            'id' => 'xero_tracking',
            'definition_class' => '\Drupal\xero\TypedData\Definition\TrackingCategoryDefinition',
          ]
        );
        $class = '\Drupal\xero\Plugin\DataType\TrackingCategory';

        $this->mockTypedDataProperties($definition, $value);
        break;

      case 'xero_tracking_option':
        $definition = new TrackingOptionDefinition([
          'id' => 'xero_tracking_option',
          'definition_class' => '\Drupal\xero\TypedData\Definition\TrackingOptionDefinition',
        ]);
        $class = '\Drupal\xero\Plugin\DataType\TrackingOption';

        $this->mockTypedDataProperties($definition, $value);
        break;

      case 'xero_tracking_category_option':
        $definition = new TrackingCategoryOptionDefinition(
          [
            'id' => 'xero_tracking_category_option',
            'definition_class' => '\Drupal\xero\TypedData\Definition\TrackingCategoryOptionDefinition',
          ]
        );
        $class = '\Drupal\xero\Plugin\DataType\TrackingCategoryOption';

        $this->mockTypedDataProperties($definition, $value);
        break;

      case 'xero_bank_transaction':
        $definition = new BankTransactionDefinition(
          [
            'id' => 'xero_bank_transaction',
            'definition_class' => '\Drupal\xero\TypedData\Definition\BankTransactionDefinition',
          ]
        );
        $class = '\Drupal\xero\Plugin\DataType\BankTransaction';

        $this->mockTypedDataProperties($definition, $value);
        break;

      case 'xero_invoice':
        $definition = new InvoiceDefinition(
          [
            'id' => 'xero_invoice',
            'definition_class' => '\Drupal\xero\TypedData\InvoiceDefinition',
          ]
        );
        $class = '\Drupal\xero\Plugin\DataType\Invoice';
        $this->mockTypedDataProperties($definition, $value);
        break;

      case 'xero_payment':
        $definition = new PaymentDefinition(
          [
            'id' => 'xero_payment',
            'definition_class' => '\Drupal\xero\TypedData\PaymentDefinition',
          ]
        );
        $class = '\Drupal\xero\Plugin\DataType\Payment';
        $this->mockTypedDataProperties($definition, $value);

        break;

      case 'xero_line_item':
        $definition = new LineItemDefinition(['id' => 'xero_line_item']);
        $class = '\Drupal\xero\Plugin\DataType\LineItem';
        break;

      case 'list':
        $itemType = $itemDefinition->getDataType();
        $listDefinition = new ListDataDefinition(
          [
            'id' => 'list',
            'definition_class' => '\Drupal\Core\TypedData\ListDataDefinition',
          ],
          $itemDefinition
        );
        $definition = $itemDefinition;

        if ($value) {
          $this->mockTypedData($itemType, $value[0], 0, NULL);
        }

        $definition_array = $this->discovery->getDefinition($itemType, FALSE);
        $this->typedDataManagerProphet
          ->getDefinition($itemType)
          ->willReturn($definition_array);

        $class = $definition_array['class'] ?? Any::class;

        $listProphet = $this->prophesize('\Drupal\xero\Plugin\DataType\XeroItemList');
        $listProphet->getItemDefinition()->willReturn($itemDefinition);
        $listProphet->getName()->willReturn($name);
        $listProphet->get(0)->willReturn($value ? $value[0] : NULL);

        $this->typedDataManagerProphet
          ->createListDataDefinition($itemType)
          ->willReturn($listDefinition);
        $this->typedDataManagerProphet
          ->create($listDefinition, Argument::type('array'))
          ->willReturn($listProphet->reveal());
        $this->typedDataManagerProphet
          ->getPropertyInstance(Argument::type('\Drupal\xero\Plugin\DataType\XeroItemList'), Argument::any(), Argument::any())
          ->will(function ($args) {
            $index = $args[1] - 1;
            return $args[0]->get($index);
          });
        break;

      case 'int':
        $definition = new DataDefinition(['id' => 'integer']);
        $class = '\Drupal\Core\TypedData\Plugin\DataType\IntegerData';
        break;

      case 'float':
        $definition = new DataDefinition(['id' => 'float']);
        $class = '\Drupal\Core\TypedData\Plugin\DataType\FloatData';
        break;

      default:
        $definition = new DataDefinition(['id' => 'string']);
        $class = '\Drupal\Core\TypedData\Plugin\DataType\StringData';
    }

    if ($class && class_exists($class)) {
      $data = new $class($definition);
    }
    else {
      $debug_type = isset($itemType) ? $type . '<' . $itemType . '>' : $type;
      $this->fail(printf('class %s does not exist for type: %s', $class, $debug_type));
    }

    // Mock create instance.
    $this->typedDataManagerProphet
      ->create($definition, Argument::any())
      ->willReturn($data);
    $this->typedDataManagerProphet
      ->createInstance($type)
      ->willReturn($data);
    $this->typedDataManagerProphet
      ->createDataDefinition($type)
      ->willReturn($definition);
    // @todo this doesn't handle primitives. Do not assert equality.
    $this->typedDataManagerProphet
      ->getPropertyInstance(Argument::any(), $name, Argument::any())
      ->will(function () use ($data, $value) {
        $data->setValue($value);
        return $data;
      });

    if ($definition instanceof XeroDefinitionInterface) {
      $definition->getPropertyDefinitions();
    }
  }

  /**
   * Mocks typed data properties for a definition.
   *
   * @param \Drupal\Core\TypedData\DataDefinitionInterface $definition
   *   The data definition.
   * @param mixed $values
   *   The values to set.
   *
   * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
   * @throws \Drupal\Core\TypedData\Exception\ReadOnlyException
   */
  protected function mockTypedDataProperties(DataDefinitionInterface $definition, $values): void {
    $itemDefinition = NULL;
    $dataType = NULL;

    if ($definition instanceof ComplexDataDefinitionInterface) {
      /** @var \Drupal\Core\TypedData\DataDefinitionInterface $propDef */
      foreach ($definition->getPropertyDefinitions() as $prop => $propDef) {
        $prop_value = $values[$prop] ?? NULL;
        $dataType = $propDef->getDataType();

        if ($propDef->isList()) {
          /** @var \Drupal\Core\TypedData\ListDataDefinitionInterface $propDef */
          $itemDefinition = $propDef->getItemDefinition();
          $dataType = 'list';
        }

        $this->mockTypedData($dataType, $prop_value, $prop, $itemDefinition);
      }
    }
  }

}

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

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