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