xero-8.x-2.x-dev/tests/src/Kernel/Normalizer/XeroNestedNormalizerTest.php

tests/src/Kernel/Normalizer/XeroNestedNormalizerTest.php
<?php

namespace Drupal\Tests\xero\Kernel\Normalizer;

use Drupal\Core\TypedData\TypedDataTrait;
use Drupal\KernelTests\KernelTestBase;
use Drupal\serialization\Normalizer\ComplexDataNormalizer;
use Drupal\serialization\Normalizer\TypedDataNormalizer;
use Drupal\xero\Normalizer\XeroListNormalizer;
use Drupal\xero\Normalizer\XeroNormalizer;
use Symfony\Component\Serializer\Serializer;

/**
 * Tests denormalizer with services enabled.
 *
 * @group xero
 */
class XeroNestedNormalizerTest extends KernelTestBase {

  use TypedDataTrait;

  /**
   * {@inheritdoc}
   */
  protected static $modules = ['user', 'serialization', 'xero'];

  /**
   * Asserts that denormalization works for deeply-nested objects.
   */
  public function testDenormalize() {
    $data = [
      'TrackingCategories' => [
        [
          'Name' => 'Region',
          'Status' => 'ACTIVE',
          'TrackingCategoryID' => '351953c4-8127-4009-88c3-f9cd8c9cbe9f',
          'Options' => [
              ['Name' => 'West Coast', 'Status' => 'ACTIVE'],
              ['Name' => 'Eastside', 'Status' => 'ACTIVE'],
          ],
        ],
      ],
    ];
    $normalizer = new XeroNormalizer($this->getTypedDataManager());
    $denormalizedData = $normalizer->denormalize(
      $data,
      '\Drupal\xero\Plugin\DataType\TrackingCategory',
      'json',
      ['plugin_id' => 'xero_tracking']
    );

    $values = $denormalizedData->getValue();
    $this->assertArrayHasKey('Options', $values[0]);
    $this->assertArrayNotHasKey('Option', $values[0]['Options']);
    $this->assertCount(2, $denormalizedData->get(0)->get('Options'));
  }

  /**
   * Tests normalization of Xero contact data under different data scenarios.
   *
   * @param array $expected
   *   The expected normalized value.
   * @param array $data
   *   The data for the typed data object.
   * @param string $message
   *   An optional message to display for the test.
   *
   * @dataProvider contactProvider
   */
  public function testNormalizeContact(array $expected, array $data, $message) {
    $this->assertNormalizationSuccessful(
      $expected, $message, 'xero_contact', 'Contact', $data, []
    );
    $this->assertNormalizationSuccessful(
      $expected, $message, 'xero_contact', 'Contact', [], $data
    );
  }

  /**
   * Tests normalization of contact when it is updated with partial data.
   */
  public function testNormalizePartialContact() {
    $definition = $this->getTypedDataManager()
      ->createDataDefinition('xero_contact');
    $normalizer = $this->getNormalizer();

    $initial = [
      'Name' => 'ABC Limited',
      'Phones' => [
        ['PhoneType' => 'DEFAULT'],
        ['PhoneType' => 'MOBILE'],
      ],
    ];

    $item = $this->getTypedDataManager()
      ->create($definition, $initial, 'Contact');
    $phoneItem = $item->get('Phones')->get(0);
    $phoneItem->get('PhoneNumber')->setValue('1111111');
    $phoneItem->get('PhoneAreaCode')->setValue('04');
    $phoneItem->get('PhoneCountryCode')->setValue('64');

    $normalized = $normalizer->normalize($item, 'json', [
      'plugin_id' => 'xero_contact',
    ]);
    $expected = [
      'Name' => 'ABC Limited',
      'Phones' => [
        [
          'PhoneType' => 'DEFAULT',
          'PhoneNumber' => '1111111',
          'PhoneAreaCode' => '04',
          'PhoneCountryCode' => '64',
        ],
        [
          'PhoneType' => 'MOBILE',
        ],
      ],
    ];

    $this->assertSame($expected, $normalized);
  }

  /**
   * Tests normalization of Xero invoice data under different data scenarios.
   *
   * @param array $expected
   *   The expected normalized value.
   * @param array $data
   *   The data to for the typed data object.
   * @param string $message
   *   An optional message to display for the test.
   *
   * @dataProvider invoiceProvider
   */
  public function testNormalizeInvoice(array $expected, array $data, $message) {
    $this->assertNormalizationSuccessful(
      $expected, $message, 'xero_invoice', 'Invoice', $data, []
    );
    $this->assertNormalizationSuccessful(
      $expected, $message, 'xero_invoice', 'Invoice', [], $data
    );
  }

