You are here

commerce_product.test in Commerce Core 7

Unit tests for the commerce product module.

File

modules/product/tests/commerce_product.test
View source
<?php

/**
 * @file
 * Unit tests for the commerce product module.
 */

/**
 * Test the product and product type CRUD.
 */
class CommerceProductCRUDTestCase extends CommerceBaseTestCase {
  public static function getInfo() {
    return array(
      'name' => 'Product CRUD',
      'description' => 'Test the product CRUD functions.',
      'group' => 'Drupal Commerce',
    );
  }
  function setUp() {
    $modules = parent::setUpHelper('all');
    $modules[] = 'commerce_product_crud_test';
    parent::setUp($modules);
    $this->site_admin = $this
      ->createSiteAdmin();
    cache_clear_all();

    // Just in case
  }

  /**
   * Ensure the default product types are created.
   */
  function testCommerceProductDefaultProducts() {
    $default_types = array(
      'product' => 'Product',
    );

    // Load the default product types.
    $types_created = commerce_product_types();

    // Ensure each type exists.
    foreach ($default_types as $type => $name) {
      $this
        ->assertTrue(!empty($types_created[$type]), 'Product type ' . check_plain($type) . ' has been created.');
    }
  }

  /**
   * Test the product type CRUD functions.
   */
  function testCommerceProductTypeCrud() {

    // Ensure commerce_product_ui_product_type_new() returns a valid empty product type.
    $new_product_type = commerce_product_ui_product_type_new();
    $this
      ->assertNotNull($new_product_type['type'], 'commerce_product_ui_product_type_new() instantiated the type property.');
    $this
      ->assertNotNull($new_product_type['name'], 'commerce_product_ui_product_type_new() instantiated the help property.');
    $this
      ->assertNotNull($new_product_type['description'], 'commerce_product_ui_product_type_new() instantiated the help property.');
    $this
      ->assertNotNull($new_product_type['help'], 'commerce_product_ui_product_type_new() instantiated the help property');

    // Supply customer values for the product type properties.
    $type = $this
      ->randomName(20);
    $name = $this
      ->randomName(40);
    $description = $this
      ->randomString(128);
    $help = $this
      ->randomString(128);

    // Add the values to the new content type.
    $new_product_type['type'] = $type;
    $new_product_type['name'] = $name;
    $new_product_type['description'] = $description;
    $new_product_type['help'] = $help;
    $new_product_type['is_new'] = TRUE;

    // Ensure content_product_ui_product_type_save() returns the proper value when inserting.
    $return = commerce_product_ui_product_type_save($new_product_type);
    $this
      ->assertEqual($return, SAVED_NEW, 'commerce_product_ui_product_type_save() returned SAVED_NEW when saving a new product type.');

    // Load the newly saved content type.
    $saved_product_type = commerce_product_type_load($type);

    // Ensure the values that were saved match the values that we created.
    $this
      ->assertTrue($saved_product_type, 'commerce_product_type_load() loaded the new product type.');
    $this
      ->assertEqual($type, $saved_product_type['type'], 'The new product type type was properly saved and loaded.');
    $this
      ->assertEqual($name, $saved_product_type['name'], 'The new product type name was properly saved and loaded.');
    $this
      ->assertEqual($description, $saved_product_type['description'], 'The new product type description text was properly saved and loaded.');
    $this
      ->assertEqual($help, $saved_product_type['help'], 'The new product type help text was properly saved and loaded.');

    // Alter the title, to ensure the update function works.
    $altered_name = $this
      ->randomName(40);
    $saved_product_type['name'] = $altered_name;

    // Ensure commerce_product_ui_product_type_save() returns the proper value when updating.
    $return = commerce_product_ui_product_type_save($saved_product_type);
    $this
      ->assertEqual($return, SAVED_UPDATED, 'commerce_product_ui_product_type_save() returned SAVED_UPDATED when saving an updated product type.');

    // Reset the cached product types, and verify commerce_product_types load the saved type.
    commerce_product_types_reset();
    $types = commerce_product_types();
    $this
      ->assertNotNull($types[$type], 'commerce_product_types_reset() successfully reset the product types.');
    $this
      ->assertEqual($saved_product_type['name'], $altered_name, 'commerce_product_ui_product_type_save() successfully updated the product type name.');

    // Ensure commerce_product_ui_product_type_delete() deletes a content type.
    commerce_product_ui_product_type_delete($type);
    $deleted_type = commerce_product_type_load($type);
    $this
      ->assertFalse($deleted_type, 'commerce_product_ui_product_type_delete() successfully removed a product type.');
  }

