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 */ `
`;
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 */ `
`;
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 */ `
`;
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 */ `
`;
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 */ `
`;
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();
});
});