123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437 |
- <?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;
- /**
- * Overrides DrupalWebTestCase::setUp().
- *
- * Configures basic Ubercart store components.
- *
- * @param $modules
- * Optional list of extra modules to install.
- * @param $permissions
- * Optional list of extra permissions for $this->adminUser.
- */
- protected 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', 'rules', '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 order workflow',
- 'administer product classes',
- 'administer product features',
- 'administer products',
- 'create product content',
- 'delete any product content',
- 'edit any product content',
- '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);
- }
- /**
- * Creates a new product class.
- *
- * 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);
- return $product_class;
- }
- /**
- * Helper function to fill-in required fields on the checkout page.
- *
- * @param $edit
- * The form-values array to which to add required fields.
- */
- function populateCheckoutForm($edit = array()) {
- foreach (array('billing', 'delivery') as $pane) {
- $prefix = 'panes[' . $pane . '][' . $pane;
- $key = $prefix . '_country]';
- $country = empty($edit[$key]) ? variable_get('uc_store_country', 840) : $edit[$key];
- $zone_id = db_query_range('SELECT zone_id FROM {uc_zones} WHERE zone_country_id = :country ORDER BY rand()', 0, 1, array('country' => $country))->fetchField();
- $edit += array(
- $prefix . '_first_name]' => $this->randomName(10),
- $prefix . '_last_name]' => $this->randomName(10),
- $prefix . '_street1]' => $this->randomName(10),
- $prefix . '_city]' => $this->randomName(10),
- $prefix . '_zone]' => $zone_id,
- $prefix . '_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';
- }
- return $edit;
- }
- /**
- * 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.')
- );
- $edit = $this->populateCheckoutForm($edit);
- // 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'));
- $order_id = db_query("SELECT order_id FROM {uc_orders} WHERE delivery_first_name = :name", array(':name' => $edit['panes[delivery][delivery_first_name]']))->fetchField();
- if ($order_id) {
- $this->pass(
- t('Order %order_id has been created', array('%order_id' => $order_id))
- );
- $order = uc_order_load($order_id);
- }
- else {
- $this->fail(t('No order was created.'));
- $order = FALSE;
- }
- return $order;
- }
- /**
- * Assert that an email was sent with a specific subject line.
- *
- * @param $pattern
- * A regular expression to match the subject against.
- *
- * @return
- * An array containing the most recently sent matching email,
- * or FALSE if the subject line did not match anything.
- */
- function findMail($pattern) {
- foreach (array_reverse($this->drupalGetMails()) as $mail) {
- if (preg_match($pattern, $mail['subject'])) {
- $this->pass(t('E-mail found with subject matching %pattern.', array('%pattern' => $pattern)));
- return $mail;
- }
- }
- $this->fail(t('E-mail not found with subject matching %pattern.', array('%pattern' => $pattern)));
- return FALSE;
- }
- /**
- * Helper function to test for text in a drupal ajax response.
- *
- * @param $ajax
- * The ajax response to test. Must be an array of ajax commands as returned by drupalPostAjax().
- * @param $text
- * The text to search for.
- * @param $message
- * The assertion message.
- * @param $not_exists
- * TRUE to assert that the text is not present. FALSE (the default) to assert that it is present.
- * @param $plain
- * TRUE to check only the plain-text contents of the 'data' keys of each 'insert' command (i.e. what would
- * be inserted into the page). FALSE to check the complete, json-encoded ajax response.
- */
- function assertAjaxHelper($ajax, $text, $message = FALSE, $not_exists = FALSE, $plain = TRUE) {
- $content = '';
- if ($plain) {
- foreach ($ajax as $command) {
- if ($command['command'] == 'insert' && !empty($command['data']) && is_string($command['data'])) {
- $content .= $command['data'];
- }
- }
- $content = filter_xss($content, array());
- }
- else {
- $content = drupal_json_encode($ajax);
- }
- if (!$message) {
- $message = !$not_exists ? t('"@text" found in ajax response', array('@text' => $text)) : t('"@text" not found in ajax response', array('@text' => $text));
- }
- $this->assert($not_exists == (strpos($content, $text) === FALSE), $message);
- }
- /**
- * Assert that the specified text is present in the plain text version of the html that would
- * be inserted into the page if this ajax response were executed.
- *
- * @param $ajax
- * The ajax response to test. Must be an array of ajax commands as returned by drupalPostAjax().
- * @param $text
- * The text to search for.
- * @param $message
- * The assertion message.
- */
- function assertAjaxText($ajax, $text, $message = FALSE) {
- $this->assertAjaxHelper($ajax, $text, $message, FALSE, TRUE);
- }
- /**
- * Assert that the specified text is not present in the plain text version of the html that would
- * be inserted into the page if this ajax response were executed.
- *
- * @param $ajax
- * The ajax response to test. Must be an array of ajax commands as returned by drupalPostAjax().
- * @param $text
- * The text to search for.
- * @param $message
- * The assertion message.
- */
- function assertNoAjaxText($ajax, $text, $message = FALSE) {
- $this->assertAjaxHelper($ajax, $text, $message, TRUE, TRUE);
- }
- /**
- * Assert that the specified text is present in the raw drupal ajax response.
- *
- * @param $ajax
- * The ajax response to test. Must be an array of ajax commands as returned by drupalPostAjax().
- * @param $text
- * The text to search for.
- * @param $message
- * The assertion message.
- */
- function assertAjaxRaw($ajax, $text, $message = FALSE) {
- $this>assertAjaxHelper($ajax, $text, $message, FALSE, FALSE);
- }
- /**
- * Assert that the specified text is not present in the raw drupal ajax response.
- *
- * @param $ajax
- * The ajax response to test. Must be an array of ajax commands as returned by drupalPostAjax().
- * @param $text
- * The text to search for.
- * @param $message
- * The assertion message.
- */
- function assertNoAjaxRaw($ajax, $text, $message = FALSE) {
- $this>assertAjaxHelper($ajax, $text, $message, TRUE, FALSE);
- }
- /**
- * Extends drupalPostAjax() to replace additional content on the page after an ajax submission.
- *
- * DrupalWebTestCase::drupalPostAjax() will only process ajax insertions which don't have a 'selector' attribute,
- * because it's not easy to convert from a jQuery selector to an XPath. However, ubercart uses many simple,
- * id-based selectors, and these can be converted easily (eg: '#my-identifier' => '//*[@id="my-identifier"]').
- * This helper method post-processes the command array returned by drupalPostAjax() to perform these insertions.
- *
- * @see DrupalWebTestCase::drupalPostAjax()
- */
- protected function ucPostAJAX($path, $edit, $triggering_element, $ajax_path = NULL, array $options = array(), array $headers = array(), $form_html_id = NULL, $ajax_settings = NULL) {
- $commands = parent::drupalPostAJAX($path, $edit, $triggering_element, $ajax_path, $options, $headers, $form_html_id, $ajax_settings);
- $dom = new DOMDocument();
- @$dom->loadHTML($this->drupalGetContent());
- foreach ($commands as $command) {
- if ($command['command'] == 'insert' && isset($command['selector']) && preg_match('/^\#-?[_a-zA-Z]+[_a-zA-Z0-9-]*$/', $command['selector'])) {
- $xpath = new DOMXPath($dom);
- $wrapperNode = $xpath->query('//*[@id="' . substr($command['selector'], 1) . '"]')->item(0);
- if ($wrapperNode) {
- // ajax.js adds an enclosing DIV to work around a Safari bug.
- $newDom = new DOMDocument();
- $newDom->loadHTML('<div>' . $command['data'] . '</div>');
- $newNode = $dom->importNode($newDom->documentElement->firstChild->firstChild, TRUE);
- $method = isset($command['method']) ? $command['method'] : $ajax_settings['method'];
- // The "method" is a jQuery DOM manipulation function. Emulate
- // each one using PHP's DOMNode API.
- switch ($method) {
- case 'replaceWith':
- $wrapperNode->parentNode->replaceChild($newNode, $wrapperNode);
- break;
- case 'append':
- $wrapperNode->appendChild($newNode);
- break;
- case 'prepend':
- // If no firstChild, insertBefore() falls back to
- // appendChild().
- $wrapperNode->insertBefore($newNode, $wrapperNode->firstChild);
- break;
- case 'before':
- $wrapperNode->parentNode->insertBefore($newNode, $wrapperNode);
- break;
- case 'after':
- // If no nextSibling, insertBefore() falls back to
- // appendChild().
- $wrapperNode->parentNode->insertBefore($newNode, $wrapperNode->nextSibling);
- break;
- case 'html':
- foreach ($wrapperNode->childNodes as $childNode) {
- $wrapperNode->removeChild($childNode);
- }
- $wrapperNode->appendChild($newNode);
- break;
- }
- }
- }
- }
- $content = $dom->saveHTML();
- $this->drupalSetContent($content);
- $this->verbose('Page content after ajax submission:<hr />' . $this->content);
- return $commands;
- }
- }
- /**
- * 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',
- );
- }
- /**
- * Test import/enable/disable/remove of Country information files.
- */
- function testCountries() {
- $import_file = 'belgium_56_3.cif';
- $country_name = 'Belgium';
- $country_code = 'BEL';
- $this->drupalLogin($this->adminUser);
- $this->drupalGet('admin/store/settings/countries');
- $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,
- 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.')
- );
- // Have to pick the right one here!
- $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.')
- );
- }
- }
|