  /**
   * Test the product CRUD functions.
   */
  function testCommerceProductCrud() {
    global $commerce_product_crud_tests;

    // Ensure commerce_product_new() returns a new product.
    $new_product = commerce_product_new('product');
    $fields = array(
      'sku',
      'type',
      'title',
      'uid',
    );
    foreach ($fields as $field) {
      $this
        ->assertNotNull($new_product->{$field}, 'commerce_product_new() instantiated the ' . check_plain($field) . ' property.');
    }
    $new_product->sku = $sku = $this
      ->randomName(10);
    $new_product->type = $type = 'product';
    $new_product->title = $title = $this
      ->randomName(10);
    $new_product->uid = 1;

    // Ensure commerce_product_save() returns SAVED_NEW when saving a new product
    $return = commerce_product_save($new_product);
    $this
      ->assertIdentical($return, SAVED_NEW, 'commerce_product_save() successfully saved the new product.');

    // Ensure commerce_product_load() loaded the saved product.
    $loaded_product = commerce_product_load($new_product->product_id);
    foreach ($fields as $field) {
      $this
        ->assertEqual($loaded_product->{$field}, $new_product->{$field}, 'The ' . check_plain($field) . ' value loaded by commerce_product_load() matches the value saved by commerce_product_save()');
    }
    $this
      ->assertTrue($loaded_product->created > 0, 'commerce_product_save() added a created date to the product');
    $this
      ->assertTrue($loaded_product->changed > 0, 'commerce_product_save() added a changed date to the product');

    // Ensure commerce_product_save() returns SAVED_UPDATED when saving an existing product.
    $loaded_product->uid = 0;
    $return = commerce_product_save($loaded_product);
    $this
      ->assertIdentical($return, SAVED_UPDATED, 'commerce_product_save() successfully updated the product.');

    // Ensure hooks invoked during the save operation can load identical objects
    // be checking a global variable set in commerce_product_crud_test_commerce_product_update()
    // if the uid is in fact being loaded as 0 in the update hook.
    $this
      ->assertTrue($commerce_product_crud_tests['hook_update_identical_uid'], t('Invoked hooks during save operation can successfully load identical object.'));

    // Ensure commerce_product_load_by_sku() can load a product by SKU.
    $loaded_product_by_sku = commerce_product_load_by_sku($sku);
    $this
      ->assertEqual($loaded_product_by_sku->product_id, $new_product->product_id, 'The ID of the product loaded via commerce_product_load_by_sku() matches the saved product ID.');

    // Ensure commerce_product_load_multiple() can load multiple multiple products.
    $saved_product_ids = array();

    // First create and save multiple new products.
    for ($i = 0; $i < 3; $i++) {
      $product = commerce_product_new('product');
      $product->type = 'product';
      $product->sku = $this
        ->randomName(10);
      $product->title = $this
        ->randomName(10);
      $product->uid = 1;
      commerce_product_save($product);

      // Save the ID and title of the newly created product.
      $saved_products[$product->product_id] = $product->title;
    }
    $loaded_products = commerce_product_load_multiple(array_keys($saved_products));
    $this
      ->assertEqual(count($saved_products), count($loaded_products), 'commerce_product_load_multiple() loaded the proper number of the products.');
    foreach ($loaded_products as $loaded_product) {
      $this
        ->assertEqual($loaded_product->title, $saved_products[$loaded_product->product_id], 'commerce_product_load_multiple() successfully loaded a product.');
    }

    // Ensure commerce_product_delete() can remove a product.
    $return = commerce_product_delete($new_product->product_id);
    $this
      ->assertTrue($return, 'commerce_product_delete() returned TRUE when deleting a product.');
    $deleted_product_load = commerce_product_load_multiple(array(
      $new_product->product_id,
    ), array(), TRUE);
    $this
      ->assertFalse($deleted_product_load, 'commerce_product_load_multiple() could not load the deleted product.');

    // Ensure commerce_product_delete_multiple() can delete multiple products.
    $return = commerce_product_delete_multiple(array_keys($saved_products));
    $this
      ->assertTrue($return, 'commerce_product_delete_multiple() returned TRUE when deleting a product.');
    $deleted_products_load = commerce_product_load_multiple(array_keys($saved_products), array(), TRUE);
    $this
      ->assertFalse($deleted_product_load, 'commerce_product_load_multiple() could not load the deleted products.');
  }