  /**
   * Provides test arguments for testNormalizeContact.
   *
   * @return array<int, mixed>[]
   *   An indexed array of tests to run with test arguments.
   */
  public static function contactProvider() {
    return [
      [
        [],
        [],
        'empty data is empty',
      ],
      [
        ['Name' => 'ABC Limited'],
        ['Name' => 'ABC Limited'],
        'single properties property are normalized with value.',
      ],
      [
        [
          'Name' => 'ABC Limited',
          'FirstName' => 'Ben',
          'LastName' => 'Bowden',
        ],
        [
          'Name' => 'ABC Limited',
          'FirstName' => 'Ben',
          'LastName' => 'Bowden',
        ],
        'multiple and optional properties are normalized with values.',
      ],
      [
        [
          'FirstName' => 'Ben',
          'LastName' => 'Bowden',
        ],
        [
          'FirstName' => 'Ben',
          'LastName' => 'Bowden',
        ],
        'required properties are excluded if unspecified.',
      ],
      [
        [
          'Name' => 'ABC Limited',
          'FirstName' => NULL,
          'LastName' => '',
        ],
        [
          'Name' => 'ABC Limited',
          'FirstName' => NULL,
          'LastName' => '',
        ],
        'empty properties are normalized as empty values.',
      ],
      [
        [
          'Name' => 'ABC Limited',
          'Phones' => [
            [
              'PhoneAreaCode' => '083',
              'PhoneNumber' => '111',
            ],
          ],
        ],
        [
          'Name' => 'ABC Limited',
          'Phones' => [
            [
              'PhoneNumber' => '111',
              'PhoneAreaCode' => '083',
            ],
          ],
        ],
        'a specified nested xero property is normalized with nested values',
      ],
      [
        [
          'Name' => 'ABC Limited',
          'Phones' => [],
        ],
        [
          'Name' => 'ABC Limited',
          'Phones' => [],
        ],
        'explicitly empty nested properties are normalized as empty arrays',
      ],
      [
        [
          'Name' => 'ABC Limited',
          'Phones' => [],
        ],
        [
          'Name' => 'ABC Limited',
          'Phones' => NULL,
        ],
        'explicitly nulled nested properties are normalized as empty arrays',
      ],
    ];
  }

  /**
   * Provides test arguments for testNormalizeInvoice.
   *
   * @return array<int, mixed>[]
   *   An indexed array of tests to run with test arguments.
   */
  public static function invoiceProvider() {
    return [
      [
        [],
        [],
        'empty data is empty',
      ],
      [
        ['Type' => 'ACCREC'],
        ['Type' => 'ACCREC'],
        'single properties property are normalized with value.',
      ],
      [
        [
          'Type' => 'ACCPAY',
          'Date' => '2011-10-12',
          'Reference' => 'Inv23123',
        ],
        [
          'Type' => 'ACCPAY',
          'Date' => '2011-10-12',
          'Reference' => 'Inv23123',
        ],
        'multiple and optional properties are normalized with values.',
      ],
      [
        [
          'Type' => 'ACCPAY',
          'InvoiceNumber' => NULL,
          'Reference' => '',
        ],
        [
          'Type' => 'ACCPAY',
          'InvoiceNumber' => NULL,
          'Reference' => '',
        ],
        'empty properties are normalized as empty values.',
      ],
      [
        [
          'Type' => 'ACCPAY',
          'Contact' => [
            'Name' => 'ABC Limited',
            'FirstName' => 'Ben',
          ],
        ],
        [
          'Type' => 'ACCPAY',
          'Contact' => [
            'Name' => 'ABC Limited',
            'FirstName' => 'Ben',
          ],
        ],
        'a specified nested xero property is normalized with nested values',
      ],
      [
        [
          'Type' => 'ACCPAY',
          'LineItems' => [],
        ],
        [
          'Type' => 'ACCPAY',
          'LineItems' => [],
        ],
        'explicitly empty nested list properties are normalized as empty arrays',
      ],
      [
        [
          'Type' => 'ACCPAY',
          'LineItems' => [],
        ],
        [
          'Type' => 'ACCPAY',
          'LineItems' => NULL,
        ],
        'explicitly nulled nested list properties are normalized as empty arrays',
      ],
      [
        [
          'Type' => 'ACCPAY',
        ],
        [
          'Type' => 'ACCPAY',
          'HasAttachments' => TRUE,
        ],
        'explicitly set properties are ignored if read-only',
      ],
      [
        [
          'Type' => 'ACCPAY',
        ],
        [
          'Type' => 'ACCPAY',
          'HasAttachments' => NULL,
        ],
        'explicitly empty properties are ignored if read-only',
      ],
      [
        [
          'Type' => 'ACCPAY',
        ],
        [
          'Type' => 'ACCPAY',
          'Payments' => NULL,
        ],
        'explicitly empty nested list properties are ignored if read-only',
      ],
    ];
  }

  /**
   * Test setting to null the contact on the invoice.
   */
  public function testInvoiceContact() {
    $data = [
      'Type' => 'ACCPAY',
      'Contact' => NULL,
    ];

    $message = 'nested property explicitly set to null is normalized to empty array';
    $expected = [
      'Type' => 'ACCPAY',
      'Contact' => [],
    ];
    $this->assertNormalizationSuccessful(
      $expected, $message, 'xero_invoice', 'Invoice', [], $data
    );

    $message = 'nested property explicitly created as null is normalized to empty array';
    $expected = ['Type' => 'ACCPAY', 'Contact' => []];
    $this->assertNormalizationSuccessful(
      $expected, $message, 'xero_invoice', 'Invoice', $data, []
    );
  }

