diff --git a/addons/point_of_sale/static/src/js/tests.js b/addons/point_of_sale/static/src/js/tests.js index 6be47e8ff10..e73a5b8eed8 100644 --- a/addons/point_of_sale/static/src/js/tests.js +++ b/addons/point_of_sale/static/src/js/tests.js @@ -1,90 +1,119 @@ odoo.define('point_of_sale.Tour', function (require) { -"use strict"; + "use strict"; -var Tour = require('web.Tour'); + var Tour = require('web.Tour'); -Tour.register({ - id: 'pos_basic_order', - name: 'Complete a basic order trough the Front-End', - path: '/web#model=pos.config&action=point_of_sale.action_pos_config_kanban', - mode: 'test', - steps: [ - { - title: 'Wait fot the bloody screen to be ready', - wait: 200, - }, - { - title: 'Load the Session', - waitNot: '.oe_loading:visible', - element: 'span:contains("Resume Session"),span:contains("Start Session")', - }, - { - title: 'Loading the Loading Screen', + function add_product_to_order(product_name) { + return [{ + title: 'buy ' + product_name, + element: '.product-list .product-name:contains("' + product_name + '")', + }, { + title: 'the ' + product_name + ' have been added to the order', + waitFor: '.order .product-name:contains("' + product_name + '")', + }]; + } + + function generate_keypad_steps(amount_str, keypad_selector) { + var i, steps = [], current_char; + for (i = 0; i < amount_str.length; ++i) { + current_char = amount_str[i]; + steps.push({ + title: 'press ' + current_char + ' on payment keypad', + element: keypad_selector + ' .input-button:contains("' + current_char + '"):visible' + }); + } + + return steps; + } + + function generate_payment_screen_keypad_steps(amount_str) { + return generate_keypad_steps(amount_str, '.payment-numpad'); + } + + function generate_product_screen_keypad_steps(amount_str) { + return generate_keypad_steps(amount_str, '.numpad'); + } + + function verify_order_total(total_str) { + return [{ + title: 'order total contains ' + total_str, + waitFor: '.order .total .value:contains("' + total_str + '")', + }]; + } + + function goto_payment_screen_and_select_payment_method() { + return [{ + title: "go to payment screen", + element: '.button.pay', + }, { + title: "pay with cash", + element: '.paymentmethod:contains("Cash")', + }]; + } + + function finish_order() { + return [{ + title: "validate the order", + element: '.button.next:visible', + }, { + title: "verify that the order is being sent to the backend", + waitFor: ".js_connecting:visible", + }, { + title: "verify that the order has been succesfully sent to the backend", + waitFor: ".js_connected:visible", + }, { + title: "next order", + element: '.button.next:visible', + }]; + } + + var steps = [{ + title: 'wait for loading screen', waitFor: '.loader' - }, - { - title: 'Waiting for the end of loading...', + }, { + title: 'waiting for loading to finish', waitFor: '.loader:hidden', - }, - { - title: 'Loading The Point of Sale', - waitFor: '.pos', - }, - { - title: 'On va manger des CHIPS!', - element: '.product-list .product-name:contains("250g Lays Pickels")', - }, - { - title: 'The chips have been added to the Order', - waitFor: '.order .product-name:contains("250g Lays Pickels")', - }, - { - title: 'The order total has been updated to the correct value', - wait: 2000, - waitFor: '.order .total .value:contains("1.48 €")', - }, - { - title: "Let's buy more chips", - element: '.product-list .product-name:contains("250g Lays Pickels")', - }, - { - title: "Let's veryify we pay the correct price for two bags of chips", - waitFor: '.order .total .value:contains("2.96 €")', - }, - { - title: "Let's pay with a debit card", - element: ".paypad-button:contains('Bank')", - }, - { - title: "Let's accept the payment", - onload: function(){ - // The test cannot validate or cancel the print() ... so we replace it by a noop !. - window._print = window.print; - window.print = function(){ console.log('Print!') }; - }, - element: ".button .iconlabel:contains('Validate'):visible", - }, - { - title: "Let's finish the order", - element: ".button:not(.disabled) .iconlabel:contains('Next'):visible", - }, - { - onload: function(){ - window.print = window._print; - window._print = undefined; - }, - title: "Let's wait for the order posting", - waitFor: ".oe_status.js_synch .js_connected:visible", - }, - { - title: "Let's close the Point of Sale", - element: ".header-button:contains('Close')", - }, - { - title: "Wait for the backend to ready itself", - element: 'span:contains("Resume Session"),span:contains("Start Session")', - }, - ], -}); + }]; + + steps = steps.concat(add_product_to_order('Peaches')); + steps = steps.concat(verify_order_total('5.10')); + + steps = steps.concat(add_product_to_order('Peaches')); // buy another kg of peaches + steps = steps.concat(verify_order_total('10.20')); + steps = steps.concat(goto_payment_screen_and_select_payment_method()); + steps = steps.concat(generate_payment_screen_keypad_steps("12.20")); + + steps = steps.concat([{ + title: "verify tendered", + waitFor: '.col-tendered:contains("12.20")', + }, { + title: "verify change", + waitFor: '.col-change:contains("2.00")', + }]); + + steps = steps.concat(finish_order()); + + // test opw-672118 orderline subtotal rounding + steps = steps.concat(add_product_to_order('Peaches')); + steps = steps.concat(generate_product_screen_keypad_steps('.999')); // sets orderline qty + steps = steps.concat(verify_order_total('5.09')); + steps = steps.concat(goto_payment_screen_and_select_payment_method()); + steps = steps.concat(generate_payment_screen_keypad_steps("10")); + steps = steps.concat(finish_order()); + + steps = steps.concat([{ + title: "close the Point of Sale frontend", + element: ".header-button", + }, { + title: "confirm closing the frontend", + element: ".header-button", + }]); + + Tour.register({ + id: 'pos_basic_order', + name: 'Complete a basic order trough the Front-End', + path: '/pos/web', + steps: steps, + }); }); diff --git a/addons/point_of_sale/test/test_frontend.py b/addons/point_of_sale/test/test_frontend.py deleted file mode 100644 index cc5aa78b35f..00000000000 --- a/addons/point_of_sale/test/test_frontend.py +++ /dev/null @@ -1,8 +0,0 @@ - -import openerp.tests - -@openerp.tests.common.at_install(False) -@openerp.tests.common.post_install(True) -class TestUi(openerp.tests.HttpCase): - def test_01_pos_basic_order(self): - self.phantom_js("/", "odoo.__DEBUG__.services['web.Tour'].run('pos_basic_order', 'test')", "odoo.__DEBUG__.services['web.Tour'].tours.pos_basic_order", login="admin") diff --git a/addons/point_of_sale/tests/__init__.py b/addons/point_of_sale/tests/__init__.py index 676a99e4a6a..9a85a649161 100644 --- a/addons/point_of_sale/tests/__init__.py +++ b/addons/point_of_sale/tests/__init__.py @@ -1,4 +1,5 @@ # -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. -from . import test_point_of_sale_flow +import test_point_of_sale_flow +import test_frontend diff --git a/addons/point_of_sale/tests/test_frontend.py b/addons/point_of_sale/tests/test_frontend.py new file mode 100644 index 00000000000..0637d471a3a --- /dev/null +++ b/addons/point_of_sale/tests/test_frontend.py @@ -0,0 +1,61 @@ +import odoo.tests +from openerp.api import Environment + +class TestUi(odoo.tests.HttpCase): + def test_01_pos_basic_order(self): + cr = self.registry.cursor() + assert cr == self.registry.test_cr + env = Environment(cr, self.uid, {}) + + journal_obj = env['account.journal'] + account_obj = env['account.account'] + main_company = env.ref('base.main_company') + main_pos_config = env.ref('point_of_sale.pos_config_main') + + account_receivable = account_obj.create({'code': 'X1012', + 'name': 'Account Receivable - Test', + 'user_type_id': env.ref('account.data_account_type_receivable').id, + 'reconcile': True}) + field = self.env['ir.model.fields'].search([('name', '=', 'property_account_receivable_id'), + ('model', '=', 'res.partner'), + ('relation', '=', 'account.account')], limit=1) + env['ir.property'].create({'name': 'property_account_receivable_id', + 'company_id': main_company.id, + 'fields_id': field.id, + 'value': 'account.account,' + str(account_receivable.id)}) + + # set the company currency to USD, otherwise it will assume + # euro's. this will cause issues as the sale journal is in + # USD, because of this all products would have a different + # price + main_company.currency_id = env.ref('base.USD') + + test_sale_journal = journal_obj.create({'name': 'Sale Journal - Test', + 'code': 'TSJ', + 'type': 'sale', + 'company_id': main_company.id}) + + main_pos_config.journal_id = test_sale_journal + main_pos_config.write({'journal_ids': [(0, 0, {'name': 'Cash Journal - Test', + 'code': 'TSC', + 'type': 'cash', + 'company_id': main_company.id, + 'journal_user': True})]}) + + # open a session, the /pos/web controller will redirect to it + main_pos_config.open_session_cb() + + # needed because tests are run before the module is marked as + # installed. In js web will only load qweb coming from modules + # that are returned by the backend in module_boot. Without + # this you end up with js, css but no qweb. + env['ir.module.module'].search([('name', '=', 'point_of_sale')], limit=1).state = 'installed' + cr.release() + + self.phantom_js("/pos/web", + "odoo.__DEBUG__.services['web.Tour'].run('pos_basic_order', 'test')", + "odoo.__DEBUG__.services['web.Tour'].tours.pos_basic_order", + login="admin") + + for order in env['pos.order'].search([]): + self.assertEqual(order.state, 'paid', "Validated order has payment of " + str(order.amount_paid) + " and total of " + str(order.amount_total))