  /**
   * Test product Token replacement.
   */
  function testCommerceProductTokens() {
    $product = commerce_product_new('product');
    $creator = $this
      ->drupalCreateUser();
    $product->sku = $this
      ->randomName(10);
    $product->title = $this
      ->randomName(10);
    $product->uid = $creator->uid;
    commerce_product_save($product);
    $this
      ->assertEqual(token_replace('[commerce-product:product-id]', array(
      'commerce-product' => $product,
    )), $product->product_id, '[commerce-product:product-id] was replaced with the product ID.');
    $this
      ->assertEqual(token_replace('[commerce-product:sku]', array(
      'commerce-product' => $product,
    )), $product->sku, '[commerce-product:sku] was replaced with the SKU.');
    $this
      ->assertEqual(token_replace('[commerce-product:type]', array(
      'commerce-product' => $product,
    )), $product->type, '[commerce-product:type] was replaced with the product type.');
    $this
      ->assertEqual(token_replace('[commerce-product:type-name]', array(
      'commerce-product' => $product,
    )), commerce_product_type_get_name($product->type), '[commerce-product:type-name] was replaced with the product type.');
    $this
      ->assertEqual(token_replace('[commerce-product:title]', array(
      'commerce-product' => $product,
    )), $product->title, '[commerce-product:title] was replaced with the title.');
    $this
      ->assertNotIdentical(strpos(token_replace('[commerce-product:edit-url]', array(
      'commerce-product' => $product,
    )), url('admin/commerce/products/' . $product->product_id . '/edit')), FALSE, '[commerce-product:edit-url] was replaced with the edit URL.');
    $this
      ->assertEqual(token_replace('[commerce-product:creator:uid]', array(
      'commerce-product' => $product,
    )), $product->uid, '[commerce-product:creator:uid] was replaced with the uid of the creator.');
    $this
      ->assertEqual(token_replace('[commerce-product:creator:name]', array(
      'commerce-product' => $product,
    )), check_plain(format_username($creator)), '[commerce-product:creator:name] was replaced with the name of the author.');
    $this
      ->assertEqual(token_replace('[commerce-product:created]', array(
      'commerce-product' => $product,
    )), format_date($product->created, 'medium'), '[commerce-product:created] was replaced with the created date.');
    $this
      ->assertEqual(token_replace('[commerce-product:changed]', array(
      'commerce-product' => $product,
    )), format_date($product->changed, 'medium'), '[commerce-product:changed] was replaced with the changed date.');
  }

  /**
   * Test product revision management.
   */
  function testCommerceProductRevisions() {
    $new_product = commerce_product_new('product');
    $new_product->sku = $this
      ->randomName(10);
    $new_product->type = 'product';
    $new_product->title = $this
      ->randomName(10);
    $new_product->uid = 1;
    commerce_product_save($new_product);

    // Ensure commerce_product_save() returns an entity with the revision_id set.
    $this
      ->assertNotNull($new_product->revision_id, 'Revision id was created after first save.');

    // Ensure that on update with the revision set to TRUE a new revision is
    // created.
    $old_revision_id = $new_product->revision_id;
    $new_product->revision = TRUE;
    $new_product->title = $this
      ->randomName(10);
    commerce_product_save($new_product);
    $this
      ->assertNotEqual($old_revision_id, $new_product->revision_id, 'New revision was created');

    // Ensure that on update with the revision set to FALSE a new revision is
    // not created.
    $old_revision_id = $new_product->revision_id;
    $new_product->revision = FALSE;
    $new_product->title = $this
      ->randomName(10);
    commerce_product_save($new_product);
    $this
      ->assertEqual($old_revision_id, $new_product->revision_id, 'No new revision was created');
  }

}

