diff options
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.js | 309 |
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(); + }); +}); |