  /**
   * Tests the normalization of a Xero type under different data scenarios.
   *
   * @param array $expected
   *   The expected normalized value.
   * @param string $message
   *   An message to display for the test.
   * @param string $xeroType
   *   The Xero type to test.
   * @param string $xeroTypeLabel
   *   The label of the Xero type to test.
   * @param array $initialData
   *   (optional) The data to create the typed data object with.
   * @param array $subsequentData
   *   (optional) The data to set subsequently on the typed data object.
   */
  public function assertNormalizationSuccessful(array $expected, $message, $xeroType, $xeroTypeLabel, array $initialData = [], array $subsequentData = []) {
    $definition = $this->getTypedDataManager()
      ->createDataDefinition($xeroType);

    $item = $this->getTypedDataManager()->create($definition, $initialData, $xeroTypeLabel);
    foreach ($subsequentData as $name => $value) {
      $item->get($name)->setValue($value);
    }

    $normalized = \Drupal::service('serializer')->normalize($item, 'json', [
      'plugin_id' => $xeroType,
    ]);
    $this->assertNormalizedSame($expected, $normalized, "$message");

    // Test the normalization as part of a list.
    $list_definition = $this->typedDataManager->createListDataDefinition($xeroType);
    $list = $this->typedDataManager->create($list_definition, []);
    $list->offsetSet(0, $item);
    $list_normalized = \Drupal::service('serializer')->normalize($list, 'json', [
      'plugin_id' => $xeroType,
    ]);
    $this->assertNormalizedSame($expected, $list_normalized, "$message (on list).");
  }

  /**
   * Asserts that the normalized values are the same.
   *
   * @param mixed $expected
   *   The expected array or string.
   * @param mixed $actual
   *   The actual array or string.
   * @param string $message
   *   A message to print out.
   */
  protected function assertNormalizedSame($expected, $actual, $message): void {
    // Ignore order of properties.
    $expected = is_array($expected) ? $this->recursiveKSort($expected) : $expected;
    $actual = is_array($actual) ? $this->recursiveKSort($actual) : $actual;
    // Use assertSame as data type may matter.
    $this->assertSame($expected, $actual, $message);
  }

  /**
   * Recursively sorts an associative array.
   *
   * @param array $array
   *   The array to sort.
   *
   * @return array
   *   The sorted array.
   */
  protected function recursiveKSort(array $array): array {
    // First, sort the main array.
    ksort($array);
    // Then check for child arrays.
    foreach ($array as $key => $value) {
      if (is_array($value)) {
        $value = $this->recursiveKSort($value);
      }
      $array[$key] = $value;
    }
    return $array;
  }

  /**
   * Gets the normalizer.
   *
   * @return \Drupal\xero\Normalizer\XeroNormalizer
   *   The normalizer instance.
   */
  protected function getNormalizer() {
    $normalizer = new XeroNormalizer($this->typedDataManager);
    $listNormalizer = new XeroListNormalizer();
    $typeddata_normalizer = new TypedDataNormalizer();
    $complex_normalizer = new ComplexDataNormalizer();
    $serializer = new Serializer([
      $listNormalizer,
      $normalizer,
      $typeddata_normalizer,
      $complex_normalizer,
    ]);
    $normalizer->setSerializer($serializer);

    return $normalizer;
  }

  /**
   * Tests denormalization of Xero bank transaction with the Contact property.
   */
  public function testDenormalizeBankTransaction() {
    $expected = [
      'ContactID' => '6d42f03b-181f-43e3-93fb-2025c012de92',
      'Name' => 'Wilson Periodicals',
    ];
    $data = [
      'BankTransactions' => [
        [
          'BankTransactionID' => 'd20b6c54-7f5d-4ce6-ab83-55f609719126',
          'Contact' => [
            'ContactID' => '6d42f03b-181f-43e3-93fb-2025c012de92',
            'Name' => 'Wilson Periodicals',
          ],
          'Date' => '2021-09-01T00:00:00',
          'Status' => 'AUTHORISED',
          'LineAmountType' => 'Inclusive',
          'Total' => '49.90',
          'TotalTax' => '0.00',
          'SubTotal' => '49.90',
          'BankAccount' => [
            'AccountID' => 'ac993f75-035b-433c-82e0-7b7a2d40802c',
            'Code' => '090',
            'Name' => 'Business Bank Account',
          ],
          'CurrencyCode' => 'NZD',
          'Type' => 'RECEIVE',
          'IsReconciled' => TRUE,
        ],
      ],
    ];
    $normalizer = new XeroNormalizer($this->getTypedDataManager());
    $denormalizedData = $normalizer->denormalize(
      $data,
      '\Drupal\xero\Plugin\DataType\BankTransaction',
      'xml',
      [
        'plugin_id' => 'xero_bank_transaction',
      ],
    );

    $values = $denormalizedData->getValue();
    $this->assertArrayHasKey('Contact', $values[0]);
    $this->assertArrayHasKey('BankAccount', $values[0]);
    $this->assertEquals($expected, $values[0]['Contact']);
  }

}

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

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