<?php

/**
 * @file
 * Test functionality provided by uc_store.
 */

/**
 * Defines a base helper class for Ubercart tests.
 */
class UbercartTestHelper extends DrupalWebTestCase {

  /** User with privileges to do everything. */
  protected $adminUser;

  /** Authenticated but unprivileged user. */
  protected $customer;

  /** Test product. */
  protected $product;


  /**
   * Configure basic Ubercart store components.
   *
   * @param $modules
   *   Optional list of extra modules to install.
   * @param $permissions
   *   Optional list of extra permissions for $this->adminUser.
   */
  function setUp($modules = array(), $permissions = array()) {
    // Enable the core Ubercart modules and dependencies, along with
    // any other modules passed as arguments.
    $modules = array_merge(array('uc_store', 'ca', 'token', 'uc_order', 'uc_product', 'uc_cart'), $modules);
    call_user_func_array(array('parent', 'setUp'), $modules);

    // Create a store administrator user account.
    $this->adminUser = $this->drupalCreateUser(array_merge($permissions, array(
      'administer store',
      'administer product classes',
      'administer product features',
      'administer products',
      'create products',
      'delete all products',
      'edit all products',
      'create orders',
      'view all orders',
      'edit orders',
      'delete orders',
      'unconditionally delete orders',
    )));

    // Create a simple customer user account.
    $this->customer = $this->drupalCreateUser(array('view own orders'));

    // Create a test product.
    $this->product = $this->createProduct(array('uid' => $this->adminUser->uid));
  }

  /**
   * Creates a new product.
   */
  function createProduct($product = array()) {
    // Set the default required fields.
    $weight_units = array('lb', 'kg', 'oz', 'g');
    $length_units = array('in', 'ft', 'cm', 'mm');
    $product += array(
      'type' => 'product',
      'model' => $this->randomName(8),
      'list_price' => mt_rand(1, 9999),
      'cost' => mt_rand(1, 9999),
      'sell_price' => mt_rand(1, 9999),
      'weight' => mt_rand(1, 9999),
      'weight_units' => array_rand(array_flip($weight_units)),
      'length' => mt_rand(1, 9999),
      'width' => mt_rand(1, 9999),
      'height' => mt_rand(1, 9999),
      'length_units' => array_rand(array_flip($length_units)),
      'pkg_qty' => mt_rand(1, 99),
      'default_qty' => 1,
      'ordering' => mt_rand(-25, 25),
      'shippable' => TRUE,
    );

    return $this->drupalCreateNode($product);
  }

  // Fix this after adding a proper API call for saving a product class.
  function createProductClass($data = array()) {
    $product_class = $data + array(
      'pcid' => $this->randomName(8),
      'name' => $this->randomName(8),
      'description' => $this->randomName(8),
    );
    $product_class = (object) $product_class;

    drupal_write_record('uc_product_classes', $product_class);
    uc_product_node_info(TRUE);
    node_types_rebuild();

    return $product_class;
  }

  /**
   * Executes the checkout process.
   */
  function checkout($edit = array()) {
    $this->drupalPost('cart', array(), 'Checkout');
    $this->assertText(
      t('Enter your billing address and information here.'),
      t('Viewed cart page: Billing pane has been displayed.')
    );

    // Build the panes.
    $zone_id = db_result(db_query('SELECT zone_id FROM {uc_zones} WHERE zone_country_id = %s ORDER BY rand() LIMIT 1', variable_get('uc_store_country', 840)));
    $edit += array(
      'panes[delivery][delivery_first_name]' => $this->randomName(10),
      'panes[delivery][delivery_last_name]' => $this->randomName(10),
      'panes[delivery][delivery_street1]' => $this->randomName(10),
      'panes[delivery][delivery_city]' => $this->randomName(10),
      'panes[delivery][delivery_zone]' => $zone_id,
      'panes[delivery][delivery_postal_code]' => mt_rand(10000, 99999),

      'panes[billing][billing_first_name]' => $this->randomName(10),
      'panes[billing][billing_last_name]' => $this->randomName(10),
      'panes[billing][billing_street1]' => $this->randomName(10),
      'panes[billing][billing_city]' => $this->randomName(10),
      'panes[billing][billing_zone]' => $zone_id,
      'panes[billing][billing_postal_code]' => mt_rand(10000, 99999),
    );

    // If the email address has not been set, and the user has not logged in,
    // add a primary email address.
    if (!isset($edit['panes[customer][primary_email]']) && !$this->loggedInUser) {
      $edit['panes[customer][primary_email]'] = $this->randomName(8) . '@example.com';
    }

    // Submit the checkout page.
    $this->drupalPost('cart/checkout', $edit, t('Review order'));
    $this->assertRaw(t('Your order is almost complete.'));

    // Complete the review page.
    $this->drupalPost(NULL, array(), t('Submit order'));

    if ($order_id = db_result(db_query("SELECT order_id FROM {uc_orders} WHERE delivery_first_name = '%s'", $edit['panes[delivery][delivery_first_name]']))) {
      $this->pass(t('Order %order_id has been created', array('%order_id' => $order_id)));
    }
    else {
      $this->fail(t('No order was created.'));
    }

    return $order_id;
  }
}

/**
 * Test the country import and update functions.
 */
class UbercartCountryTestCase extends UbercartTestHelper {

  public static function getInfo() {
    return array(
      'name' => 'Country functionality',
      'description' => 'Import, edit, and remove countries and their settings.',
      'group' => 'Ubercart',
    );
  }

  function testCountries() {
    $import_file = 'belgium_56_3.cif';
    $country_name = 'Belgium';
    $country_code = 'BEL';

    $this->drupalLogin($this->adminUser);

    $this->drupalGet('admin/store/settings/countries/edit');
    $this->assertRaw(
      '<option value="'. $import_file .'">'. $import_file .'</option>',
      t('Ensure country file is not imported yet.')
    );

    $edit = array(
      'import_file[]' => array($import_file => $import_file),
    );
    $this->drupalPost(
      'admin/store/settings/countries/edit',
      $edit,
      t('Import')
    );
    $this->assertText(
      t('Country file @file imported.', array('@file' => $import_file)),
      t('Country was imported successfully.')
    );
    $this->assertText(
      $country_code,
      t('Country appears in the imported countries table.')
    );
    $this->assertNoRaw(
      '<option value="'. $import_file .'">'. $import_file .'</option>',
      t('Country does not appear in list of files to be imported.')
    );

    $this->clickLink(t('disable'));
    $this->assertText(
      t('@name disabled.', array('@name' => $country_name)),
      t('Country was disabled.')
    );

    $this->clickLink(t('enable'));
    $this->assertText(
      t('@name enabled.', array('@name' => $country_name)),
      t('Country was enabled.')
    );

    $this->clickLink(t('remove'));
    $this->assertText(
      t('Are you sure you want to remove @name from the system?', array('@name' => $country_name)),
       t('Confirm form is displayed.')
    );

    $this->drupalPost(
      'admin/store/settings/countries/56/remove',
       array(),
       t('Remove')
    );
    $this->assertText(
      t('@name removed.', array('@name' => $country_name)),
      t('Country removed.')
    );
    $this->assertRaw(
      '<option value="'. $import_file .'">'. $import_file .'</option>',
       t('Ensure country file is not imported yet.')
    );
    $this->assertNoText(
      $country_code,
      t('Country does not appear in imported countries table.')
    );
  }
}
