summaryrefslogtreecommitdiff
path: root/addons/point_of_sale/static/tests/unit/test_PaymentScreen.js
diff options
context:
space:
mode:
Diffstat (limited to 'addons/point_of_sale/static/tests/unit/test_PaymentScreen.js')
-rw-r--r--addons/point_of_sale/static/tests/unit/test_PaymentScreen.js309
1 files changed, 309 insertions, 0 deletions
diff --git a/addons/point_of_sale/static/tests/unit/test_PaymentScreen.js b/addons/point_of_sale/static/tests/unit/test_PaymentScreen.js
new file mode 100644
index 00000000..48d3b55d
--- /dev/null
+++ b/addons/point_of_sale/static/tests/unit/test_PaymentScreen.js
@@ -0,0 +1,309 @@
+odoo.define('point_of_sale.tests.PaymentScreen', 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 { useState } = owl;
+
+ QUnit.module('unit tests for PaymentScreen components', {});
+
+ QUnit.test('PaymentMethodButton', async function (assert) {
+ assert.expect(2);
+
+ class Parent extends PosComponent {
+ constructor() {
+ super(...arguments);
+ useListener('new-payment-line', this._newPaymentLine);
+ }
+ _newPaymentLine() {
+ assert.step('new-payment-line');
+ }
+ }
+ Parent.env = makePosTestEnv();
+ Parent.template = xml/* html */ `
+ <div>
+ <PaymentMethodButton paymentMethod="{ name: 'Cash', id: 1 }" />
+ </div>
+ `;
+
+ const parent = new Parent();
+ await parent.mount(testUtils.prepareTarget());
+
+ const button = parent.el.querySelector('.paymentmethod');
+ await testUtils.dom.click(button);
+ assert.verifySteps(['new-payment-line']);
+
+ parent.unmount();
+ parent.destroy();
+ });
+
+ QUnit.test('PSNumpadInputButton', async function (assert) {
+ assert.expect(15);
+
+ class Parent extends PosComponent {
+ constructor({ value, text, changeClassTo }) {
+ super();
+ this.state = useState({ value, text, changeClassTo });
+ useListener('input-from-numpad', this._inputFromNumpad);
+ }
+ _inputFromNumpad({ detail: { key } }) {
+ assert.step(`${key}-input`);
+ }
+ setState(obj) {
+ Object.assign(this.state, obj);
+ }
+ }
+ Parent.env = makePosTestEnv();
+ Parent.template = xml/* html */ `
+ <div>
+ <PSNumpadInputButton value="state.value" text="state.text" changeClassTo="state.changeClassTo" />
+ </div>
+ `;
+
+ let parent = new Parent({ value: '1' });
+ await parent.mount(testUtils.prepareTarget());
+
+ let button = parent.el.querySelector('button');
+ assert.ok(button.textContent.includes('1'));
+ assert.ok(button.classList.contains('number-char'));
+ await testUtils.dom.click(button);
+ await testUtils.nextTick();
+ assert.verifySteps(['1-input']);
+
+ parent.setState({ value: '2', text: 'Two' });
+ await testUtils.nextTick();
+ assert.ok(button.textContent.includes('Two'));
+ await testUtils.dom.click(button);
+ await testUtils.nextTick();
+ assert.verifySteps(['2-input']);
+
+ parent.setState({ value: '+12', text: null, changeClassTo: 'not-number-char' });
+ await testUtils.nextTick();
+ assert.ok(button.textContent.includes('+12'));
+ assert.ok(button.classList.contains('not-number-char'));
+ // class number-char should have been replaced
+ assert.notOk(button.classList.contains('number-char'));
+ await testUtils.dom.click(button);
+ await testUtils.nextTick();
+ assert.verifySteps(['+12-input']);
+
+ parent.unmount();
+ parent.destroy();
+
+ // using the slot should ignore value and text props of the component
+ Parent.template = xml/* html */ `
+ <div>
+ <PSNumpadInputButton value="state.value" text="state.text" changeClassTo="state.changeClassTo">
+ <span>UseSlot</span>
+ </PSNumpadInputButton>
+ </div>
+ `;
+ parent = new Parent({ value: 'slotted', text: 'Text' });
+ await parent.mount(testUtils.prepareTarget());
+
+ button = parent.el.querySelector('button');
+ assert.ok(button.textContent.includes('UseSlot'));
+ await testUtils.dom.click(button);
+ await testUtils.nextTick();
+ assert.verifySteps(['slotted-input']);
+
+ parent.unmount();
+ parent.destroy();
+ });
+
+ QUnit.test('PaymentScreenPaymentLines', async function (assert) {
+ assert.expect(12);
+
+ class Parent extends PosComponent {
+ constructor() {
+ super();
+ useListener('delete-payment-line', this._onDeletePaymentLine);
+ useListener('select-payment-line', this._onSelectPaymentLine);
+ }
+ get paymentLines() {
+ return this.order.get_paymentlines();
+ }
+ get order() {
+ return this.env.pos.get_order();
+ }
+ mounted() {
+ this.order.paymentlines.on('change', this.render, this);
+ }
+ willUnmount() {
+ this.order.paymentlines.off('change', null, this);
+ }
+ _onDeletePaymentLine() {
+ assert.step('delete-click');
+ }
+ _onSelectPaymentLine() {
+ assert.step('select-click');
+ }
+ }
+ Parent.env = makePosTestEnv();
+ Parent.template = xml/* html */ `
+ <div>
+ <PaymentScreenPaymentLines paymentLines="paymentLines" />
+ </div>
+ `;
+
+ let parent = new Parent();
+ await parent.mount(testUtils.prepareTarget());
+
+ const order = parent.env.pos.get_order();
+ const cashPM = { id: 0, name: 'Cash', is_cash_count: true, use_payment_terminal: false };
+ const bankPM = { id: 0, name: 'Bank', is_cash_count: false, use_payment_terminal: false };
+
+ let paymentline1 = order.add_paymentline(cashPM);
+ await testUtils.nextTick();
+
+ let statusContainer = parent.el.querySelector('.payment-status-container');
+ let linesEl = parent.el.querySelector('.paymentlines');
+ assert.ok(linesEl, 'payment lines are shown');
+ let newLine = linesEl.querySelector('.selected');
+ assert.ok(newLine, 'the new line is automatically selected');
+
+ let paymentline2 = order.add_paymentline(bankPM);
+ await testUtils.nextTick();
+ assert.notOk(
+ linesEl.querySelector('.selected') === newLine,
+ 'the previously added paymentline should not be selected anymore'
+ );
+ assert.ok(
+ linesEl.querySelectorAll('.paymentline:not(.heading)').length === 2,
+ 'there should be two paymentlines'
+ );
+
+ let paymentline3 = order.add_paymentline(cashPM);
+ await testUtils.nextTick();
+ assert.ok(
+ linesEl.querySelectorAll('.paymentline:not(.heading)').length === 3,
+ 'there should be three paymentlines'
+ );
+ assert.ok(
+ linesEl.querySelectorAll('.paymentline.selected').length === 1,
+ 'there should only be one selected paymentline'
+ );
+
+ await testUtils.dom.click(linesEl.querySelector('.paymentline.selected .delete-button'));
+ await testUtils.nextTick();
+ assert.verifySteps(['delete-click', 'select-click']);
+
+ // click the 2nd payment line
+ await testUtils.dom.click(linesEl.querySelectorAll('.paymentline:not(.heading)')[1]);
+ await testUtils.nextTick();
+ assert.verifySteps(['select-click']);
+
+ // remove paymentline3 (the selected)
+ order.remove_paymentline(paymentline3);
+ await testUtils.nextTick();
+ assert.notOk(
+ linesEl.querySelector('.paymentline.selected'),
+ 'no more selected payment line'
+ );
+
+ order.remove_paymentline(paymentline1);
+ order.remove_paymentline(paymentline2);
+
+ parent.unmount();
+ parent.destroy();
+ });
+
+ QUnit.test('PaymentScreenElectronicPayment', async function (assert) {
+ assert.expect(17);
+
+ class SimulatedPaymentLine extends Backbone.Model {
+ constructor() {
+ super();
+ this.payment_status = 'pending';
+ this.can_be_reversed = false;
+ }
+ canBeAdjusted() {
+ return false;
+ }
+ setPaymentStatus(status) {
+ this.payment_status = status;
+ this.trigger('change');
+ }
+ toggleCanBeReversed() {
+ this.can_be_reversed = !this.can_be_reversed;
+ this.trigger('change');
+ }
+ }
+
+ class Parent extends PosComponent {
+ constructor() {
+ super();
+ this.line = new SimulatedPaymentLine();
+ useListener('send-payment-request', () => assert.step('send-payment-request'));
+ useListener('send-force-done', () => assert.step('send-force-done'));
+ useListener('send-payment-cancel', () => assert.step('send-payment-cancel'));
+ useListener('send-payment-reverse', () => assert.step('send-payment-reverse'));
+ }
+ }
+ Parent.env = makePosTestEnv();
+ Parent.template = xml/* html */ `
+ <div>
+ <PaymentScreenElectronicPayment line="line" />
+ </div>
+ `;
+
+ let parent = new Parent();
+ await parent.mount(testUtils.prepareTarget());
+
+ assert.ok(parent.el.querySelector('.paymentline .send_payment_request'));
+ await testUtils.dom.click(parent.el.querySelector('.paymentline .send_payment_request'));
+ await testUtils.nextTick();
+ assert.verifySteps(['send-payment-request']);
+
+ parent.line.setPaymentStatus('retry');
+ await testUtils.nextTick();
+ await testUtils.dom.click(parent.el.querySelector('.paymentline .send_payment_request'));
+ await testUtils.nextTick();
+ assert.verifySteps(['send-payment-request']);
+
+ parent.line.setPaymentStatus('force_done');
+ await testUtils.nextTick();
+ await testUtils.dom.click(parent.el.querySelector('.paymentline .send_force_done'));
+ await testUtils.nextTick();
+ assert.verifySteps(['send-force-done']);
+
+ parent.line.setPaymentStatus('waitingCard');
+ await testUtils.nextTick();
+ await testUtils.dom.click(parent.el.querySelector('.paymentline .send_payment_cancel'));
+ await testUtils.nextTick();
+ assert.verifySteps(['send-payment-cancel']);
+
+ parent.line.setPaymentStatus('waiting');
+ await testUtils.nextTick();
+ assert.ok(parent.el.querySelector('.paymentline i.fa-spinner'));
+
+ parent.line.setPaymentStatus('waitingCancel');
+ await testUtils.nextTick();
+ assert.ok(parent.el.querySelector('.paymentline i.fa-spinner'));
+
+ parent.line.setPaymentStatus('reversing');
+ await testUtils.nextTick();
+ assert.ok(parent.el.querySelector('.paymentline i.fa-spinner'));
+
+ parent.line.setPaymentStatus('done');
+ await testUtils.nextTick();
+ assert.notOk(parent.el.querySelector('.paymentline .send_payment_reversal'));
+
+ parent.line.toggleCanBeReversed();
+ await testUtils.nextTick();
+ assert.ok(parent.el.querySelector('.paymentline .send_payment_reversal'));
+ await testUtils.dom.click(parent.el.querySelector('.paymentline .send_payment_reversal'));
+ await testUtils.nextTick();
+ assert.verifySteps(['send-payment-reverse']);
+
+ parent.line.setPaymentStatus('reversed');
+ await testUtils.nextTick();
+ assert.ok(parent.el.querySelector('.paymentline'));
+
+ parent.unmount();
+ parent.destroy();
+ });
+});