/**
* Test the Rules and Entity integration.
*
* TODO: replace this with a simpler event test that doesn't depend on the odd
* product loading / saving interplay. I don't even think the unchanged
* condition will ever work as is in here.
*
class CommerceProductRulesTestCase extends DrupalWebTestCase {

 public static function getInfo() {
   return array(
     'name' => 'Product rules integration',
     'description' => 'Tests the product rules integration.',
     'group' => 'Drupal Commerce',
   );
 }

 function setUp() {
   parent::setUp('commerce_product', 'rules');
 }

 /**
  * Calculates the output of t() given an array of placeholders to replace.
  *
 static function t($text, $strings) {
   $placeholders = array();
   foreach ($strings as $string) {
     $placeholders['%' . $string] = drupal_placeholder($string);
   }
   return strtr($text, $placeholders);
 }

 /**
  * Tests rules CRUD actions for products.
  *
 function testRulesCRUD() {
   // Test creation.
   $action = rules_action('entity_create', array(
     'type' => 'commerce_product',
     'param_type' => 'product',
     'param_sku' => 'foo',
     'param_title' => 'bar',
     'param_creator' => $GLOBALS['user'],
   ));
   // Test running access() and execute.
   $action->access();
   $action->execute();

   $text = RulesLog::logger()->render();
   $pos = strpos($text, self::t('Added the provided variable %entity_created of type %commerce_product', array('entity_created', 'commerce_product')));
   $pos = ($pos !== FALSE) ? strpos($text, self::t('Saved %entity_created of type %commerce_product.', array('entity_created', 'commerce_product')), $pos) : FALSE;
   $this->assertTrue($pos !== FALSE, 'Product has been created and saved.');

   $product = commerce_product_new('product');
   commerce_product_save($product);
   $rule = rule();
   $rule->action('entity_fetch', array('type' => 'commerce_product', 'id' => $product->product_id, 'entity_fetched:var' => 'product'));
   $rule->action('entity_save', array('data:select' => 'product', 'immediate' => TRUE));
   $rule->action('entity_delete', array('data:select' => 'product'));
   // Test running access and integrtiy check + execute.
   $rule->access();
   $rule->integrityCheck()->execute();
   $text = RulesLog::logger()->render();
   $pos = strpos($text, RulesTestCase::t('Evaluating the action %entity_fetch.', array('entity_fetch')));
   $pos = ($pos !== FALSE) ? strpos($text, self::t('Added the provided variable %product of type %commerce_product', array('product', 'commerce_product')), $pos) : FALSE;
   $pos = ($pos !== FALSE) ? strpos($text, self::t('Saved %product of type %commerce_product.', array('product', 'commerce_product')), $pos) : FALSE;
   $pos = ($pos !== FALSE) ? strpos($text, self::t('Evaluating the action %entity_delete.', array('entity_delete')), $pos) : FALSE;
   $this->assertTrue($pos !== FALSE, 'Product has been fetched, saved and deleted.');
   $this->assertFalse(commerce_product_load($product->product_id), 'Product has been deleted.');
 }

 /**
  * Tests making use of product metadata.
  *
 function testProductPropertyInfo() {
   // Populate $values with all values that are setable. They will be set
   // with an metadata wrapper, so we also test setting that way.
   $values = array();
   $wrapper = entity_metadata_wrapper('commerce_product');
   foreach ($wrapper as $name => $child) {
     $info = $wrapper->$name->info();
     if (!empty($info['setter callback'])) {
       $info += array('type' => 'text');
       $values[$name] = $this->createValue($info['type'], $info);
     }
   }
   $values['type'] = 'product';
   $product = entity_create('commerce_product', $values);
   $this->assertTrue($product, "Created a product and set all setable values.");

   $wrapper = entity_metadata_wrapper('commerce_product', $product);
   foreach ($wrapper as $key => $child) {
     $this->assertValue($wrapper, $key);
   }
 }

 /**
  * Assert the value for the given property is returned.
  *
 protected function assertValue($wrapper, $key) {
   $this->assertTrue($wrapper->$key->value() !== NULL, check_plain($key) . ' property returned.');
   $info = $wrapper->$key->info();
   if (!empty($info['raw getter callback'])) {
     // Also test getting the raw value
     $this->assertTrue($wrapper->$key->raw() !== NULL, check_plain($key) . ' raw value returned.');
   }
 }

 /**
  * Creates a value for the given data type.
  *
 protected function createValue($type, $info) {
   if (!isset($this->node)) {
     // Create some entities to use the first time this runs.
     $this->node = $this->drupalCreateNode(array('type' => 'article'));
     $this->user = $this->drupalCreateUser();
   }

   if (isset($info['options list'])) {
     $options = array_keys($info['options list']());
     return entity_property_list_extract_type($type) ? array(reset($options)) : reset($options);
   }

   switch ($type) {
     case 'decimal':
     case 'integer':
     case 'duration':
       return 1;
     case 'date':
       return REQUEST_TIME;
     case 'boolean':
       return TRUE;
     case 'text':
       return drupal_strtolower($this->randomName(8));
     case 'text_formatted':
       return array('value' => $this->randomName(16));

     default:
       return $this->$type;
   }
 }


 /**
  * Tests making use of the product 'presave' event and loading the unchanged
  * product.
  *
 public function testProductEvent() {
   $rule = rules_reaction_rule();
   $rule->event('commerce_product_presave')
        ->condition('data_is', array('data:select' => 'product:type', 'value' => 'product'))
        ->condition(rules_condition('data_is', array('data:select' => 'product:sku', 'value:select' => 'product_unchanged:sku'))->negate())
        ->action('entity_delete', array('data:select' => 'product'));
   // Try running access and integrity checks.
   $rule->access();
   $rule->integrityCheck();
   // Save it.
   $rule->save('commerce_product_test1', 'commerce_product');

   // Force immediate cache clearing so we can test the rule *now*.
   rules_clear_cache(TRUE);

   // Create initial product.
   $product = commerce_product_new('product');
   $product->sku = 'foo';
   commerce_product_save($product);

   $this->assertTrue(commerce_product_load($product->product_id), 'Reaction rule not fired.');

   // Now update, so that the rule fires.
   $product->sku = 'bar';
   unset($product->is_new);
   commerce_product_save($product);
   $this->assertFalse(commerce_product_load($product->product_id), 'Reaction rule fired.');
   RulesLog::logger()->checkLog();
 }
}
*/

Classes

Namesort descending Description
CommerceProductCRUDTestCase Test the product and product type CRUD.