uc_cart.test 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858
  1. <?php
  2. /**
  3. * @file
  4. * Shopping cart and checkout tests.
  5. */
  6. /**
  7. * Tests the cart and checkout functionality.
  8. */
  9. class UbercartCartCheckoutTestCase extends UbercartTestHelper {
  10. public static function getInfo() {
  11. return array(
  12. 'name' => 'Cart and checkout',
  13. 'description' => 'Ensures the cart and checkout process is functioning for both anonymous and authenticated users.',
  14. 'group' => 'Ubercart',
  15. );
  16. }
  17. /**
  18. * Overrides DrupalWebTestCase::setUp().
  19. */
  20. protected function setUp($modules = array(), $permissions = array()) {
  21. $modules = array('uc_payment', 'uc_payment_pack', 'uc_roles');
  22. $permissions = array('administer permissions');
  23. parent::setUp($modules, $permissions);
  24. }
  25. /**
  26. * Creates a new order.
  27. */
  28. function createOrder($fields = array()) {
  29. $order = uc_order_new();
  30. foreach ($fields as $key => $value) {
  31. $order->$key = $value;
  32. }
  33. if (empty($order->primary_email)) {
  34. $order->primary_email = $this->randomString() . '@example.org';
  35. }
  36. if (!isset($fields['products'])) {
  37. $item = clone $this->product;
  38. $item->qty = 1;
  39. $item->price = $item->sell_price;
  40. $item->data = array();
  41. $order->products = array($item);
  42. }
  43. $order->order_total = uc_order_get_total($order, TRUE);
  44. $order->line_items = uc_order_load_line_items($order, TRUE);
  45. uc_order_save($order);
  46. return $order;
  47. }
  48. function testCartAPI() {
  49. // Test the empty cart.
  50. $items = uc_cart_get_contents();
  51. $this->assertEqual($items, array(), 'Cart is an empty array.');
  52. // Add an item to the cart.
  53. uc_cart_add_item($this->product->nid);
  54. $items = uc_cart_get_contents();
  55. $this->assertEqual(count($items), 1, 'Cart contains one item.');
  56. $item = reset($items);
  57. $this->assertEqual($item->nid, $this->product->nid, 'Cart item nid is correct.');
  58. $this->assertEqual($item->qty, 1, 'Cart item quantity is correct.');
  59. // Add more of the same item.
  60. $qty = mt_rand(1, 100);
  61. uc_cart_add_item($this->product->nid, $qty);
  62. $items = uc_cart_get_contents();
  63. $this->assertEqual(count($items), 1, 'Updated cart contains one item.');
  64. $item = reset($items);
  65. $this->assertEqual($item->qty, $qty + 1, 'Updated cart item quantity is correct.');
  66. // Set the quantity and data.
  67. $qty = mt_rand(1, 100);
  68. $item->qty = $qty;
  69. $item->data['updated'] = TRUE;
  70. uc_cart_update_item($item);
  71. $items = uc_cart_get_contents();
  72. $item = reset($items);
  73. $this->assertEqual($item->qty, $qty, 'Set cart item quantity is correct.');
  74. $this->assertTrue($item->data['updated'], 'Set cart item data is correct.');
  75. // Add an item with different data to the cart.
  76. uc_cart_add_item($this->product->nid, 1, array('test' => TRUE));
  77. $items = uc_cart_get_contents();
  78. $this->assertEqual(count($items), 2, 'Updated cart contains two items.');
  79. // Remove the items.
  80. foreach ($items as $item) {
  81. uc_cart_remove_item($item->nid, NULL, $item->data);
  82. }
  83. // @TODO: remove the need for this
  84. uc_cart_get_contents(NULL, 'rebuild');
  85. $items = uc_cart_get_contents();
  86. $this->assertEqual(count($items), 0, 'Cart is empty after removal.');
  87. // Empty the cart.
  88. uc_cart_add_item($this->product->nid);
  89. uc_cart_empty();
  90. $items = uc_cart_get_contents();
  91. $this->assertEqual($items, array(), 'Cart is emptied correctly.');
  92. }
  93. function testCart() {
  94. module_enable(array('uc_cart_entity_test'));
  95. // Test the empty cart.
  96. $this->drupalGet('cart');
  97. $this->assertText('There are no products in your shopping cart.');
  98. // Add an item to the cart.
  99. $this->drupalPost('node/' . $this->product->nid, array(), t('Add to cart'));
  100. $this->assertText($this->product->title . ' added to your shopping cart.');
  101. $this->assertText('hook_uc_cart_item_insert fired');
  102. // Test the cart page.
  103. $this->drupalGet('cart');
  104. $this->assertText($this->product->title, t('The product is in the cart.'));
  105. $this->assertFieldByName('items[0][qty]', 1, t('The product quantity is 1.'));
  106. // Add the item again.
  107. $this->drupalPost('node/' . $this->product->nid, array(), t('Add to cart'));
  108. $this->assertText('Your item(s) have been updated.');
  109. $this->assertText('hook_uc_cart_item_update fired');
  110. // Test the cart page again.
  111. $this->drupalGet('cart');
  112. $this->assertFieldByName('items[0][qty]', 2, t('The product quantity is 2.'));
  113. // Update the quantity.
  114. $qty = mt_rand(3, 100);
  115. $this->drupalPost('cart', array('items[0][qty]' => $qty), t('Update cart'));
  116. $this->assertText('Your cart has been updated.');
  117. $this->assertFieldByName('items[0][qty]', $qty, t('The product quantity was updated.'));
  118. $this->assertText('hook_uc_cart_item_update fired');
  119. // Update the quantity to zero.
  120. $this->drupalPost('cart', array('items[0][qty]' => 0), t('Update cart'));
  121. $this->assertText('Your cart has been updated.');
  122. $this->assertText('There are no products in your shopping cart.');
  123. $this->assertText('hook_uc_cart_item_delete fired');
  124. // Test the remove item button.
  125. $this->drupalPost('node/' . $this->product->nid, array(), t('Add to cart'));
  126. $this->drupalPost('cart', array(), t('Remove'));
  127. $this->assertText($this->product->title . ' removed from your shopping cart.');
  128. $this->assertText('There are no products in your shopping cart.');
  129. $this->assertText('hook_uc_cart_item_delete fired');
  130. }
  131. function testCartMerge() {
  132. // Add an item to the cart as an anonymous user.
  133. $this->drupalLogin($this->customer);
  134. $this->drupalPost('node/' . $this->product->nid, array(), t('Add to cart'));
  135. $this->assertText($this->product->title . ' added to your shopping cart.');
  136. $this->drupalLogout();
  137. // Add an item to the cart as an anonymous user.
  138. $this->drupalPost('node/' . $this->product->nid, array(), t('Add to cart'));
  139. $this->assertText($this->product->title . ' added to your shopping cart.');
  140. // Log in and check the items are merged.
  141. $this->drupalLogin($this->customer);
  142. $this->drupalGet('cart');
  143. $this->assertText($this->product->title, t('The product remains in the cart after logging in.'));
  144. $this->assertFieldByName('items[0][qty]', 2, t('The product quantity is 2.'));
  145. }
  146. function testDeletedCartItem() {
  147. // Add a product to the cart, then delete the node.
  148. $this->drupalPost('node/' . $this->product->nid, array(), t('Add to cart'));
  149. node_delete($this->product->nid);
  150. // Test that the cart is empty.
  151. $this->drupalGet('cart');
  152. $this->assertText('There are no products in your shopping cart.');
  153. $this->assertEqual(uc_cart_get_total_qty(), 0, 'There are no items in the cart.');
  154. }
  155. function testMaximumQuantityRule() {
  156. // Enable the example maximum quantity rule.
  157. $rule = rules_config_load('uc_cart_maximum_product_qty');
  158. $rule->active = TRUE;
  159. $rule->save();
  160. // Try to add more items than allowed to the cart.
  161. $this->drupalPost('node/' . $this->product->nid, array(), t('Add to cart'));
  162. $this->drupalPost('cart', array('items[0][qty]' => 11), t('Update cart'));
  163. // Test the restriction was applied.
  164. $this->assertText('You are only allowed to order a maximum of 10 of ' . $this->product->title . '.');
  165. $this->assertFieldByName('items[0][qty]', 10);
  166. }
  167. function testCheckout() {
  168. // Allow customer to specify username and password, but don't log in after checkout.
  169. $settings = array(
  170. 'uc_cart_new_account_name' => TRUE,
  171. 'uc_cart_new_account_password' => TRUE,
  172. 'uc_new_customer_login' => FALSE,
  173. );
  174. $this->drupalLogin($this->adminUser);
  175. $this->drupalPost('admin/store/settings/checkout', $settings, t('Save configuration'));
  176. $this->drupalLogout();
  177. $new_user = new stdClass();
  178. $new_user->name = $this->randomName(20);
  179. $new_user->pass_raw = $this->randomName(20);
  180. // Test as anonymous user.
  181. $this->drupalPost('node/' . $this->product->nid, array(), t('Add to cart'));
  182. $this->checkout(array(
  183. 'panes[customer][new_account][name]' => $new_user->name,
  184. 'panes[customer][new_account][pass]' => $new_user->pass_raw,
  185. 'panes[customer][new_account][pass_confirm]' => $new_user->pass_raw,
  186. ));
  187. $this->assertRaw('Your order is complete!');
  188. $this->assertText($new_user->name, 'Username is shown on screen.');
  189. $this->assertNoText($new_user->pass_raw, 'Password is not shown on screen.');
  190. // Check that cart is now empty.
  191. $this->drupalGet('cart');
  192. $this->assertText('There are no products in your shopping cart.');
  193. // Test new account email.
  194. $mail = $this->drupalGetMails(array('id' => 'user_register_no_approval_required'));
  195. $mail = array_pop($mail);
  196. $this->assertTrue(strpos($mail['body'], $new_user->name) !== FALSE, 'Mail body contains username.');
  197. // Test invoice email.
  198. $mail = $this->drupalGetMails(array('subject' => 'Your Order at Ubercart'));
  199. $mail = array_pop($mail);
  200. $this->assertTrue(strpos($mail['body'], $new_user->name) !== FALSE, 'Invoice body contains username.');
  201. $this->assertFalse(strpos($mail['body'], $new_user->pass_raw) !== FALSE, 'Mail body does not contain password.');
  202. // Check that the password works.
  203. $this->drupalLogout();
  204. $this->drupalLogin($new_user);
  205. // Test again as authenticated user.
  206. $this->drupalPost('node/' . $this->product->nid, array(), t('Add to cart'));
  207. $this->checkout();
  208. $this->assertRaw('Your order is complete!');
  209. $this->assertRaw('While logged in');
  210. // Test again with generated username and password.
  211. $this->drupalLogout();
  212. $this->drupalPost('node/' . $this->product->nid, array(), t('Add to cart'));
  213. $this->checkout();
  214. $this->assertRaw('Your order is complete!');
  215. // Test new account email.
  216. $mail = $this->drupalGetMails(array('id' => 'user_register_no_approval_required'));
  217. $mail = array_pop($mail);
  218. $new_user = new stdClass();
  219. $new_user->name = $mail['params']['account']->name;
  220. $new_user->pass_raw = $mail['params']['account']->password;
  221. $this->assertTrue(!empty($new_user->name), 'New username is not empty.');
  222. $this->assertTrue(!empty($new_user->pass_raw), 'New password is not empty.');
  223. $this->assertTrue(strpos($mail['body'], $new_user->name) !== FALSE, 'Mail body contains username.');
  224. // Test invoice email.
  225. $mail = $this->drupalGetMails(array('subject' => 'Your Order at Ubercart'));
  226. $mail = array_pop($mail);
  227. $this->assertTrue(strpos($mail['body'], $new_user->name) !== FALSE, 'Invoice body contains username.');
  228. $this->assertTrue(strpos($mail['body'], $new_user->pass_raw) !== FALSE, 'Invoice body contains password.');
  229. // We can check the password now we know it.
  230. $this->assertText($new_user->name, 'Username is shown on screen.');
  231. $this->assertText($new_user->pass_raw, 'Password is shown on screen.');
  232. // Check that the password works.
  233. $this->drupalLogout();
  234. $this->drupalLogin($new_user);
  235. // Test again with an existing email address
  236. $this->drupalLogout();
  237. $this->drupalPost('node/' . $this->product->nid, array(), t('Add to cart'));
  238. $this->checkout(array('panes[customer][primary_email]' => $this->customer->mail));
  239. $this->assertRaw('Your order is complete!');
  240. $this->assertRaw('order has been attached to the account we found');
  241. }
  242. function testCheckoutNewUsername() {
  243. // Configure the checkout for this test.
  244. $this->drupalLogin($this->adminUser);
  245. $settings = array(
  246. // Allow customer to specify username.
  247. 'uc_cart_new_account_name' => TRUE,
  248. // Disable address panes.
  249. 'uc_pane_delivery_enabled' => FALSE,
  250. 'uc_pane_billing_enabled' => FALSE,
  251. );
  252. $this->drupalPost('admin/store/settings/checkout/panes', $settings, t('Save configuration'));
  253. $this->drupalLogout();
  254. // Test with an account that already exists.
  255. $this->drupalPost('node/' . $this->product->nid, array(), t('Add to cart'));
  256. $edit = array(
  257. 'panes[customer][primary_email]' => $this->randomName(8) . '@example.com',
  258. 'panes[customer][new_account][name]' => $this->adminUser->name,
  259. );
  260. $this->drupalPost('cart/checkout', $edit, 'Review order');
  261. $this->assertText('The username ' . $this->adminUser->name . ' is already taken.');
  262. // Let the account be automatically created instead.
  263. $edit = array(
  264. 'panes[customer][primary_email]' => $this->randomName(8) . '@example.com',
  265. 'panes[customer][new_account][name]' => '',
  266. );
  267. $this->drupalPost('cart/checkout', $edit, 'Review order');
  268. $this->drupalPost(NULL, array(), 'Submit order');
  269. $this->assertText('Your order is complete!');
  270. $this->assertText('A new account has been created');
  271. }
  272. function testCheckoutBlockedUser() {
  273. // Block user after checkout.
  274. $settings = array(
  275. 'uc_new_customer_status_active' => FALSE,
  276. );
  277. $this->drupalLogin($this->adminUser);
  278. $this->drupalPost('admin/store/settings/checkout', $settings, t('Save configuration'));
  279. $this->drupalLogout();
  280. // Test as anonymous user.
  281. $this->drupalPost('node/' . $this->product->nid, array(), t('Add to cart'));
  282. $this->checkout();
  283. $this->assertRaw('Your order is complete!');
  284. // Test new account email.
  285. $mail = $this->drupalGetMails(array('id' => 'user_register_pending_approval'));
  286. $this->assertTrue(!empty($mail), 'Blocked user email found.');
  287. $mail = $this->drupalGetMails(array('id' => 'user_register_no_approval_required'));
  288. $this->assertTrue(empty($mail), 'No unblocked user email found.');
  289. }
  290. function testCheckoutLogin() {
  291. // Log in after checkout.
  292. variable_set('uc_new_customer_login', TRUE);
  293. // Test checkout.
  294. $this->drupalGet('node/' . $this->product->nid);
  295. $this->drupalPost(NULL, array(), t('Add to cart'));
  296. $this->assertNotNull($this->session_id, 'Session ID is set.');
  297. $session_id = $this->session_id;
  298. $this->checkout();
  299. $this->assertRaw('Your order is complete!');
  300. $this->assertRaw('you are already logged in');
  301. // Confirm login.
  302. $this->assertNotNull($this->session_id, 'Session ID is set.');
  303. $this->assertNotIdentical($this->session_id, $session_id, 'Session ID has changed.');
  304. $this->drupalGet('<front>');
  305. $this->assertText('My account', 'User is logged in.');
  306. // Check that cart is now empty.
  307. $this->drupalGet('cart');
  308. $this->assertText('There are no products in your shopping cart.');
  309. }
  310. function testCheckoutComplete() {
  311. // Payment notification is received first.
  312. $order_data = array('primary_email' => 'simpletest@ubercart.org');
  313. $order = $this->createOrder($order_data);
  314. uc_payment_enter($order->order_id, 'SimpleTest', $order->order_total);
  315. $output = uc_cart_complete_sale($order);
  316. // Check that a new account was created.
  317. $this->assertTrue(strpos($output['#message'], 'new account has been created') !== FALSE, 'Checkout message mentions new account.');
  318. // 2 e-mails: new account, customer invoice
  319. $mails = $this->drupalGetMails();
  320. $this->assertEqual(count($mails), 2, '2 e-mails were sent.');
  321. variable_del('drupal_test_email_collector');
  322. $password = $mails[0]['params']['account']->password;
  323. $this->assertTrue(!empty($password), 'New password is not empty.');
  324. // In D7, new account emails do not contain the password.
  325. //$this->assertTrue(strpos($mails[0]['body'], $password) !== FALSE, 'Mail body contains password.');
  326. // Different user, sees the checkout page first.
  327. $order_data = array('primary_email' => 'simpletest2@ubercart.org');
  328. $order = $this->createOrder($order_data);
  329. $output = uc_cart_complete_sale($order, TRUE);
  330. uc_payment_enter($order->order_id, 'SimpleTest', $order->order_total);
  331. // 2 e-mails: new account, customer invoice
  332. $mails = $this->drupalGetMails();
  333. $this->assertEqual(count($mails), 2, '2 e-mails were sent.');
  334. variable_del('drupal_test_email_collector');
  335. $password = $mails[0]['params']['account']->password;
  336. $this->assertTrue(!empty($password), 'New password is not empty.');
  337. // In D7, new account emails do not contain the password.
  338. //$this->assertTrue(strpos($mails[0]['body'], $password) !== FALSE, 'Mail body contains password.');
  339. // Same user, new order.
  340. $order = $this->createOrder($order_data);
  341. $output = uc_cart_complete_sale($order, TRUE);
  342. uc_payment_enter($order->order_id, 'SimpleTest', $order->order_total);
  343. // Check that no new account was created.
  344. $this->assertTrue(strpos($output['#message'], 'order has been attached to the account') !== FALSE, 'Checkout message mentions existing account.');
  345. // 1 e-mail: customer invoice
  346. $mails = $this->drupalGetMails();
  347. $this->assertEqual(count($mails), 1, '1 e-mail was sent.');
  348. variable_del('drupal_test_email_collector');
  349. }
  350. function testCheckoutRoleAssignment() {
  351. // Add role assignment to the test product.
  352. $rid = $this->drupalCreateRole(array('access content'));
  353. $this->drupalLogin($this->adminUser);
  354. $this->drupalPost('node/' . $this->product->nid . '/edit/features', array('feature' => 'role'), t('Add'));
  355. $this->drupalPost(NULL, array('uc_roles_role' => $rid), t('Save feature'));
  356. // Process an anonymous, shippable order.
  357. $item = clone $this->product;
  358. $item->qty = 1;
  359. $item->price = $item->sell_price;
  360. $item->data = array('shippable' => TRUE);
  361. $order = $this->createOrder(array(
  362. 'products' => array($item),
  363. ));
  364. uc_payment_enter($order->order_id, 'SimpleTest', $order->order_total);
  365. // Find the order uid.
  366. $uid = db_query("SELECT uid FROM {uc_orders} ORDER BY order_id DESC")->fetchField();
  367. $account = user_load($uid);
  368. $this->assertTrue(isset($account->roles[$rid]), 'New user was granted role.');
  369. $order = uc_order_load($order->order_id);
  370. $this->assertEqual($order->order_status, 'payment_received', 'Shippable order was set to payment received.');
  371. // 3 e-mails: new account, customer invoice, role assignment
  372. $mails = $this->drupalGetMails();
  373. $this->assertEqual(count($mails), 3, '3 e-mails were sent.');
  374. variable_del('drupal_test_email_collector');
  375. // Test again with an existing email address and a non-shippable order.
  376. $item->data = array('shippable' => FALSE);
  377. $order = $this->createOrder(array(
  378. 'primary_email' => $this->customer->mail,
  379. 'products' => array($item),
  380. ));
  381. uc_payment_enter($order->order_id, 'SimpleTest', $order->order_total);
  382. $account = user_load($this->customer->uid);
  383. $this->assertTrue(isset($account->roles[$rid]), 'Existing user was granted role.');
  384. $order = uc_order_load($order->order_id);
  385. $this->assertEqual($order->order_status, 'completed', 'Non-shippable order was set to completed.');
  386. // 2 e-mails: customer invoice, role assignment
  387. $mails = $this->drupalGetMails();
  388. $this->assertEqual(count($mails), 2, '2 e-mails were sent.');
  389. variable_del('drupal_test_email_collector');
  390. }
  391. /**
  392. * Tests that cart orders are marked abandoned after a timeout.
  393. */
  394. function testCartOrderTimeout() {
  395. $this->drupalPost('node/' . $this->product->nid, array(), t('Add to cart'));
  396. $this->drupalPost('cart', array(), 'Checkout');
  397. $this->assertText(
  398. t('Enter your billing address and information here.'),
  399. t('Viewed cart page: Billing pane has been displayed.')
  400. );
  401. // Build the panes.
  402. $zone_id = db_query_range('SELECT zone_id FROM {uc_zones} WHERE zone_country_id = :country ORDER BY rand()', 0, 1, array('country' => variable_get('uc_store_country', 840)))->fetchField();
  403. $oldname = $this->randomName(10);
  404. $edit = array(
  405. 'panes[delivery][delivery_first_name]' => $oldname,
  406. 'panes[delivery][delivery_last_name]' => $this->randomName(10),
  407. 'panes[delivery][delivery_street1]' => $this->randomName(10),
  408. 'panes[delivery][delivery_city]' => $this->randomName(10),
  409. 'panes[delivery][delivery_zone]' => $zone_id,
  410. 'panes[delivery][delivery_postal_code]' => mt_rand(10000, 99999),
  411. 'panes[billing][billing_first_name]' => $this->randomName(10),
  412. 'panes[billing][billing_last_name]' => $this->randomName(10),
  413. 'panes[billing][billing_street1]' => $this->randomName(10),
  414. 'panes[billing][billing_city]' => $this->randomName(10),
  415. 'panes[billing][billing_zone]' => $zone_id,
  416. 'panes[billing][billing_postal_code]' => mt_rand(10000, 99999),
  417. );
  418. // If the email address has not been set, and the user has not logged in,
  419. // add a primary email address.
  420. if (!isset($edit['panes[customer][primary_email]']) && !$this->loggedInUser) {
  421. $edit['panes[customer][primary_email]'] = $this->randomName(8) . '@example.com';
  422. }
  423. // Submit the checkout page.
  424. $this->drupalPost('cart/checkout', $edit, t('Review order'));
  425. $order_id = db_query("SELECT order_id FROM {uc_orders} WHERE delivery_first_name = :name", array(':name' => $oldname))->fetchField();
  426. if ($order_id) {
  427. // Go to a different page, then back to order - make sure order_id is the same.
  428. $this->drupalGet('<front>');
  429. $this->drupalPost('node/' . $this->product->nid, array(), t('Add to cart'));
  430. $this->drupalPost('cart', array(), 'Checkout');
  431. $this->assertRaw($oldname, 'Customer name was unchanged.');
  432. $this->drupalPost('cart/checkout', $edit, t('Review order'));
  433. $new_order_id = db_query("SELECT order_id FROM {uc_orders} WHERE delivery_first_name = :name", array(':name' => $edit['panes[delivery][delivery_first_name]']))->fetchField();
  434. $this->assertEqual($order_id, $new_order_id, 'Original order_id was reused.');
  435. // Jump 10 minutes into the future.
  436. db_update('uc_orders')
  437. ->fields(array(
  438. 'modified' => time() - UC_CART_ORDER_TIMEOUT - 1,
  439. ))
  440. ->condition('order_id', $order_id)
  441. ->execute();
  442. $old_order = uc_order_load($order_id);
  443. // Go to a different page, then back to order - verify that we are using a new order.
  444. $this->drupalGet('<front>');
  445. $this->drupalPost('cart', array(), 'Checkout');
  446. $this->assertNoRaw($oldname, 'Customer name was cleared after timeout.');
  447. $newname = $this->randomName(10);
  448. $edit['panes[delivery][delivery_first_name]'] = $newname;
  449. $this->drupalPost('cart/checkout', $edit, t('Review order'));
  450. $new_order_id = db_query("SELECT order_id FROM {uc_orders} WHERE delivery_first_name = :name", array(':name' => $newname))->fetchField();
  451. $this->assertNotEqual($order_id, $new_order_id, 'New order was created after timeout.');
  452. // Verify that the status of old order is abandoned.
  453. $old_order = uc_order_load($order_id, TRUE);
  454. $this->assertEqual($old_order->order_status, 'abandoned', 'Original order was marked abandoned.');
  455. }
  456. else {
  457. $this->fail('No order was created.');
  458. }
  459. }
  460. function testCustomerInformationCheckoutPane() {
  461. // Log in as a customer and add an item to the cart.
  462. $this->drupalLogin($this->customer);
  463. $this->drupalPost('node/' . $this->product->nid, array(), t('Add to cart'));
  464. $this->drupalPost('cart', array(), 'Checkout');
  465. // Test the customer information pane.
  466. $mail = $this->customer->mail;
  467. $this->assertText('Customer information');
  468. $this->assertText('Order information will be sent to your account e-mail listed below.');
  469. $this->assertText('E-mail address: ' . $mail);
  470. // Use the 'edit' link to change the email address on the account.
  471. $new_mail = $this->randomName() . '@example.com';
  472. $this->clickLink('edit');
  473. $data = array(
  474. 'current_pass' => $this->customer->pass_raw,
  475. 'mail' => $new_mail,
  476. );
  477. $this->drupalPost(NULL, $data, 'Save');
  478. // Test the updated email address.
  479. $this->assertText('Order information will be sent to your account e-mail listed below.');
  480. $this->assertNoText('E-mail address: ' . $mail);
  481. $this->assertText('E-mail address: ' . $new_mail);
  482. }
  483. }
  484. /**
  485. * Tests the cart settings page.
  486. */
  487. class UbercartCartSettingsTestCase extends UbercartTestHelper {
  488. public static function getInfo() {
  489. return array(
  490. 'name' => 'Cart settings',
  491. 'description' => 'Tests the cart settings page.',
  492. 'group' => 'Ubercart',
  493. );
  494. }
  495. function testAddToCartRedirect() {
  496. $this->drupalLogin($this->adminUser);
  497. $this->drupalGet('admin/store/settings/cart');
  498. $this->assertField(
  499. 'uc_add_item_redirect',
  500. t('Add to cart redirect field exists')
  501. );
  502. $redirect = $this->randomName(8);
  503. $this->drupalPost(
  504. 'admin/store/settings/cart',
  505. array('uc_add_item_redirect' => $redirect),
  506. t('Save configuration')
  507. );
  508. $this->drupalPost(
  509. 'node/' . $this->product->nid,
  510. array(),
  511. t('Add to cart')
  512. );
  513. $url_pass = ($this->getUrl() == url($redirect, array('absolute' => TRUE)));
  514. $this->assertTrue(
  515. $url_pass,
  516. t('Add to cart redirect takes user to the correct URL.')
  517. );
  518. $this->drupalPost(
  519. 'admin/store/settings/cart',
  520. array('uc_add_item_redirect' => '<none>'),
  521. t('Save configuration')
  522. );
  523. $this->drupalPost('node/' . $this->product->nid, array(), t('Add to cart'), array('query' => array('test' => 'querystring')));
  524. $url = url('node/' . $this->product->nid, array('absolute' => TRUE, 'query' => array('test' => 'querystring')));
  525. $this->assertTrue($this->getUrl() == $url, 'Add to cart no-redirect works with a query string.');
  526. }
  527. function testMinimumSubtotal() {
  528. $this->drupalLogin($this->adminUser);
  529. $this->drupalGet('admin/store/settings/cart');
  530. $this->assertField(
  531. 'uc_minimum_subtotal',
  532. t('Minimum order subtotal field exists')
  533. );
  534. $minimum_subtotal = mt_rand(2, 9999);
  535. $this->drupalPost(
  536. NULL,
  537. array('uc_minimum_subtotal' => $minimum_subtotal),
  538. t('Save configuration')
  539. );
  540. // Create two products, one below the minimum price, and one above the minimum price.
  541. $product_below_limit = $this->createProduct(array('sell_price' => $minimum_subtotal - 1));
  542. $product_above_limit = $this->createProduct(array('sell_price' => $minimum_subtotal + 1));
  543. $this->drupalLogout();
  544. // Check to see if the lower priced product triggers the minimum price logic.
  545. $this->drupalPost(
  546. 'node/' . $product_below_limit->nid,
  547. array(),
  548. t('Add to cart')
  549. );
  550. $this->drupalPost('cart',
  551. array(),
  552. t('Checkout')
  553. );
  554. $this->assertRaw(
  555. 'The minimum order subtotal for checkout is',
  556. t('Prevented checkout below the minimum order total.')
  557. );
  558. // Add another product to the cart, and verify that we land on the checkout page.
  559. $this->drupalPost(
  560. 'node/' . $product_above_limit->nid,
  561. array(),
  562. t('Add to cart')
  563. );
  564. $this->drupalPost(
  565. 'cart',
  566. array(),
  567. t('Checkout')
  568. );
  569. $this->assertText('Enter your billing address and information here.');
  570. }
  571. function testEmptyCart() {
  572. // Test that the feature is not enabled by default.
  573. $this->drupalPost('node/' . $this->product->nid, array(), 'Add to cart');
  574. $this->assertNoRaw('Empty cart');
  575. // Test the admin settings itself.
  576. $this->drupalLogin($this->adminUser);
  577. $this->drupalGet('admin/store/settings/cart');
  578. $this->assertField('uc_cart_empty_button', 'Empty cart button checkbox found.');
  579. $this->drupalPost(NULL, array('uc_cart_empty_button' => TRUE), 'Save configuration');
  580. // Test the feature itself.
  581. $this->drupalGet('cart');
  582. $this->drupalPost(NULL, array(), 'Empty cart');
  583. $this->assertText('Are you sure you want to empty your shopping cart? ');
  584. $this->drupalPost(NULL, array(), 'Confirm');
  585. $this->assertText('There are no products in your shopping cart.');
  586. }
  587. function testContinueShopping() {
  588. // Continue shopping link should take you back to the product page.
  589. $this->drupalPost(
  590. 'node/' . $this->product->nid,
  591. array(),
  592. t('Add to cart')
  593. );
  594. $this->assertLink(
  595. t('Continue shopping'),
  596. 0,
  597. t('Continue shopping link appears on the page.')
  598. );
  599. $links = $this->xpath('//a[@href="' . url('node/' . $this->product->nid, array('absolute' => FALSE)) . '"]');
  600. $this->assertTrue(
  601. isset($links[0]),
  602. t('Continue shopping link returns to the product page.')
  603. );
  604. $this->drupalLogin($this->adminUser);
  605. $this->drupalGet('admin/store/settings/cart');
  606. $this->assertField(
  607. 'uc_continue_shopping_type',
  608. t('Continue shopping element display field exists')
  609. );
  610. $this->assertField(
  611. 'uc_continue_shopping_url',
  612. t('Default continue shopping link URL field exists')
  613. );
  614. // Test continue shopping button that sends users to a fixed URL.
  615. $settings = array(
  616. 'uc_continue_shopping_type' => 'button',
  617. 'uc_continue_shopping_use_last_url' => FALSE,
  618. 'uc_continue_shopping_url' => $this->randomName(8),
  619. );
  620. $this->drupalPost(
  621. NULL,
  622. $settings,
  623. t('Save configuration')
  624. );
  625. $this->drupalPost(
  626. 'cart',
  627. array(),
  628. t('Continue shopping')
  629. );
  630. $url_pass = ($this->getUrl() == url($settings['uc_continue_shopping_url'],
  631. array('absolute' => TRUE)));
  632. $this->assertTrue(
  633. $url_pass,
  634. t('Continue shopping button takes the user to the correct URL.')
  635. );
  636. }
  637. function testCartBreadcrumb() {
  638. $this->drupalLogin($this->adminUser);
  639. $this->drupalGet('admin/store/settings/cart');
  640. $this->assertField(
  641. 'uc_cart_breadcrumb_text',
  642. t('Custom cart breadcrumb text field exists')
  643. );
  644. $this->assertField(
  645. 'uc_cart_breadcrumb_url',
  646. t('Custom cart breadcrumb URL')
  647. );
  648. $settings = array(
  649. 'uc_cart_breadcrumb_text' => $this->randomName(8),
  650. 'uc_cart_breadcrumb_url' => $this->randomName(7),
  651. );
  652. $this->drupalPost(
  653. NULL,
  654. $settings,
  655. t('Save configuration')
  656. );
  657. $this->drupalPost(
  658. 'node/' . $this->product->nid,
  659. array(),
  660. t('Add to cart')
  661. );
  662. $this->assertLink(
  663. $settings['uc_cart_breadcrumb_text'],
  664. 0,
  665. t('The breadcrumb link text is set correctly.')
  666. );
  667. $links = $this->xpath('//a[@href="' . url($settings['uc_cart_breadcrumb_url']) . '"]');
  668. $this->assertTrue(
  669. isset($links[0]),
  670. t('The breadcrumb link is set correctly.')
  671. );
  672. }
  673. }
  674. /**
  675. * Tests the checkout settings page.
  676. */
  677. class UbercartCheckoutSettingsTestCase extends UbercartTestHelper {
  678. public static function getInfo() {
  679. return array(
  680. 'name' => 'Checkout settings',
  681. 'description' => 'Tests the checkout settings page.',
  682. 'group' => 'Ubercart',
  683. );
  684. }
  685. function testEnableCheckout() {
  686. $this->drupalLogin($this->adminUser);
  687. $this->drupalGet('admin/store/settings/checkout');
  688. $this->assertField(
  689. 'uc_checkout_enabled',
  690. t('Enable checkout field exists')
  691. );
  692. $this->drupalPost(
  693. 'admin/store/settings/checkout',
  694. array('uc_checkout_enabled' => FALSE),
  695. t('Save configuration')
  696. );
  697. $this->drupalPost(
  698. 'node/' . $this->product->nid,
  699. array(),
  700. t('Add to cart')
  701. );
  702. $this->assertNoRaw(t('Checkout'));
  703. $buttons = $this->xpath('//input[@value="' . t('Checkout') . '"]');
  704. $this->assertFalse(
  705. isset($buttons[0]),
  706. t('The checkout button is not shown.')
  707. );
  708. }
  709. function testAnonymousCheckout() {
  710. $this->drupalLogin($this->adminUser);
  711. $this->drupalGet('admin/store/settings/checkout');
  712. $this->assertField(
  713. 'uc_checkout_anonymous',
  714. t('Anonymous checkout field exists')
  715. );
  716. $this->drupalPost(
  717. 'admin/store/settings/checkout',
  718. array('uc_checkout_anonymous' => FALSE),
  719. t('Save configuration')
  720. );
  721. $this->drupalLogout();
  722. $this->drupalPost(
  723. 'node/' . $this->product->nid,
  724. array(),
  725. t('Add to cart')
  726. );
  727. $this->drupalPost(
  728. 'cart',
  729. array(), 'Checkout');
  730. $this->assertNoText(
  731. 'Enter your billing address and information here.',
  732. t('The checkout page is not displayed.')
  733. );
  734. }
  735. }