'Shipping Quotes', 'description' => 'Test shipping quotes.', 'group' => 'Ubercart', ); } /** * Overrides DrupalWebTestCase::setUp(). */ protected function setUp($modules = array(), $permissions = array()) { $modules = array( 'rules_admin', 'uc_payment', 'uc_payment_pack', 'uc_quote', 'uc_flatrate', ); $permissions = array('administer rules', 'bypass rules access'); parent::setUp($modules, $permissions); module_load_include('inc', 'uc_flatrate', 'uc_flatrate.admin'); $this->drupalLogin($this->adminUser); } /** * Creates a flat rate shipping quote with optional conditions. * * @param array $edit * Data to use to create shipping quote, same format as the values * submitted from the add flatrate method form. * @param bool $condition * If specified, a RulesAnd component defining the conditions to apply * for this method. */ protected function createQuote(array $edit = array(), $condition = FALSE) { $edit += array( 'title' => $this->randomName(8), 'label' => $this->randomName(8), 'base_rate' => mt_rand(1, 10), 'product_rate' => mt_rand(1, 10), ); $form_state = array('values' => $edit); drupal_form_submit('uc_flatrate_admin_method_edit_form', $form_state); $method = db_query("SELECT * FROM {uc_flatrate_methods} WHERE mid = :mid", array(':mid' => $form_state['values']['mid']))->fetchObject(); if ($condition) { $name = 'get_quote_from_flatrate_' . $method->mid; $condition['LABEL'] = $edit['label'] . ' conditions'; $oldconfig = rules_config_load($name); $newconfig = rules_import(array($name => $condition)); $newconfig->id = $oldconfig->id; unset($newconfig->is_new); $newconfig->status = ENTITY_CUSTOM; $newconfig->save(); entity_flush_caches(); } $this->assertTrue($method->base_rate == $edit['base_rate'], 'Flatrate quote was created successfully'); return $method; } /** * Simulates selection of a delivery country on the checkout page. * * @param string $country * The text version of the country name to select, e.g. "Canada" or * "United States". */ protected function selectCountry($country = "Canada") { $dom = new DOMDocument(); $dom->loadHTML($this->content); $parent = $dom->getElementById('edit-panes-delivery-delivery-country'); $options = $parent->getElementsByTagName('option'); for ($i = 0; $i < $options->length; $i++) { if ($options->item($i)->textContent == $country) { $options->item($i)->setAttribute('selected', 'selected'); } else { $options->item($i)->removeAttribute('selected'); } } $this->drupalSetContent($dom->saveHTML()); return $this->drupalPostAjax(NULL, array(), 'panes[delivery][delivery_country]'); } /** * Simulates selection of a quote on the checkout page. * * @param int $n * The index of the quote to select. */ protected function selectQuote($n) { // Get the list of available quotes. $xpath = '//*[@name="panes[quotes][quotes][quote_option]"]'; $elements = $this->xpath($xpath); $vals = array(); foreach ($elements as $element) { $vals[(string) $element['id']] = (string) $element['value']; } // Set the checked attribute of the chosen quote. $dom = new DOMDocument(); $dom->loadHTML($this->content); $i = 0; $selected = ''; foreach ($vals as $id => $value) { if ($i == $n) { $dom->getElementById($id)->setAttribute('checked', 'checked'); $selected = $value; } else { $dom->getElementById($id)->removeAttribute('checked'); } $i++; } $this->drupalSetContent($dom->saveHTML()); // Post the selection via Ajax. $option = array('panes[quotes][quotes][quote_option]' => $selected); return $this->drupalPostAjax(NULL, array(), $option); } /** * Verifies shipping pane is hidden when there are no shippable items. */ public function testNoQuote() { $product = $this->createProduct(array('shippable' => FALSE)); $quote = $this->createQuote(); $this->drupalPost('node/' . $product->nid, array(), t('Add to cart')); $this->drupalPost('cart', array('items[0][qty]' => 1), t('Checkout')); $this->assertNoText('Calculate shipping cost', 'Shipping pane is not present with no shippable item.'); } /** * Tests basic flatrate shipping quote functionality. */ public function testQuote() { // Create product and quotes. $product = $this->createProduct(); $quote1 = $this->createQuote(); $quote2 = $this->createQuote(array(), array( 'LABEL' => 'quote_conditions', 'PLUGIN' => 'and', 'REQUIRES' => array('rules'), 'USES VARIABLES' => array( 'order' => array( 'type' => 'uc_order', 'label' => 'Order', ), ), 'AND' => array(array( 'data_is' => array( 'data' => array('order:delivery-address:country'), 'value' => '840', ), )), )); // Define strings to test for. $qty = mt_rand(2, 100); foreach (array($quote1, $quote2) as $quote) { $quote->amount = uc_currency_format($quote->base_rate + $quote->product_rate * $qty); $quote->option_text = $quote->label . ': ' . $quote->amount; $quote->total = uc_currency_format($product->sell_price * $qty + $quote->base_rate + $quote->product_rate * $qty); } // Add product to cart, update qty, and go to checkout page. $this->drupalPost('node/' . $product->nid, array(), t('Add to cart')); $this->drupalPost('cart', array('items[0][qty]' => $qty), t('Checkout')); $this->assertText($quote1->option_text, 'The default quote option is available'); $this->assertText($quote2->option_text, 'The second quote option is available'); $this->assertText($quote1->total, 'Order total includes the default quote.'); // Select a different quote and ensure the total updates correctly. // Currently, we have to do this by examining the ajax return value // directly (rather than the page contents) because drupalPostAjax() // can only handle replacements via the 'wrapper' property, and the ajax // callback may use a command with a selector. $edit = array('panes[quotes][quotes][quote_option]' => 'flatrate_2---0'); $result = $this->ucPostAjax(NULL, $edit, $edit); $this->assertText($quote2->total, 'The order total includes the selected quote.'); // Switch to a different country and ensure the ajax updates the page correctly. $edit['panes[delivery][delivery_country]'] = 124; $result = $this->ucPostAjax(NULL, $edit, 'panes[delivery][delivery_country]'); $this->assertText($quote1->option_text, 'The default quote is still available after changing the country.'); $this->assertNoText($quote2->option_text, 'The second quote is no longer available after changing the country.'); $this->assertText($quote1->total, 'The total includes the default quote.'); // Proceed to review page and ensure the correct quote is present. $edit['panes[quotes][quotes][quote_option]'] = 'flatrate_1---0'; $edit = $this->populateCheckoutForm($edit); $this->drupalPost(NULL, $edit, t('Review order')); $this->assertRaw(t('Your order is almost complete.')); $this->assertText($quote1->total, 'The total is correct on the order review page.'); // Submit the review. $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) { $order = uc_order_load($order_id); foreach ($order->line_items as $line) { if ($line['type'] == 'shipping') { break; } } // Verify line item is correct. $this->assertEqual($line['type'], 'shipping', t('The shipping line item was saved to the order.')); $this->assertEqual($quote1->amount, uc_currency_format($line['amount']), t('Stored shipping line item has the correct amount.')); // Verify order total is correct on order-view form. $this->drupalGet('admin/store/orders/' . $order_id); $this->assertText($quote1->total, 'The total is correct on the order admin view page.'); // Verify shipping line item is correct on order edit form. $this->drupalGet('admin/store/orders/' . $order_id . '/edit'); $this->assertFieldByName('line_items[' . $line['line_item_id'] . '][title]', $quote1->label, t('Found the correct shipping line item title.')); $this->assertFieldByName('line_items[' . $line['line_item_id'] . '][amount]', substr($quote1->amount, 1), t('Found the correct shipping line item title.')); // Verify that the "get quotes" button works as expected. $result = $this->ucPostAjax('admin/store/orders/' . $order_id . '/edit', array(), array('op' => t('Get shipping quotes'))); $this->assertText($quote1->option_text, 'The default quote is available on the order-edit page.'); $this->assertNoText($quote2->option_text, 'The second quote is not available on the order-edit page.'); } else { $this->fail('No order was created.'); } } }