summaryrefslogtreecommitdiff
path: root/addons/pos_restaurant/static/tests
diff options
context:
space:
mode:
authorstephanchrst <stephanchrst@gmail.com>2022-05-10 21:51:50 +0700
committerstephanchrst <stephanchrst@gmail.com>2022-05-10 21:51:50 +0700
commit3751379f1e9a4c215fb6eb898b4ccc67659b9ace (patch)
treea44932296ef4a9b71d5f010906253d8c53727726 /addons/pos_restaurant/static/tests
parent0a15094050bfde69a06d6eff798e9a8ddf2b8c21 (diff)
initial commit 2
Diffstat (limited to 'addons/pos_restaurant/static/tests')
-rw-r--r--addons/pos_restaurant/static/tests/tours/ControlButtons.tour.js48
-rw-r--r--addons/pos_restaurant/static/tests/tours/FloorScreen.tour.js109
-rw-r--r--addons/pos_restaurant/static/tests/tours/OrderManagementScreen.tour.js124
-rw-r--r--addons/pos_restaurant/static/tests/tours/SplitBillScreen.tour.js52
-rw-r--r--addons/pos_restaurant/static/tests/tours/TicketScreen.tour.js61
-rw-r--r--addons/pos_restaurant/static/tests/tours/TipScreen.tour.js123
-rw-r--r--addons/pos_restaurant/static/tests/tours/helpers/BillScreenTourMethods.js30
-rw-r--r--addons/pos_restaurant/static/tests/tours/helpers/ChromeTourMethods.js33
-rw-r--r--addons/pos_restaurant/static/tests/tours/helpers/FloorScreenTourMethods.js157
-rw-r--r--addons/pos_restaurant/static/tests/tours/helpers/ProductScreenTourMethods.js70
-rw-r--r--addons/pos_restaurant/static/tests/tours/helpers/SplitBillScreenTourMethods.js65
-rw-r--r--addons/pos_restaurant/static/tests/tours/helpers/TextAreaPopupTourMethods.js39
-rw-r--r--addons/pos_restaurant/static/tests/tours/helpers/TextInputPopupTourMethods.js39
-rw-r--r--addons/pos_restaurant/static/tests/tours/helpers/TipScreenTourMethods.js60
-rw-r--r--addons/pos_restaurant/static/tests/tours/pos_restaurant.js108
-rw-r--r--addons/pos_restaurant/static/tests/unit/test_FloorScreen.js197
16 files changed, 1315 insertions, 0 deletions
diff --git a/addons/pos_restaurant/static/tests/tours/ControlButtons.tour.js b/addons/pos_restaurant/static/tests/tours/ControlButtons.tour.js
new file mode 100644
index 00000000..3b6e499a
--- /dev/null
+++ b/addons/pos_restaurant/static/tests/tours/ControlButtons.tour.js
@@ -0,0 +1,48 @@
+odoo.define('pos_restaurant.tour.ControlButtons', function (require) {
+ 'use strict';
+
+ const { TextAreaPopup } = require('pos_restaurant.tour.TextAreaPopupTourMethods');
+ const { Chrome } = require('pos_restaurant.tour.ChromeTourMethods');
+ const { FloorScreen } = require('pos_restaurant.tour.FloorScreenTourMethods');
+ const { ProductScreen } = require('pos_restaurant.tour.ProductScreenTourMethods');
+ const { SplitBillScreen } = require('pos_restaurant.tour.SplitBillScreenTourMethods');
+ const { BillScreen } = require('pos_restaurant.tour.BillScreenTourMethods');
+ const { getSteps, startSteps } = require('point_of_sale.tour.utils');
+ var Tour = require('web_tour.tour');
+
+ // signal to start generating steps
+ // when finished, steps can be taken from getSteps
+ startSteps();
+
+ // Test TransferOrderButton
+ FloorScreen.do.clickTable('T2');
+ ProductScreen.exec.addOrderline('Water', '5', '2', '10.0');
+ ProductScreen.do.clickTransferButton();
+ FloorScreen.do.clickTable('T4');
+ ProductScreen.do.clickOrderline('Water', '5', '2');
+ Chrome.do.backToFloor();
+ FloorScreen.do.clickTable('T2');
+ ProductScreen.check.orderIsEmpty();
+ Chrome.do.backToFloor();
+ FloorScreen.do.clickTable('T4');
+ ProductScreen.do.clickOrderline('Water', '5', '2');
+
+ // Test SplitBillButton
+ ProductScreen.do.clickSplitBillButton();
+ SplitBillScreen.do.clickBack();
+
+ // Test OrderlineNoteButton
+ ProductScreen.do.clickNoteButton();
+ TextAreaPopup.check.isShown();
+ TextAreaPopup.do.inputText('test note');
+ TextAreaPopup.do.clickConfirm();
+ ProductScreen.check.orderlineHasNote('Water', '5', 'test note');
+ ProductScreen.exec.addOrderline('Water', '8', '1', '8.0');
+
+ // Test PrintBillButton
+ ProductScreen.do.clickPrintBillButton();
+ BillScreen.check.isShown();
+ BillScreen.do.clickBack();
+
+ Tour.register('ControlButtonsTour', { test: true, url: '/pos/ui' }, getSteps());
+});
diff --git a/addons/pos_restaurant/static/tests/tours/FloorScreen.tour.js b/addons/pos_restaurant/static/tests/tours/FloorScreen.tour.js
new file mode 100644
index 00000000..6c542e66
--- /dev/null
+++ b/addons/pos_restaurant/static/tests/tours/FloorScreen.tour.js
@@ -0,0 +1,109 @@
+odoo.define('pos_restaurant.tour.FloorScreen', function (require) {
+ 'use strict';
+
+ const { Chrome } = require('pos_restaurant.tour.ChromeTourMethods');
+ const { FloorScreen } = require('pos_restaurant.tour.FloorScreenTourMethods');
+ const { TextInputPopup } = require('pos_restaurant.tour.TextInputPopupTourMethods');
+ const { NumberPopup } = require('point_of_sale.tour.NumberPopupTourMethods');
+ const { ProductScreen } = require('pos_restaurant.tour.ProductScreenTourMethods');
+ const { getSteps, startSteps } = require('point_of_sale.tour.utils');
+ var Tour = require('web_tour.tour');
+
+ // signal to start generating steps
+ // when finished, steps can be taken from getSteps
+ startSteps();
+
+ // check floors if they contain their corresponding tables
+ FloorScreen.check.selectedFloorIs('Main Floor');
+ FloorScreen.check.hasTable('T2');
+ FloorScreen.check.hasTable('T4');
+ FloorScreen.check.hasTable('T5');
+ FloorScreen.do.clickFloor('Second Floor');
+ FloorScreen.check.hasTable('T3');
+ FloorScreen.check.hasTable('T1');
+
+ // clicking table in active mode does not open product screen
+ // instead, table is selected
+ FloorScreen.do.clickEdit();
+ FloorScreen.check.editModeIsActive(true);
+ FloorScreen.do.clickTable('T3');
+ FloorScreen.check.selectedTableIs('T3');
+ FloorScreen.do.clickTable('T1');
+ FloorScreen.check.selectedTableIs('T1');
+
+ // switching floor in edit mode deactivates edit mode
+ FloorScreen.do.clickFloor('Main Floor');
+ FloorScreen.check.editModeIsActive(false);
+ FloorScreen.do.clickEdit();
+ FloorScreen.check.editModeIsActive(true);
+
+ // test add table
+ FloorScreen.do.clickAddTable();
+ FloorScreen.check.selectedTableIs('T1');
+ FloorScreen.do.clickRename();
+ TextInputPopup.check.isShown();
+ TextInputPopup.do.inputText('T100');
+ TextInputPopup.do.clickConfirm();
+ FloorScreen.check.selectedTableIs('T100');
+
+ // test duplicate table
+ FloorScreen.do.clickDuplicate();
+ // new table is already named T101
+ FloorScreen.check.selectedTableIs('T101');
+ FloorScreen.do.clickRename();
+ TextInputPopup.check.isShown();
+ TextInputPopup.do.inputText('T1111');
+ TextInputPopup.do.clickConfirm();
+ FloorScreen.check.selectedTableIs('T1111');
+
+ // switch floor, switch back and check if
+ // the new tables are still there
+ FloorScreen.do.clickFloor('Second Floor');
+ FloorScreen.check.editModeIsActive(false);
+ FloorScreen.check.hasTable('T3');
+ FloorScreen.check.hasTable('T1');
+
+ FloorScreen.do.clickFloor('Main Floor');
+ FloorScreen.check.hasTable('T2');
+ FloorScreen.check.hasTable('T4');
+ FloorScreen.check.hasTable('T5');
+ FloorScreen.check.hasTable('T100');
+ FloorScreen.check.hasTable('T1111');
+
+ // test delete table
+ FloorScreen.do.clickEdit();
+ FloorScreen.check.editModeIsActive(true);
+ FloorScreen.do.clickTable('T2');
+ FloorScreen.check.selectedTableIs('T2');
+ FloorScreen.do.clickTrash();
+ Chrome.do.confirmPopup();
+
+ // change number of seats
+ FloorScreen.do.clickTable('T4');
+ FloorScreen.check.selectedTableIs('T4');
+ FloorScreen.do.clickSeats();
+ NumberPopup.do.pressNumpad('Backspace 9');
+ NumberPopup.check.inputShownIs('9');
+ NumberPopup.do.clickConfirm();
+ FloorScreen.check.tableSeatIs('T4', '9');
+
+ // change shape
+ FloorScreen.do.changeShapeTo('round');
+
+ // Opening product screen in main floor should go back to main floor
+ FloorScreen.do.clickEdit();
+ FloorScreen.check.editModeIsActive(false);
+ FloorScreen.check.tableIsNotSelected('T4');
+ FloorScreen.do.clickTable('T4');
+ ProductScreen.check.isShown();
+ Chrome.check.backToFloorTextIs('Main Floor', 'T4');
+ Chrome.do.backToFloor();
+
+ // Opening product screen in second floor should go back to second floor
+ FloorScreen.do.clickFloor('Second Floor');
+ FloorScreen.check.hasTable('T3');
+ FloorScreen.do.clickTable('T3');
+ Chrome.check.backToFloorTextIs('Second Floor', 'T3');
+
+ Tour.register('FloorScreenTour', { test: true, url: '/pos/ui' }, getSteps());
+});
diff --git a/addons/pos_restaurant/static/tests/tours/OrderManagementScreen.tour.js b/addons/pos_restaurant/static/tests/tours/OrderManagementScreen.tour.js
new file mode 100644
index 00000000..bc64f368
--- /dev/null
+++ b/addons/pos_restaurant/static/tests/tours/OrderManagementScreen.tour.js
@@ -0,0 +1,124 @@
+odoo.define('pos_restaurant.tour.OrderManagementScreen', function (require) {
+ 'use strict';
+
+ // This tour tests the integration of OrderManagementScreen
+ // to some pos_restaurant features.
+
+ const { makeFullOrder } = require('point_of_sale.tour.CompositeTourMethods');
+ const { Chrome } = require('pos_restaurant.tour.ChromeTourMethods');
+ const {
+ OrderManagementScreen,
+ } = require('point_of_sale.tour.OrderManagementScreenTourMethods');
+ const { FloorScreen } = require('pos_restaurant.tour.FloorScreenTourMethods');
+ const { ProductScreen } = require('pos_restaurant.tour.ProductScreenTourMethods');
+ const { TicketScreen } = require('point_of_sale.tour.TicketScreenTourMethods');
+ const { getSteps, startSteps } = require('point_of_sale.tour.utils');
+ var Tour = require('web_tour.tour');
+
+ // signal to start generating steps
+ // when finished, steps can be taken from getSteps
+ startSteps();
+
+ FloorScreen.do.clickTable('T2');
+
+ // make one order and check if it can be seen from the management screen.
+ makeFullOrder({ orderlist: [['Minute Maid', '5', '6']], payment: ['Cash', '30'] });
+ Chrome.do.clickOrderManagementButton();
+ OrderManagementScreen.check.isShown();
+ OrderManagementScreen.check.orderlistHas({ orderName: '-0001', total: '30' });
+
+ // go back to create multiple unpaid orders
+ OrderManagementScreen.do.clickBack();
+
+ // create 2 unpaid orders on T2 (orders 0002 and 0003)
+ FloorScreen.do.clickTable('T2');
+ ProductScreen.exec.addMultiOrderlines(
+ ['Coca-Cola', '1', '2'],
+ ['Water', '3', '4'],
+ ['Minute Maid', '5', '6']
+ );
+ Chrome.do.clickTicketButton();
+ TicketScreen.do.clickNewTicket();
+ ProductScreen.exec.addMultiOrderlines(['Coca-Cola', '1', '2'], ['Minute Maid', '5', '6']);
+ Chrome.do.backToFloor();
+
+ // create 2 unpaid orders on T5 (orders 0004 and 0005)
+ FloorScreen.do.clickTable('T5');
+ ProductScreen.exec.addMultiOrderlines(
+ ['Coca-Cola', '7', '8'],
+ ['Water', '9', '10'],
+ ['Minute Maid', '11', '12']
+ );
+ Chrome.do.clickTicketButton();
+ TicketScreen.do.clickNewTicket();
+ ProductScreen.exec.addMultiOrderlines(['Coca-Cola', '13', '14'], ['Minute Maid', '15', '16']);
+ Chrome.do.backToFloor();
+
+ // check that the unpaid orders are listed in the management screen
+ Chrome.do.clickOrderManagementButton();
+ OrderManagementScreen.check.isShown();
+ OrderManagementScreen.check.orderlistHas({ orderName: '-0002', total: '44.0' });
+ OrderManagementScreen.check.orderlistHas({ orderName: '-0003', total: '32.0' });
+ OrderManagementScreen.check.orderlistHas({ orderName: '-0004', total: '278.0' });
+ OrderManagementScreen.check.orderlistHas({ orderName: '-0005', total: '422.0' });
+
+ // select order 0003 and check if it is really in T2
+ OrderManagementScreen.do.clickOrder('-0003');
+ ProductScreen.check.isShown();
+ ProductScreen.check.totalAmountIs('32');
+ Chrome.check.backToFloorTextIs('Main Floor', 'T2');
+
+ Chrome.do.clickOrderManagementButton();
+
+ // select order 0005 and check it it is really in T5
+ OrderManagementScreen.check.isShown();
+ OrderManagementScreen.do.clickOrder('-0005');
+ ProductScreen.check.totalAmountIs('422');
+ Chrome.check.backToFloorTextIs('Main Floor', 'T5');
+
+ // go back to floor screen and start order management from there
+ Chrome.do.backToFloor();
+ FloorScreen.check.selectedFloorIs('Main Floor');
+ Chrome.do.clickOrderManagementButton();
+ OrderManagementScreen.check.isShown();
+
+ // select order 0002 and check if it is really in T2
+ OrderManagementScreen.do.clickOrder('-0002');
+ ProductScreen.check.isShown();
+ ProductScreen.check.totalAmountIs('44');
+ Chrome.check.backToFloorTextIs('Main Floor', 'T2');
+
+ Chrome.do.clickOrderManagementButton();
+ OrderManagementScreen.check.isShown();
+
+ // select order 0004 and check if it is really in T5
+ OrderManagementScreen.do.clickOrder('-0004');
+ ProductScreen.check.isShown();
+ ProductScreen.check.totalAmountIs('278');
+ Chrome.check.backToFloorTextIs('Main Floor', 'T5');
+
+ // transfer order 0004 to T2
+ ProductScreen.do.clickTransferButton();
+ FloorScreen.do.clickTable('T2');
+ ProductScreen.check.isShown();
+
+ Chrome.do.clickOrderManagementButton();
+ OrderManagementScreen.check.isShown();
+
+ // select order 0004 and check if it is now in T2
+ OrderManagementScreen.do.clickOrder('-0004', ['table', 'T2']);
+ ProductScreen.check.isShown();
+ ProductScreen.check.totalAmountIs('278');
+ Chrome.check.backToFloorTextIs('Main Floor', 'T2');
+
+ Chrome.do.clickOrderManagementButton();
+ OrderManagementScreen.check.isShown();
+
+ // finally, select order 0002
+ OrderManagementScreen.do.clickOrder('-0002');
+ ProductScreen.check.isShown();
+ ProductScreen.check.totalAmountIs('44');
+ Chrome.check.backToFloorTextIs('Main Floor', 'T2');
+
+ Tour.register('PosResOrderManagementScreenTour', { test: true, url: '/pos/ui' }, getSteps());
+});
diff --git a/addons/pos_restaurant/static/tests/tours/SplitBillScreen.tour.js b/addons/pos_restaurant/static/tests/tours/SplitBillScreen.tour.js
new file mode 100644
index 00000000..8b9c0f7d
--- /dev/null
+++ b/addons/pos_restaurant/static/tests/tours/SplitBillScreen.tour.js
@@ -0,0 +1,52 @@
+odoo.define('pos_restaurant.tour.SplitBillScreen', function (require) {
+ 'use strict';
+
+ const { PaymentScreen } = require('point_of_sale.tour.PaymentScreenTourMethods');
+ const { Chrome } = require('pos_restaurant.tour.ChromeTourMethods');
+ const { FloorScreen } = require('pos_restaurant.tour.FloorScreenTourMethods');
+ const { ProductScreen } = require('pos_restaurant.tour.ProductScreenTourMethods');
+ const { SplitBillScreen } = require('pos_restaurant.tour.SplitBillScreenTourMethods');
+ const { TicketScreen } = require('point_of_sale.tour.TicketScreenTourMethods');
+ const { getSteps, startSteps } = require('point_of_sale.tour.utils');
+ var Tour = require('web_tour.tour');
+
+ // signal to start generating steps
+ // when finished, steps can be taken from getSteps
+ startSteps();
+
+ FloorScreen.do.clickTable('T2');
+ ProductScreen.exec.addOrderline('Water', '5', '2', '10.0');
+ ProductScreen.exec.addOrderline('Minute Maid', '3', '2', '6.0');
+ ProductScreen.exec.addOrderline('Coca-Cola', '1', '2', '2.0');
+ ProductScreen.do.clickSplitBillButton();
+
+ // Check if the screen contains all the orderlines
+ SplitBillScreen.check.orderlineHas('Water', '5', '0');
+ SplitBillScreen.check.orderlineHas('Minute Maid', '3', '0');
+ SplitBillScreen.check.orderlineHas('Coca-Cola', '1', '0');
+
+ // split 3 water and 1 coca-cola
+ SplitBillScreen.do.clickOrderline('Water');
+ SplitBillScreen.check.orderlineHas('Water', '5', '1');
+ SplitBillScreen.do.clickOrderline('Water');
+ SplitBillScreen.do.clickOrderline('Water');
+ SplitBillScreen.check.orderlineHas('Water', '5', '3');
+ SplitBillScreen.check.subtotalIs('6.0')
+ SplitBillScreen.do.clickOrderline('Coca-Cola');
+ SplitBillScreen.check.orderlineHas('Coca-Cola', '1', '1');
+ SplitBillScreen.check.subtotalIs('8.0')
+
+ // click pay to split, go back to check the lines
+ SplitBillScreen.do.clickPay();
+ PaymentScreen.do.clickBack();
+ ProductScreen.do.clickOrderline('Water', '3.0')
+ ProductScreen.do.clickOrderline('Coca-Cola', '1.0')
+
+ // go back to the original order and see if the order is changed
+ Chrome.do.clickTicketButton();
+ TicketScreen.do.selectOrder('-0001');
+ ProductScreen.do.clickOrderline('Water', '2.0')
+ ProductScreen.do.clickOrderline('Minute Maid', '3.0')
+
+ Tour.register('SplitBillScreenTour', { test: true, url: '/pos/ui' }, getSteps());
+});
diff --git a/addons/pos_restaurant/static/tests/tours/TicketScreen.tour.js b/addons/pos_restaurant/static/tests/tours/TicketScreen.tour.js
new file mode 100644
index 00000000..278bbfc5
--- /dev/null
+++ b/addons/pos_restaurant/static/tests/tours/TicketScreen.tour.js
@@ -0,0 +1,61 @@
+odoo.define('pos_restaurant.tour.TicketScreen', function (require) {
+ 'use strict';
+
+ const { ProductScreen } = require('point_of_sale.tour.ProductScreenTourMethods');
+ const { FloorScreen } = require('pos_restaurant.tour.FloorScreenTourMethods');
+ const { TicketScreen } = require('point_of_sale.tour.TicketScreenTourMethods');
+ const { Chrome } = require('pos_restaurant.tour.ChromeTourMethods');
+ const { getSteps, startSteps } = require('point_of_sale.tour.utils');
+ var Tour = require('web_tour.tour');
+
+ startSteps();
+
+ // New Ticket button should not be in the ticket screen if no table is selected.
+ Chrome.do.clickTicketButton();
+ TicketScreen.check.noNewTicketButton();
+ TicketScreen.do.clickDiscard();
+
+ // Deleting the last order in the table brings back to floorscreen
+ FloorScreen.do.clickTable('T4');
+ ProductScreen.check.isShown();
+ Chrome.do.clickTicketButton();
+ TicketScreen.check.nthRowContains(2, '-0001');
+ TicketScreen.do.deleteOrder('-0001');
+ FloorScreen.check.isShown();
+
+ // Create 2 items in a table. From floorscreen, delete 1 item. Then select the other item.
+ // Correct order and screen should be displayed and the BackToFloorButton is shown.
+ FloorScreen.do.clickTable('T2');
+ ProductScreen.exec.addOrderline('Minute Maid', '1', '2');
+ ProductScreen.check.totalAmountIs('2.0');
+ Chrome.do.clickTicketButton();
+ TicketScreen.do.clickNewTicket();
+ ProductScreen.exec.addOrderline('Coca-Cola', '2', '2');
+ ProductScreen.check.totalAmountIs('4.0');
+ Chrome.do.backToFloor();
+ FloorScreen.check.orderCountSyncedInTableIs('T2', '2');
+ Chrome.do.clickTicketButton();
+ TicketScreen.do.deleteOrder('-0003');
+ Chrome.do.confirmPopup();
+ TicketScreen.do.selectOrder('-0002');
+ ProductScreen.check.totalAmountIs('2.0');
+ Chrome.check.backToFloorTextIs('Main Floor', 'T2');
+ Chrome.do.backToFloor();
+
+ // Make sure that order is deleted properly.
+ FloorScreen.do.clickTable('T5');
+ ProductScreen.exec.addOrderline('Minute Maid', '1', '3');
+ ProductScreen.check.totalAmountIs('3.0');
+ Chrome.do.backToFloor();
+ FloorScreen.check.orderCountSyncedInTableIs('T5', '1');
+ Chrome.do.clickTicketButton();
+ TicketScreen.do.deleteOrder('-0004');
+ Chrome.do.confirmPopup();
+ TicketScreen.do.clickDiscard();
+ FloorScreen.check.isShown();
+ FloorScreen.check.orderCountSyncedInTableIs('T5', '0');
+ FloorScreen.do.clickTable('T5');
+ ProductScreen.check.orderIsEmpty();
+
+ Tour.register('PosResTicketScreenTour', { test: true, url: '/pos/ui' }, getSteps());
+});
diff --git a/addons/pos_restaurant/static/tests/tours/TipScreen.tour.js b/addons/pos_restaurant/static/tests/tours/TipScreen.tour.js
new file mode 100644
index 00000000..430c7a2f
--- /dev/null
+++ b/addons/pos_restaurant/static/tests/tours/TipScreen.tour.js
@@ -0,0 +1,123 @@
+odoo.define('pos_restaurant.tour.TipScreen', function (require) {
+ 'use strict';
+
+ const { ProductScreen } = require('point_of_sale.tour.ProductScreenTourMethods');
+ const { PaymentScreen } = require('point_of_sale.tour.PaymentScreenTourMethods');
+ const { ReceiptScreen } = require('point_of_sale.tour.ReceiptScreenTourMethods');
+ const { FloorScreen } = require('pos_restaurant.tour.FloorScreenTourMethods');
+ const { TicketScreen } = require('point_of_sale.tour.TicketScreenTourMethods');
+ const { TipScreen } = require('pos_restaurant.tour.TipScreenTourMethods');
+ const { NumberPopup } = require('point_of_sale.tour.NumberPopupTourMethods');
+ const { Chrome } = require('pos_restaurant.tour.ChromeTourMethods');
+ const { getSteps, startSteps } = require('point_of_sale.tour.utils');
+ var Tour = require('web_tour.tour');
+
+ startSteps();
+
+ // Create order that is synced when draft.
+ // order 1
+ FloorScreen.do.clickTable('T2');
+ ProductScreen.exec.addOrderline('Minute Maid', '1', '2');
+ ProductScreen.check.totalAmountIs('2.0');
+ Chrome.do.backToFloor();
+ FloorScreen.check.orderCountSyncedInTableIs('T2', '1');
+ FloorScreen.do.clickTable('T2');
+ ProductScreen.check.totalAmountIs('2.0');
+ ProductScreen.do.clickPayButton();
+ PaymentScreen.do.clickPaymentMethod('Bank');
+ PaymentScreen.do.clickValidate();
+ TipScreen.check.isShown();
+ Chrome.do.clickTicketButton();
+ TicketScreen.do.clickNewTicket();
+ // order 2
+ ProductScreen.exec.addOrderline('Coca-Cola', '2', '2');
+ ProductScreen.check.totalAmountIs('4.0');
+ Chrome.do.backToFloor();
+ FloorScreen.check.orderCountSyncedInTableIs('T2', '1');
+ Chrome.do.clickTicketButton();
+ TicketScreen.check.nthRowContains('2', 'Tipping');
+ TicketScreen.do.clickDiscard();
+
+ // Create without syncing the draft.
+ // order 3
+ FloorScreen.do.clickTable('T5');
+ ProductScreen.exec.addOrderline('Minute Maid', '3', '2');
+ ProductScreen.check.totalAmountIs('6.0');
+ ProductScreen.do.clickPayButton();
+ PaymentScreen.do.clickPaymentMethod('Bank');
+ PaymentScreen.do.clickValidate();
+ TipScreen.check.isShown();
+ Chrome.do.clickTicketButton();
+ TicketScreen.do.clickNewTicket();
+ // order 4
+ ProductScreen.exec.addOrderline('Coca-Cola', '4', '2');
+ ProductScreen.check.totalAmountIs('8.0');
+ Chrome.do.backToFloor();
+ FloorScreen.check.orderCountSyncedInTableIs('T5', '1');
+ Chrome.do.clickTicketButton();
+ TicketScreen.check.nthRowContains('4', 'Tipping');
+
+ // Tip 20% on order1
+ TicketScreen.do.selectOrder('-0001');
+ TipScreen.check.isShown();
+ TipScreen.check.totalAmountIs('2.0');
+ TipScreen.check.percentAmountIs('15%', '0.30');
+ TipScreen.check.percentAmountIs('20%', '0.40');
+ TipScreen.check.percentAmountIs('25%', '0.50');
+ TipScreen.do.clickPercentTip('20%');
+ TipScreen.check.inputAmountIs('0.40')
+ Chrome.do.backToFloor();
+ FloorScreen.check.isShown();
+ Chrome.do.clickTicketButton();
+
+ // Tip 25% on order3
+ TicketScreen.do.selectOrder('-0003');
+ TipScreen.check.isShown();
+ TipScreen.check.totalAmountIs('6.0');
+ TipScreen.check.percentAmountIs('15%', '0.90');
+ TipScreen.check.percentAmountIs('20%', '1.20');
+ TipScreen.check.percentAmountIs('25%', '1.50');
+ TipScreen.do.clickPercentTip('25%');
+ TipScreen.check.inputAmountIs('1.50');
+ Chrome.do.backToFloor();
+ FloorScreen.check.isShown();
+ Chrome.do.clickTicketButton();
+
+ // finalize order 4 then tip custom amount
+ TicketScreen.do.selectOrder('-0004');
+ ProductScreen.check.totalAmountIs('8.0');
+ ProductScreen.do.clickPayButton();
+ PaymentScreen.do.clickPaymentMethod('Bank');
+ PaymentScreen.do.clickValidate();
+ TipScreen.check.isShown();
+ TipScreen.check.totalAmountIs('8.0');
+ TipScreen.check.percentAmountIs('15%', '1.20');
+ TipScreen.check.percentAmountIs('20%', '1.60');
+ TipScreen.check.percentAmountIs('25%', '2.00');
+ TipScreen.do.setCustomTip('1.00');
+ TipScreen.check.inputAmountIs('1.00')
+ Chrome.do.backToFloor();
+ FloorScreen.check.isShown();
+
+ // settle tips here
+ Chrome.do.clickTicketButton();
+ TicketScreen.do.selectFilter('Tipping');
+ TicketScreen.do.settleTips();
+ TicketScreen.do.selectFilter('All Tickets');
+ TicketScreen.check.nthRowContains(2, 'Ongoing');
+
+ // tip order2 during payment
+ // tip screen should not show after validating payment screen
+ TicketScreen.do.selectOrder('-0002');
+ ProductScreen.do.clickPayButton();
+ PaymentScreen.do.clickTipButton();
+ NumberPopup.check.isShown();
+ NumberPopup.do.pressNumpad('1');
+ NumberPopup.check.inputShownIs('1');
+ NumberPopup.do.clickConfirm();
+ PaymentScreen.do.clickPaymentMethod('Cash');
+ PaymentScreen.do.clickValidate();
+ ReceiptScreen.check.isShown();
+
+ Tour.register('PosResTipScreenTour', { test: true, url: '/pos/ui' }, getSteps());
+});
diff --git a/addons/pos_restaurant/static/tests/tours/helpers/BillScreenTourMethods.js b/addons/pos_restaurant/static/tests/tours/helpers/BillScreenTourMethods.js
new file mode 100644
index 00000000..9f831367
--- /dev/null
+++ b/addons/pos_restaurant/static/tests/tours/helpers/BillScreenTourMethods.js
@@ -0,0 +1,30 @@
+odoo.define('pos_restaurant.tour.BillScreenTourMethods', function (require) {
+ 'use strict';
+
+ const { createTourMethods } = require('point_of_sale.tour.utils');
+
+ class Do {
+ clickBack() {
+ return [
+ {
+ content: `go back`,
+ trigger: `.receipt-screen .back`,
+ },
+ ];
+ }
+ }
+
+ class Check {
+ isShown() {
+ return [
+ {
+ content: 'Bill screen is shown',
+ trigger: '.receipt-screen h1:contains("Bill Printing")',
+ run: () => {},
+ },
+ ];
+ }
+ }
+
+ return createTourMethods('BillScreen', Do, Check);
+});
diff --git a/addons/pos_restaurant/static/tests/tours/helpers/ChromeTourMethods.js b/addons/pos_restaurant/static/tests/tours/helpers/ChromeTourMethods.js
new file mode 100644
index 00000000..d60e3986
--- /dev/null
+++ b/addons/pos_restaurant/static/tests/tours/helpers/ChromeTourMethods.js
@@ -0,0 +1,33 @@
+odoo.define('pos_restaurant.tour.ChromeTourMethods', function (require) {
+ 'use strict';
+
+ const { createTourMethods } = require('point_of_sale.tour.utils');
+ const { Do } = require('point_of_sale.tour.ChromeTourMethods');
+
+ class DoExt extends Do {
+ backToFloor() {
+ return [
+ {
+ content: 'back to floor',
+ trigger: '.floor-button',
+ },
+ ];
+ }
+ }
+
+ class Check {
+ backToFloorTextIs(floor, table) {
+ return [
+ {
+ content: `back to floor text is '${floor} ( ${table} )'`,
+ trigger: `.floor-button span:contains("${floor}") ~ .table-name:contains("${table}")`,
+ run: () => {},
+ },
+ ];
+ }
+ }
+
+ class Execute {}
+
+ return createTourMethods('Chrome', DoExt, Check, Execute);
+});
diff --git a/addons/pos_restaurant/static/tests/tours/helpers/FloorScreenTourMethods.js b/addons/pos_restaurant/static/tests/tours/helpers/FloorScreenTourMethods.js
new file mode 100644
index 00000000..733fd26d
--- /dev/null
+++ b/addons/pos_restaurant/static/tests/tours/helpers/FloorScreenTourMethods.js
@@ -0,0 +1,157 @@
+odoo.define('pos_restaurant.tour.FloorScreenTourMethods', function (require) {
+ 'use strict';
+
+ const { createTourMethods } = require('point_of_sale.tour.utils');
+
+ class Do {
+ clickTable(name) {
+ return [
+ {
+ content: `click table '${name}'`,
+ trigger: `.floor-map .table .label:contains("${name}")`,
+ },
+ ];
+ }
+ clickFloor(name) {
+ return [
+ {
+ content: `click '${name}' floor`,
+ trigger: `.floor-selector .button-floor:contains("${name}")`,
+ },
+ ];
+ }
+ clickEdit() {
+ return [
+ {
+ content: `click edit button`,
+ trigger: `.floor-map .edit-button`,
+ },
+ ];
+ }
+ clickAddTable() {
+ return [
+ {
+ content: 'add table',
+ trigger: `.floor-map .edit-button i[aria-label=Add]`,
+ },
+ ];
+ }
+ clickDuplicate() {
+ return [
+ {
+ content: 'duplicate table',
+ trigger: `.floor-map .edit-button i[aria-label=Duplicate]`,
+ },
+ ];
+ }
+ clickRename() {
+ return [
+ {
+ content: 'rename table',
+ trigger: `.floor-map .edit-button i[aria-label=Rename]`,
+ },
+ ];
+ }
+ clickSeats() {
+ return [
+ {
+ content: 'change number of seats',
+ trigger: `.floor-map .edit-button i[aria-label=Seats]`,
+ },
+ ];
+ }
+ clickTrash() {
+ return [
+ {
+ content: 'trash table',
+ trigger: `.floor-map .edit-button.trash`,
+ },
+ ];
+ }
+ changeShapeTo(shape) {
+ return [
+ {
+ content: `change shape to '${shape}'`,
+ trigger: `.edit-button .button-option${shape === 'round' ? '.square' : '.round'}`,
+ },
+ ];
+ }
+ }
+
+ class Check {
+ selectedFloorIs(name) {
+ return [
+ {
+ content: `selected floor is '${name}'`,
+ trigger: `.floor-selector .button-floor.active:contains("${name}")`,
+ run: () => {},
+ },
+ ];
+ }
+ selectedTableIs(name) {
+ return [
+ {
+ content: `selected table is '${name}'`,
+ trigger: `.floor-map .table.selected .label:contains("${name}")`,
+ run: () => {},
+ },
+ ];
+ }
+ hasTable(name) {
+ return [
+ {
+ content: `selected floor has '${name}' table`,
+ trigger: `.floor-map .tables .table .label:contains("${name}")`,
+ run: () => {},
+ },
+ ];
+ }
+ editModeIsActive(flag) {
+ return [
+ {
+ content: `check if edit mode is ${flag ? 'active' : 'inactive'}`,
+ trigger: `.floor-map .edit-button${flag ? '.active' : ':not(:has(.active))'}`,
+ run: () => {},
+ },
+ ];
+ }
+ tableSeatIs(table, val) {
+ return [
+ {
+ content: `number of seats in table '${table}' is '${val}'`,
+ trigger: `.floor-map .tables .table .label:contains("${table}") ~ .table-seats:contains("${val}")`,
+ run: function () {},
+ },
+ ];
+ }
+ orderCountSyncedInTableIs(table, count) {
+ return [
+ {
+ trigger: `.floor-map .table .order-count:contains("${count}") ~ .label:contains("${table}")`,
+ run: function () {},
+ },
+ ];
+ }
+ isShown() {
+ return [
+ {
+ trigger: '.floor-map',
+ run: function () {},
+ },
+ ];
+ }
+ tableIsNotSelected(name) {
+ return [
+ {
+ content: `table '${name}' is not selected`,
+ trigger: `.floor-map .table:not(.selected) .label:contains("${name}")`,
+ run: function () {},
+ },
+ ];
+ }
+ }
+
+ class Execute {}
+
+ return createTourMethods('FloorScreen', Do, Check, Execute);
+});
diff --git a/addons/pos_restaurant/static/tests/tours/helpers/ProductScreenTourMethods.js b/addons/pos_restaurant/static/tests/tours/helpers/ProductScreenTourMethods.js
new file mode 100644
index 00000000..decd30c4
--- /dev/null
+++ b/addons/pos_restaurant/static/tests/tours/helpers/ProductScreenTourMethods.js
@@ -0,0 +1,70 @@
+odoo.define('pos_restaurant.tour.ProductScreenTourMethods', function (require) {
+ 'use strict';
+
+ const { createTourMethods } = require('point_of_sale.tour.utils');
+ const { Do, Check, Execute } = require('point_of_sale.tour.ProductScreenTourMethods');
+
+ class DoExt extends Do {
+ clickSplitBillButton() {
+ return [
+ {
+ content: 'click split bill button',
+ trigger: '.control-buttons .control-button.order-split',
+ },
+ ];
+ }
+ clickTransferButton() {
+ return [
+ {
+ content: 'click transfer button',
+ trigger: '.control-buttons .control-button span:contains("Transfer")',
+ },
+ ];
+ }
+ clickNoteButton() {
+ return [
+ {
+ content: 'click note button',
+ trigger: '.control-buttons .control-button span:contains("Note")',
+ },
+ ];
+ }
+ clickPrintBillButton() {
+ return [
+ {
+ content: 'click print bill button',
+ trigger: '.control-buttons .control-button.order-printbill',
+ },
+ ];
+ }
+ clickSubmitButton() {
+ return [
+ {
+ content: 'click print bill button',
+ trigger: '.control-buttons .control-button span:contains("Order")',
+ },
+ ];
+ }
+ }
+
+ class CheckExt extends Check {
+ orderlineHasNote(name, quantity, note) {
+ return [
+ {
+ content: `line has ${quantity} quantity`,
+ trigger: `.order .orderline .product-name:contains("${name}") ~ .info-list em:contains("${quantity}")`,
+ run: function () {}, // it's a check
+ },
+ {
+ content: `line has '${note}' note`,
+ trigger: `.order .orderline .info-list .orderline-note:contains("${note}")`,
+ run: function () {}, // it's a check
+ },
+ ];
+ }
+ }
+
+ class ExecuteExt extends Execute {}
+
+ return createTourMethods('ProductScreen', DoExt, CheckExt, ExecuteExt);
+});
diff --git a/addons/pos_restaurant/static/tests/tours/helpers/SplitBillScreenTourMethods.js b/addons/pos_restaurant/static/tests/tours/helpers/SplitBillScreenTourMethods.js
new file mode 100644
index 00000000..7f58a1fc
--- /dev/null
+++ b/addons/pos_restaurant/static/tests/tours/helpers/SplitBillScreenTourMethods.js
@@ -0,0 +1,65 @@
+odoo.define('pos_restaurant.tour.SplitBillScreenTourMethods', function (require) {
+ 'use strict';
+
+ const { createTourMethods } = require('point_of_sale.tour.utils');
+
+ class Do {
+ clickOrderline(name, totalQuantity) {
+ let trigger = `li.orderline .product-name:contains("${name}")`;
+ if (totalQuantity) {
+ trigger += ` ~ .info-list .info:contains("${totalQuantity}")`;
+ }
+ return [
+ {
+ content: `click '${name}' orderline with total quantity of '${totalQuantity}'`,
+ trigger,
+ },
+ ];
+ }
+ clickBack() {
+ return [
+ {
+ content: 'click back button',
+ trigger: `.splitbill-screen .button.back`,
+ },
+ ];
+ }
+ clickPay() {
+ return [
+ {
+ content: 'click pay button',
+ trigger: `.splitbill-screen .pay-button .button`
+ }
+ ]
+ }
+ }
+
+ class Check {
+ orderlineHas(name, totalQuantity, splitQuantity) {
+ return [
+ {
+ content: `'${name}' orderline has total quantity of '${totalQuantity}'`,
+ trigger: `li.orderline .product-name:contains("${name}") ~ .info-list .info:contains("${totalQuantity}")`,
+ run: () => {},
+ },
+ {
+ content: `'${name}' orderline has '${splitQuantity}' quantity to split`,
+ trigger: `li.orderline .product-name:contains("${name}") ~ .info-list .info em:contains("${splitQuantity}")`,
+ run: () => {},
+ },
+ ];
+ }
+ subtotalIs(amount) {
+ return [
+ {
+ content: `total amount of split is '${amount}'`,
+ trigger: `.splitbill-screen .order-info .subtotal:contains("${amount}")`,
+ },
+ ];
+ }
+ }
+
+ class Execute {}
+
+ return createTourMethods('SplitBillScreen', Do, Check, Execute);
+});
diff --git a/addons/pos_restaurant/static/tests/tours/helpers/TextAreaPopupTourMethods.js b/addons/pos_restaurant/static/tests/tours/helpers/TextAreaPopupTourMethods.js
new file mode 100644
index 00000000..8f833370
--- /dev/null
+++ b/addons/pos_restaurant/static/tests/tours/helpers/TextAreaPopupTourMethods.js
@@ -0,0 +1,39 @@
+odoo.define('pos_restaurant.tour.TextAreaPopupTourMethods', function (require) {
+ 'use strict';
+
+ const { createTourMethods } = require('point_of_sale.tour.utils');
+
+ class Do {
+ inputText(val) {
+ return [
+ {
+ content: `input text '${val}'`,
+ trigger: `.modal-dialog .popup-textarea textarea`,
+ run: `text ${val}`,
+ },
+ ];
+ }
+ clickConfirm() {
+ return [
+ {
+ content: 'confirm text input popup',
+ trigger: '.modal-dialog .confirm',
+ },
+ ];
+ }
+ }
+
+ class Check {
+ isShown() {
+ return [
+ {
+ content: 'text input popup is shown',
+ trigger: '.modal-dialog .popup-textarea',
+ run: () => {},
+ },
+ ];
+ }
+ }
+
+ return createTourMethods('TextAreaPopup', Do, Check);
+});
diff --git a/addons/pos_restaurant/static/tests/tours/helpers/TextInputPopupTourMethods.js b/addons/pos_restaurant/static/tests/tours/helpers/TextInputPopupTourMethods.js
new file mode 100644
index 00000000..b46841c6
--- /dev/null
+++ b/addons/pos_restaurant/static/tests/tours/helpers/TextInputPopupTourMethods.js
@@ -0,0 +1,39 @@
+odoo.define('pos_restaurant.tour.TextInputPopupTourMethods', function (require) {
+ 'use strict';
+
+ const { createTourMethods } = require('point_of_sale.tour.utils');
+
+ class Do {
+ inputText(val) {
+ return [
+ {
+ content: `input text '${val}'`,
+ trigger: `.modal-dialog .popup-textinput input`,
+ run: `text ${val}`,
+ },
+ ];
+ }
+ clickConfirm() {
+ return [
+ {
+ content: 'confirm text input popup',
+ trigger: '.modal-dialog .confirm',
+ },
+ ];
+ }
+ }
+
+ class Check {
+ isShown() {
+ return [
+ {
+ content: 'text input popup is shown',
+ trigger: '.modal-dialog .popup-textinput',
+ run: () => {},
+ },
+ ];
+ }
+ }
+
+ return createTourMethods('TextInputPopup', Do, Check);
+});
diff --git a/addons/pos_restaurant/static/tests/tours/helpers/TipScreenTourMethods.js b/addons/pos_restaurant/static/tests/tours/helpers/TipScreenTourMethods.js
new file mode 100644
index 00000000..8895d566
--- /dev/null
+++ b/addons/pos_restaurant/static/tests/tours/helpers/TipScreenTourMethods.js
@@ -0,0 +1,60 @@
+odoo.define('pos_restaurant.tour.TipScreenTourMethods', function (require) {
+ 'use strict';
+
+ const { createTourMethods } = require('point_of_sale.tour.utils');
+
+ class Do {
+ clickPercentTip(percent) {
+ return [
+ {
+ trigger: `.tip-screen .percentage:contains("${percent}")`,
+ },
+ ];
+ }
+ setCustomTip(amount) {
+ return [
+ {
+ trigger: `.tip-screen .custom-amount-form input`,
+ run: `text ${amount}`,
+ },
+ ];
+ }
+ }
+
+ class Check {
+ isShown() {
+ return [
+ {
+ trigger: '.pos .tip-screen',
+ run: () => {},
+ },
+ ];
+ }
+ totalAmountIs(amount) {
+ return [
+ {
+ trigger: `.tip-screen .total-amount:contains("${amount}")`,
+ run: () => {},
+ },
+ ];
+ }
+ percentAmountIs(percent, amount) {
+ return [
+ {
+ trigger: `.tip-screen .percentage:contains("${percent}") ~ .amount:contains("${amount}")`,
+ run: () => {},
+ },
+ ];
+ }
+ inputAmountIs(amount) {
+ return [
+ {
+ trigger: `.tip-screen .custom-amount-form input[data-amount="${amount}"]`,
+ run: () => {},
+ }
+ ]
+ }
+ }
+
+ return createTourMethods('TipScreen', Do, Check);
+});
diff --git a/addons/pos_restaurant/static/tests/tours/pos_restaurant.js b/addons/pos_restaurant/static/tests/tours/pos_restaurant.js
new file mode 100644
index 00000000..03b7c86e
--- /dev/null
+++ b/addons/pos_restaurant/static/tests/tours/pos_restaurant.js
@@ -0,0 +1,108 @@
+odoo.define('pos_reataurant.tour.synchronized_table_management', function (require) {
+ 'use strict';
+
+ const { PaymentScreen } = require('point_of_sale.tour.PaymentScreenTourMethods');
+ const { ReceiptScreen } = require('point_of_sale.tour.ReceiptScreenTourMethods');
+ const { Chrome } = require('pos_restaurant.tour.ChromeTourMethods');
+ const { FloorScreen } = require('pos_restaurant.tour.FloorScreenTourMethods');
+ const { ProductScreen } = require('pos_restaurant.tour.ProductScreenTourMethods');
+ const { TicketScreen } = require('point_of_sale.tour.TicketScreenTourMethods');
+ const { getSteps, startSteps } = require('point_of_sale.tour.utils');
+ const Tour = require('web_tour.tour');
+
+ startSteps();
+
+ FloorScreen.do.clickTable('T5');
+
+ // Create first order
+ ProductScreen.do.clickDisplayedProduct('Coca-Cola');
+ ProductScreen.check.selectedOrderlineHas('Coca-Cola');
+ ProductScreen.do.clickDisplayedProduct('Water');
+ ProductScreen.check.selectedOrderlineHas('Water');
+ ProductScreen.check.totalAmountIs('4.40');
+
+ // Create 2nd order (paid)
+ Chrome.do.clickTicketButton();
+ TicketScreen.do.clickNewTicket();
+ ProductScreen.do.clickDisplayedProduct('Coca-Cola');
+ ProductScreen.check.selectedOrderlineHas('Coca-Cola');
+ ProductScreen.do.clickDisplayedProduct('Minute Maid');
+ ProductScreen.check.selectedOrderlineHas('Minute Maid');
+ ProductScreen.check.totalAmountIs('4.40');
+ ProductScreen.do.clickPayButton();
+ PaymentScreen.do.clickPaymentMethod('Cash');
+ PaymentScreen.do.clickValidate();
+ ReceiptScreen.do.clickNextOrder();
+
+ // After clicking next order, floor screen is shown.
+ // It should have 1 as number of draft synced order.
+ FloorScreen.check.orderCountSyncedInTableIs('T5', '1');
+ FloorScreen.do.clickTable('T5');
+ ProductScreen.check.totalAmountIs('4.40');
+
+ // Create another draft order and go back to floor
+ Chrome.do.clickTicketButton();
+ TicketScreen.do.clickNewTicket();
+ ProductScreen.do.clickDisplayedProduct('Coca-Cola');
+ ProductScreen.check.selectedOrderlineHas('Coca-Cola');
+ ProductScreen.do.clickDisplayedProduct('Minute Maid');
+ ProductScreen.check.selectedOrderlineHas('Minute Maid');
+ Chrome.do.backToFloor();
+
+ // At floor screen, there should be 2 synced draft orders
+ FloorScreen.check.orderCountSyncedInTableIs('T5', '2');
+
+ // Delete the first order then go back to floor
+ FloorScreen.do.clickTable('T5');
+ ProductScreen.check.isShown();
+ Chrome.do.clickTicketButton();
+ TicketScreen.do.deleteOrder('-0001');
+ Chrome.do.confirmPopup();
+ TicketScreen.do.selectOrder('-0003');
+ Chrome.do.backToFloor();
+
+ // There should be 1 synced draft order.
+ FloorScreen.check.orderCountSyncedInTableIs('T5', '1');
+
+ Tour.register('pos_restaurant_sync', { test: true, url: '/pos/ui' }, getSteps());
+
+ startSteps();
+
+ /* pos_restaurant_sync_second_login
+ *
+ * This tour should be run after the first tour is done.
+ */
+
+ // There is one draft synced order from the previous tour
+ FloorScreen.check.orderCountSyncedInTableIs('T5', '1');
+ FloorScreen.do.clickTable('T5');
+ ProductScreen.check.totalAmountIs('4.40');
+
+ // Test transfering an order
+ ProductScreen.do.clickTransferButton();
+ FloorScreen.do.clickTable('T4');
+
+ // Test if products still get merged after transfering the order
+ ProductScreen.do.clickDisplayedProduct('Coca-Cola');
+ ProductScreen.check.selectedOrderlineHas('Coca-Cola', '2.0');
+ ProductScreen.check.totalAmountIs('6.60');
+ ProductScreen.do.pressNumpad('1');
+ ProductScreen.check.totalAmountIs('4.40');
+ ProductScreen.do.clickPayButton();
+ PaymentScreen.do.clickPaymentMethod('Cash');
+ PaymentScreen.do.clickValidate();
+ ReceiptScreen.do.clickNextOrder();
+ // At this point, there are no draft orders.
+
+ FloorScreen.do.clickTable('T2');
+ ProductScreen.check.isShown();
+ ProductScreen.check.orderIsEmpty();
+ ProductScreen.do.clickTransferButton();
+ FloorScreen.do.clickTable('T4');
+ ProductScreen.do.clickDisplayedProduct('Coca-Cola');
+ ProductScreen.check.totalAmountIs('2.20');
+ Chrome.do.backToFloor();
+ FloorScreen.check.orderCountSyncedInTableIs('T4', '1');
+
+ Tour.register('pos_restaurant_sync_second_login', { test: true, url: '/pos/ui' }, getSteps());
+});
diff --git a/addons/pos_restaurant/static/tests/unit/test_FloorScreen.js b/addons/pos_restaurant/static/tests/unit/test_FloorScreen.js
new file mode 100644
index 00000000..34f13671
--- /dev/null
+++ b/addons/pos_restaurant/static/tests/unit/test_FloorScreen.js
@@ -0,0 +1,197 @@
+odoo.define('pos_restaurant.tests.FloorScreen', function (require) {
+ 'use strict';
+
+ const PosComponent = require('point_of_sale.PosComponent');
+ const { useListener } = require('web.custom_hooks');
+ const testUtils = require('web.test_utils');
+ const makePosTestEnv = require('point_of_sale.test_env');
+ const { xml } = owl.tags;
+ const { useRef } = owl.hooks;
+
+ QUnit.module('FloorScreen components', {});
+
+ QUnit.test('TableWidget', async function (assert) {
+ assert.expect(9);
+
+ class Parent extends PosComponent {
+ constructor() {
+ super();
+ useListener('select-table', () => assert.step('select-table'));
+ }
+ get table() {
+ // render table T1
+ return Object.values(this.env.pos.tables_by_id).find(
+ (table) => table.name === 'T1'
+ );
+ }
+ }
+ Parent.env = makePosTestEnv();
+ Parent.template = xml/* html */ `
+ <div><TableWidget table="table" /></div>
+ `;
+
+ const parent = new Parent();
+ await parent.mount(testUtils.prepareTarget());
+
+ const tableEl = parent.el.querySelector('.table');
+ assert.ok(tableEl.querySelector('span.label').textContent.includes('T1'));
+ assert.ok(tableEl.querySelector('span.table-seats').textContent.includes('4'));
+ assert.strictEqual(tableEl.style.width, '100px');
+ assert.strictEqual(tableEl.style.height, '100px');
+ assert.strictEqual(tableEl.style.background, 'rgb(53, 211, 116)');
+ assert.strictEqual(tableEl.style.top, '50px');
+ assert.strictEqual(tableEl.style.left, '50px');
+
+ await testUtils.dom.click(tableEl);
+ assert.verifySteps(['select-table']);
+
+ parent.unmount();
+ parent.destroy();
+ });
+
+ QUnit.test('EditableTable', async function (assert) {
+ assert.expect(11);
+
+ class Parent extends PosComponent {
+ constructor() {
+ super();
+ useListener('save-table', () => assert.step('save-table'));
+ this.tableRef = useRef('table-ref');
+ }
+ get table() {
+ // render table T1
+ return Object.values(this.env.pos.tables_by_id).find(
+ (table) => table.name === 'T1'
+ );
+ }
+ }
+ Parent.env = makePosTestEnv();
+ Parent.template = xml/* html */ `
+ <div class="floor-map">
+ <EditableTable table="table" t-ref="table-ref" />
+ </div>
+ `;
+
+ const parent = new Parent();
+ await parent.mount(testUtils.prepareTarget());
+
+ const tableEl = parent.el.querySelector('.table.selected');
+ assert.ok(tableEl.querySelector('span.label').textContent.includes('T1'));
+ assert.ok(tableEl.querySelector('span.table-seats').textContent.includes('4'));
+ assert.strictEqual(tableEl.style.width, '100px');
+ assert.strictEqual(tableEl.style.height, '100px');
+ assert.strictEqual(tableEl.style.background, 'rgb(53, 211, 116)');
+ assert.strictEqual(tableEl.style.top, '50px');
+ assert.strictEqual(tableEl.style.left, '50px');
+
+ parent.tableRef.comp.trigger('resize-end', {
+ size: { width: 100, height: 100 },
+ loc: { top: 50, left: 50 },
+ });
+ assert.verifySteps(['save-table']);
+ parent.tableRef.comp.trigger('drag-end', { loc: { top: 50, left: 50 } });
+ assert.verifySteps(['save-table']);
+
+ parent.unmount();
+ parent.destroy();
+ });
+
+ QUnit.test('EditBar', async function (assert) {
+ assert.expect(26);
+
+ class Parent extends PosComponent {
+ constructor() {
+ super();
+ useListener('create-table', () => assert.step('create-table'));
+ useListener('duplicate-table', () => assert.step('duplicate-table'));
+ useListener('rename-table', () => assert.step('rename-table'));
+ useListener('change-seats-num', () => assert.step('change-seats-num'));
+ useListener('change-shape', () => assert.step('change-shape'));
+ useListener('set-table-color', this._onSetTableColor);
+ useListener('set-floor-color', this._onSetFloorColor);
+ useListener('delete-table', () => assert.step('delete-table'));
+ }
+ get table() {
+ // render table T1
+ return Object.values(this.env.pos.tables_by_id).find(
+ (table) => table.name === 'T1'
+ );
+ }
+ _onSetTableColor({ detail: color }) {
+ assert.step('set-table-color');
+ assert.step(color);
+ }
+ _onSetFloorColor({ detail: color }) {
+ assert.step('set-floor-color');
+ assert.step(color);
+ }
+ }
+ Parent.env = makePosTestEnv();
+
+ // Part 1: Test EditBar with selected table
+
+ Parent.template = xml/* html */ `
+ <div>
+ <EditBar selectedTable="table" />
+ </div>
+ `;
+
+ let parent = new Parent();
+ await parent.mount(testUtils.prepareTarget());
+
+ await testUtils.dom.click(parent.el.querySelector('.edit-button i[aria-label=Add]'));
+ assert.verifySteps(['create-table']);
+ await testUtils.dom.click(parent.el.querySelector('.edit-button i[aria-label=Duplicate]'));
+ assert.verifySteps(['duplicate-table']);
+ await testUtils.dom.click(parent.el.querySelector('.edit-button i[aria-label=Rename]'));
+ assert.verifySteps(['rename-table']);
+ await testUtils.dom.click(parent.el.querySelector('.edit-button i[aria-label=Seats]'));
+ assert.verifySteps(['change-seats-num']);
+ await testUtils.dom.click(
+ parent.el.querySelector('.edit-button i[aria-label="Square Shape"]')
+ );
+ assert.verifySteps(['change-shape']);
+
+ await testUtils.dom.click(parent.el.querySelector('.edit-button i[aria-label=Tint]'));
+ await testUtils.nextTick();
+
+ assert.ok(parent.el.querySelector('.color-picker.fg-picker'));
+ await testUtils.dom.click(parent.el.querySelector('.fg-picker .color.tl'));
+ assert.verifySteps(['set-table-color', '#EB6D6D']);
+
+ await testUtils.dom.click(parent.el.querySelector('.edit-button.trash'));
+ assert.verifySteps(['delete-table']);
+
+ parent.unmount();
+ parent.destroy();
+
+ // Part 2: Test EditBar without selected table
+
+ Parent.template = xml/* html */ `
+ <div>
+ <EditBar />
+ </div>
+ `;
+
+ parent = new Parent();
+ await parent.mount(testUtils.prepareTarget());
+
+ assert.ok(parent.el.querySelector('.edit-button.disabled i[aria-label=Duplicate]'));
+ assert.ok(parent.el.querySelector('.edit-button.disabled i[aria-label=Rename]'));
+ assert.ok(parent.el.querySelector('.edit-button.disabled i[aria-label=Seats]'));
+ assert.ok(parent.el.querySelector('.edit-button.disabled i[aria-label="Square Shape"]'));
+ assert.ok(parent.el.querySelector('.edit-button.disabled i[aria-label=Delete]'));
+
+ await testUtils.dom.click(parent.el.querySelector('.edit-button i[aria-label=Tint]'));
+ await testUtils.nextTick();
+
+ assert.notOk(parent.el.querySelector('.color-picker.fg-picker'));
+ assert.ok(parent.el.querySelector('.color-picker.bg-picker'));
+
+ await testUtils.dom.click(parent.el.querySelector('.bg-picker .color.tl'));
+ assert.verifySteps(['set-floor-color', 'rgb(244, 149, 149)']);
+
+ parent.unmount();
+ parent.destroy();
+ });
+});