You are here

public function AttributeTest::testAttributeApi in Ubercart 8.4

Tests the basic attribute API.

File

uc_attribute/tests/src/Functional/AttributeTest.php, line 43

Class

AttributeTest
Tests the product attribute API.

Namespace

Drupal\Tests\uc_attribute\Functional

Code

public function testAttributeApi() {

  // Create an attribute.
  $attribute = $this
    ->createAttribute();

  // Test retrieval.
  $loaded_attribute = uc_attribute_load($attribute->aid);

  // Check the attribute integrity.
  foreach ($this
    ->attributeFieldsToTest() as $field) {
    if ($loaded_attribute->{$field} != $attribute->{$field}) {
      $this
        ->fail('Attribute integrity check failed.');
      break;
    }
  }

  // Add a product.
  $product = $this
    ->createProduct();

  // Attach the attribute to a product.
  uc_attribute_subject_save($attribute, 'product', $product
    ->id());

  // Confirm the database is correct.
  $this
    ->assertEquals($attribute->aid, \Drupal::database()
    ->query('SELECT aid FROM {uc_product_attributes} WHERE nid = :nid', [
    ':nid' => $product
      ->id(),
  ])
    ->fetchField(), 'Attribute was attached to a product properly.');
  $this
    ->assertTrue(uc_attribute_subject_exists($attribute->aid, 'product', $product
    ->id()));

  // Test retrieval.
  $loaded_attribute = uc_attribute_load($attribute->aid, $product
    ->id(), 'product');

  // Check the attribute integrity.
  foreach ($this
    ->attributeFieldsToTest('product') as $field) {
    if ($loaded_attribute->{$field} != $attribute->{$field}) {
      $this
        ->fail('Attribute integrity check failed.');
      break;
    }
  }

  // Delete it.
  uc_attribute_subject_delete($attribute->aid, 'product', $product
    ->id());

  // Confirm again.
  $this
    ->assertFalse(\Drupal::database()
    ->query('SELECT aid FROM {uc_product_attributes} WHERE nid = :nid', [
    ':nid' => $product
      ->id(),
  ])
    ->fetchField(), 'Attribute was detached from a product properly.');
  $this
    ->assertFalse(uc_attribute_subject_exists($attribute->aid, 'product', $product
    ->id()));

  // Add a product class.
  $product_class = $this
    ->createProductClass();

  // Attach the attribute to a product class.
  uc_attribute_subject_save($attribute, 'class', $product_class
    ->id());

  // Confirm the database is correct.
  $this
    ->assertEquals($attribute->aid, \Drupal::database()
    ->query('SELECT aid FROM {uc_class_attributes} WHERE pcid = :pcid', [
    ':pcid' => $product_class
      ->id(),
  ])
    ->fetchField(), 'Attribute was attached to a product class properly.');
  $this
    ->assertTrue(uc_attribute_subject_exists($attribute->aid, 'class', $product_class
    ->id()));

  // Test retrieval.
  $loaded_attribute = uc_attribute_load($attribute->aid, $product_class
    ->id(), 'class');

  // Check the attribute integrity.
  foreach ($this
    ->attributeFieldsToTest('class') as $field) {
    if ($loaded_attribute->{$field} != $attribute->{$field}) {
      $this
        ->fail('Attribute integrity check failed.');
      break;
    }
  }

  // Delete it.
  uc_attribute_subject_delete($attribute->aid, 'class', $product_class
    ->id());

  // Confirm again.
  $this
    ->assertFalse(\Drupal::database()
    ->query('SELECT aid FROM {uc_class_attributes} WHERE pcid = :pcid', [
    ':pcid' => $product_class
      ->id(),
  ])
    ->fetchField(), 'Attribute was detached from a product class properly.');
  $this
    ->assertFalse(uc_attribute_subject_exists($attribute->aid, 'class', $product_class
    ->id()));

  // Create a few more.
  for ($i = 0; $i < 5; $i++) {
    $a = $this
      ->createAttribute();
    $attributes[$a->aid] = $a;
  }

  // Add some options, organizing them by aid and oid.
  $attribute_aids = array_keys($attributes);
  $all_options = [];
  foreach ($attribute_aids as $aid) {
    for ($i = 0; $i < 3; $i++) {
      $option = $this
        ->createAttributeOption([
        'aid' => $aid,
      ]);
      $all_options[$option->aid][$option->oid] = $option;
    }
  }
  for ($i = 0; $i < 3; $i++) {
    $option = $this
      ->createAttributeOption([
      'aid' => $aid,
    ]);
    $all_options[$option->aid][$option->oid] = $option;
  }

  // Get the options.
  $attribute = uc_attribute_load($attribute->aid);

  // Load every attribute we got.
  $attributes_with_options = uc_attribute_load_multiple();

  // Make sure all the new options are on attributes correctly.
  foreach ($all_options as $aid => $options) {
    foreach ($options as $oid => $option) {
      foreach ($this
        ->attributeOptionFieldsToTest() as $field) {
        if ($option->{$field} != $attributes_with_options[$aid]->options[$oid]->{$field}) {
          $this
            ->fail('Option integrity check failed.');
          break;
        }
      }
    }
  }

  // Pick 5 keys to check at random.
  $aids = array_rand($attributes, 3);
  $aids = array_combine($aids, $aids);

  // Load the attributes back.
  $loaded_attributes = uc_attribute_load_multiple($aids);

  // Make sure we only got the attributes we asked for. No more, no less.
  $this
    ->assertSameSize($aids, $loaded_attributes, 'Verifying attribute result.');
  $this
    ->assertSameSize($aids, array_intersect_key($aids, $loaded_attributes), 'Verifying attribute result.');

  // Check the attributes' integrity.
  foreach ($loaded_attributes as $aid => $loaded_attribute) {
    foreach ($this
      ->attributeFieldsToTest() as $field) {
      if ($attributes[$aid]->{$field} != $loaded_attributes[$aid]->{$field}) {
        $this
          ->fail('Attribute integrity check failed.');
        break;
      }
    }
  }

  // Add the selected attributes to the product.
  foreach ($loaded_attributes as $loaded_attribute) {
    uc_attribute_subject_save($loaded_attribute, 'product', $product
      ->id(), TRUE);
  }

  // Test loading all product attributes. (This covers
  // uc_attribute_load_product_attributes(), as the semantics are the same).
  $loaded_product_attributes = uc_attribute_load_multiple([], 'product', $product
    ->id());

  // We'll get all in $loaded_attributes above, plus the original.
  $product_attributes = $loaded_attributes;

  // Make sure we only got the attributes we asked for. No more, no less.
  $this
    ->assertSameSize($loaded_product_attributes, $product_attributes, 'Verifying attribute result.');
  $this
    ->assertSameSize($loaded_product_attributes, array_intersect_key($loaded_product_attributes, $product_attributes), 'Verifying attribute result.');

  // Check the attributes' integrity.
  foreach ($loaded_product_attributes as $aid => $loaded_product_attribute) {
    foreach ($this
      ->attributeFieldsToTest('product') as $field) {
      if ($loaded_product_attributes[$aid]->{$field} != $product_attributes[$aid]->{$field}) {
        $this
          ->fail('Attribute integrity check failed.');
        break;
      }
    }
  }

  // Make sure all the options are on attributes correctly.
  foreach ($all_options as $aid => $options) {
    foreach ($options as $oid => $option) {
      if (empty($loaded_product_attributes[$aid]) || empty($loaded_product_attributes[$aid]->options[$oid])) {
        continue;
      }
      foreach ($this
        ->attributeOptionFieldsToTest() as $field) {
        if ($option->{$field} != $loaded_product_attributes[$aid]->options[$oid]->{$field}) {
          $this
            ->fail('Option integrity check failed.');
          break;
        }
      }
    }
  }

  // Add the selected attributes to the product.
  foreach ($loaded_attributes as $loaded_attribute) {
    uc_attribute_subject_save($loaded_attribute, 'class', $product_class
      ->id(), TRUE);
  }

  // Test loading all product attributes. (This covers
  // uc_attribute_load_product_attributes(), as the semantics are the same).
  $loaded_class_attributes = uc_attribute_load_multiple([], 'class', $product_class
    ->id());

  // We'll get all in $loaded_attributes above, plus the original.
  $class_attributes = $loaded_attributes;

  // Make sure we only got the attributes we asked for. No more, no less.
  $this
    ->assertSameSize($loaded_class_attributes, $class_attributes, 'Verifying attribute result.');
  $this
    ->assertSameSize($loaded_class_attributes, array_intersect_key($loaded_class_attributes, $class_attributes), 'Verifying attribute result.');

  // Check the attributes' integrity.
  foreach ($loaded_class_attributes as $aid => $loaded_class_attribute) {
    foreach ($this
      ->attributeFieldsToTest('class') as $field) {
      if ($loaded_class_attributes[$aid]->{$field} != $class_attributes[$aid]->{$field}) {
        $this
          ->fail('Attribute integrity check failed.');
        break;
      }
    }
  }

  // Make sure all the options are on attributes correctly.
  foreach ($all_options as $aid => $options) {
    foreach ($options as $oid => $option) {
      if (empty($loaded_class_attributes[$aid]) || empty($loaded_class_attributes[$aid]->options[$oid])) {
        continue;
      }
      foreach ($this
        ->attributeOptionFieldsToTest() as $field) {
        if ($option->{$field} != $loaded_class_attributes[$aid]->options[$oid]->{$field}) {
          $this
            ->fail('Option integrity check failed.');
          break;
        }
      }
    }
  }

  // Test deletion of base attribute.
  $options = $attribute->options;
  uc_attribute_delete($attribute->aid);
  $this
    ->assertFalse(uc_attribute_load($attribute->aid), 'Attribute was deleted properly.');

  // Sanity check!
  $this
    ->assertFalse(\Drupal::database()
    ->query('SELECT aid FROM {uc_attributes} WHERE aid = :aid', [
    ':aid' => $attribute->aid,
  ])
    ->fetchField(), 'Attribute was seriously deleted properly!');

  // Test that options were deleted properly.
  foreach ($options as $option) {
    $this
      ->assertFalse(\Drupal::database()
      ->query('SELECT oid FROM {uc_attribute_options} WHERE oid = :oid', [
      ':oid' => $option->oid,
    ])
      ->fetchField(), 'Make sure options are deleted properly.');
  }

  // Test the deletion applied to products too.
  $loaded_product_attributes = uc_attribute_load_multiple([], 'product', $product
    ->id());

  // We'll get all in $loaded_attributes above, without the original. (Which
  // has been deleted.)
  $product_attributes = $loaded_attributes;

  // Make sure we only got the attributes we asked for. No more, no less.
  $this
    ->assertSameSize($loaded_product_attributes, $product_attributes, 'Verifying attribute result.');
  $this
    ->assertSameSize($loaded_product_attributes, array_intersect_key($loaded_product_attributes, $product_attributes), 'Verifying attribute result.');

  // Test the deletion applied to classes too.
  $loaded_class_attributes = uc_attribute_load_multiple([], 'class', $product_class
    ->id());

  // We'll get all in $loaded_attributes above, without the original. (Which
  // has been deleted.)
  $class_attributes = $loaded_attributes;

  // Make sure we only got the attributes we asked for. No more, no less.
  $this
    ->assertSameSize($loaded_class_attributes, $class_attributes, 'Verifying attribute result.');
  $this
    ->assertSameSize($loaded_class_attributes, array_intersect_key($loaded_class_attributes, $class_attributes), 'Verifying attribute result.');

  // Add some adjustments.
  $this
    ->createProductAdjustment([
    'combination' => 'a:1:{i:1;s:1:"1";}',
    'nid' => 1,
  ]);
  $this
    ->createProductAdjustment([
    'combination' => 'a:1:{i:1;s:1:"2";}',
    'nid' => 1,
  ]);
  $this
    ->createProductAdjustment([
    'combination' => 'a:1:{i:1;s:1:"3";}',
    'nid' => 1,
  ]);
  $this
    ->createProductAdjustment([
    'combination' => 'a:1:{i:2;s:1:"1";}',
    'nid' => 2,
  ]);
  $this
    ->createProductAdjustment([
    'combination' => 'a:1:{i:3;s:1:"1";}',
    'nid' => 2,
  ]);
  $this
    ->createProductAdjustment([
    'combination' => 'a:1:{i:1;s:1:"2";}',
    'nid' => 3,
  ]);
  $this
    ->createProductAdjustment([
    'combination' => 'a:1:{i:1;s:1:"3";}',
    'nid' => 3,
  ]);
  $this
    ->createProductAdjustment([
    'combination' => 'a:1:{i:3;s:1:"2";}',
    'nid' => 3,
  ]);
  $this
    ->createProductAdjustment([
    'combination' => 'a:1:{i:3;s:1:"3";}',
    'nid' => 4,
  ]);

  // Test deletion by nid.
  uc_attribute_adjustments_delete([
    'nid' => 1,
  ]);
  $this
    ->assertEquals(6, \Drupal::database()
    ->query('SELECT COUNT(*) FROM {uc_product_adjustments}')
    ->fetchField());

  // Test deletion by aid.
  uc_attribute_adjustments_delete([
    'aid' => 2,
  ]);
  $this
    ->assertEquals(5, \Drupal::database()
    ->query('SELECT COUNT(*) FROM {uc_product_adjustments}')
    ->fetchField());

  // Test deletion by oid.
  uc_attribute_adjustments_delete([
    'oid' => 2,
  ]);
  $this
    ->assertEquals(3, \Drupal::database()
    ->query('SELECT COUNT(*) FROM {uc_product_adjustments}')
    ->fetchField());

  // Test deletion by aid and oid.
  uc_attribute_adjustments_delete([
    'aid' => 1,
    'oid' => 3,
  ]);
  $this
    ->assertEquals(2, \Drupal::database()
    ->query('SELECT COUNT(*) FROM {uc_product_adjustments}')
    ->fetchField());
}