mirror of
https://github.com/bringout/oca-ocb-sale.git
synced 2026-04-26 15:52:03 +02:00
Initial commit: Sale packages
This commit is contained in:
commit
14e3d26998
6469 changed files with 2479670 additions and 0 deletions
|
|
@ -0,0 +1,34 @@
|
|||
odoo.define('point_of_sale.test_env', async function (require) {
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Many components in PoS are dependent on the PosGlobalState instance (pos).
|
||||
* Therefore, for unit tests that require pos in the Components' env, we
|
||||
* prepared here a test env maker (makePosTestEnv) based on
|
||||
* makeTestEnvironment of web.
|
||||
*/
|
||||
|
||||
const makeTestEnvironment = require('web.test_env');
|
||||
const env = require('point_of_sale.env');
|
||||
const { PosGlobalState } = require('point_of_sale.models');
|
||||
const cleanup = require("@web/../tests/helpers/cleanup");
|
||||
|
||||
// We override this method in the pos unit tests to prevent the unnecessary error in the web tests.
|
||||
cleanup.registerCleanup = () => {}
|
||||
|
||||
await env.session.is_bound;
|
||||
const pos = PosGlobalState.create({ env });
|
||||
await pos.load_server_data();
|
||||
|
||||
/**
|
||||
* @param {Object} env default env
|
||||
* @param {Function} providedRPC mock rpc
|
||||
* @param {Function} providedDoAction mock do_action
|
||||
*/
|
||||
function makePosTestEnv(env = {}, providedRPC = null, providedDoAction = null) {
|
||||
env = Object.assign(env, { pos });
|
||||
return makeTestEnvironment(env, providedRPC);
|
||||
}
|
||||
|
||||
return makePosTestEnv;
|
||||
});
|
||||
|
|
@ -0,0 +1,414 @@
|
|||
odoo.define('point_of_sale.tests.ComponentRegistry', function(require) {
|
||||
'use strict';
|
||||
|
||||
const Registries = require('point_of_sale.Registries');
|
||||
|
||||
QUnit.module('unit tests for ComponentRegistry', {
|
||||
before() {},
|
||||
});
|
||||
|
||||
QUnit.test('basic extend', async function(assert) {
|
||||
assert.expect(5);
|
||||
|
||||
class A {
|
||||
constructor() {
|
||||
assert.step('A');
|
||||
}
|
||||
}
|
||||
Registries.Component.add(A);
|
||||
|
||||
let A1 = x =>
|
||||
class extends x {
|
||||
constructor() {
|
||||
super();
|
||||
assert.step('A1');
|
||||
}
|
||||
};
|
||||
Registries.Component.extend(A, A1);
|
||||
|
||||
Registries.Component.freeze();
|
||||
|
||||
const RegA = Registries.Component.get(A);
|
||||
let a = new RegA();
|
||||
assert.verifySteps(['A', 'A1']);
|
||||
assert.ok(a instanceof RegA);
|
||||
assert.ok(RegA.name === 'A');
|
||||
});
|
||||
|
||||
QUnit.test('addByExtending', async function(assert) {
|
||||
assert.expect(8);
|
||||
|
||||
class A {
|
||||
constructor() {
|
||||
assert.step('A');
|
||||
}
|
||||
}
|
||||
Registries.Component.add(A);
|
||||
|
||||
let B = x =>
|
||||
class extends x {
|
||||
constructor() {
|
||||
super();
|
||||
assert.step('B');
|
||||
}
|
||||
};
|
||||
Registries.Component.addByExtending(B, A);
|
||||
|
||||
let A1 = x =>
|
||||
class extends x {
|
||||
constructor() {
|
||||
super();
|
||||
assert.step('A1');
|
||||
}
|
||||
};
|
||||
Registries.Component.extend(A, A1);
|
||||
|
||||
let A2 = x =>
|
||||
class extends x {
|
||||
constructor() {
|
||||
super();
|
||||
assert.step('A2');
|
||||
}
|
||||
};
|
||||
Registries.Component.extend(A, A2);
|
||||
|
||||
Registries.Component.freeze();
|
||||
|
||||
const RegA = Registries.Component.get(A);
|
||||
const RegB = Registries.Component.get(B);
|
||||
let b = new RegB();
|
||||
assert.verifySteps(['A', 'A1', 'A2', 'B']);
|
||||
assert.ok(b instanceof RegA);
|
||||
assert.ok(b instanceof RegB);
|
||||
assert.ok(RegB.name === 'B');
|
||||
});
|
||||
|
||||
QUnit.test('extend the one that is added by extending', async function(assert) {
|
||||
assert.expect(6);
|
||||
|
||||
class A {
|
||||
constructor() {
|
||||
assert.step('A');
|
||||
}
|
||||
}
|
||||
Registries.Component.add(A);
|
||||
|
||||
let B = x =>
|
||||
class extends x {
|
||||
constructor() {
|
||||
super();
|
||||
assert.step('B');
|
||||
}
|
||||
};
|
||||
Registries.Component.addByExtending(B, A);
|
||||
|
||||
let B1 = x =>
|
||||
class extends x {
|
||||
constructor() {
|
||||
super();
|
||||
assert.step('B1');
|
||||
}
|
||||
};
|
||||
Registries.Component.extend(B, B1);
|
||||
|
||||
let B2 = x =>
|
||||
class extends x {
|
||||
constructor() {
|
||||
super();
|
||||
assert.step('B2');
|
||||
}
|
||||
};
|
||||
Registries.Component.extend(B, B2);
|
||||
|
||||
let A1 = x =>
|
||||
class extends x {
|
||||
constructor() {
|
||||
super();
|
||||
assert.step('A1');
|
||||
}
|
||||
};
|
||||
Registries.Component.extend(A, A1);
|
||||
|
||||
Registries.Component.freeze();
|
||||
|
||||
const RegB = Registries.Component.get(B);
|
||||
new RegB();
|
||||
assert.verifySteps(['A', 'A1', 'B', 'B1', 'B2']);
|
||||
});
|
||||
|
||||
QUnit.test('addByExtending based on added by extending', async function(assert) {
|
||||
assert.expect(10);
|
||||
|
||||
class A {
|
||||
constructor() {
|
||||
assert.step('A');
|
||||
}
|
||||
}
|
||||
Registries.Component.add(A);
|
||||
|
||||
let B = x =>
|
||||
class extends x {
|
||||
constructor() {
|
||||
super();
|
||||
assert.step('B');
|
||||
}
|
||||
};
|
||||
Registries.Component.addByExtending(B, A);
|
||||
|
||||
let A1 = x =>
|
||||
class extends x {
|
||||
constructor() {
|
||||
super();
|
||||
assert.step('A1');
|
||||
}
|
||||
};
|
||||
Registries.Component.extend(A, A1);
|
||||
|
||||
let C = x =>
|
||||
class extends x {
|
||||
constructor() {
|
||||
super();
|
||||
assert.step('C');
|
||||
}
|
||||
};
|
||||
Registries.Component.addByExtending(C, B);
|
||||
|
||||
let B7 = x =>
|
||||
class extends x {
|
||||
constructor() {
|
||||
super();
|
||||
assert.step('B7');
|
||||
}
|
||||
};
|
||||
Registries.Component.extend(B, B7);
|
||||
|
||||
Registries.Component.freeze();
|
||||
|
||||
const RegA = Registries.Component.get(A);
|
||||
const RegB = Registries.Component.get(B);
|
||||
const RegC = Registries.Component.get(C);
|
||||
let c = new RegC();
|
||||
assert.verifySteps(['A', 'A1', 'B', 'B7', 'C']);
|
||||
assert.ok(c instanceof RegA);
|
||||
assert.ok(c instanceof RegB);
|
||||
assert.ok(c instanceof RegC);
|
||||
assert.ok(RegC.name === 'C');
|
||||
});
|
||||
|
||||
QUnit.test('deeper inheritance', async function(assert) {
|
||||
assert.expect(9);
|
||||
|
||||
class A {
|
||||
constructor() {
|
||||
assert.step('A');
|
||||
}
|
||||
}
|
||||
Registries.Component.add(A);
|
||||
|
||||
let B = x =>
|
||||
class extends x {
|
||||
constructor() {
|
||||
super();
|
||||
assert.step('B');
|
||||
}
|
||||
};
|
||||
Registries.Component.addByExtending(B, A);
|
||||
|
||||
let A1 = x =>
|
||||
class extends x {
|
||||
constructor() {
|
||||
super();
|
||||
assert.step('A1');
|
||||
}
|
||||
};
|
||||
Registries.Component.extend(A, A1);
|
||||
|
||||
let C = x =>
|
||||
class extends x {
|
||||
constructor() {
|
||||
super();
|
||||
assert.step('C');
|
||||
}
|
||||
};
|
||||
Registries.Component.addByExtending(C, B);
|
||||
|
||||
let B2 = x =>
|
||||
class extends x {
|
||||
constructor() {
|
||||
super();
|
||||
assert.step('B2');
|
||||
}
|
||||
};
|
||||
Registries.Component.extend(B, B2);
|
||||
|
||||
let B3 = x =>
|
||||
class extends x {
|
||||
constructor() {
|
||||
super();
|
||||
assert.step('B3');
|
||||
}
|
||||
};
|
||||
Registries.Component.extend(B, B3);
|
||||
|
||||
let A9 = x =>
|
||||
class extends x {
|
||||
constructor() {
|
||||
super();
|
||||
assert.step('A9');
|
||||
}
|
||||
};
|
||||
Registries.Component.extend(A, A9);
|
||||
|
||||
let E = x =>
|
||||
class extends x {
|
||||
constructor() {
|
||||
super();
|
||||
assert.step('E');
|
||||
}
|
||||
};
|
||||
Registries.Component.addByExtending(E, C);
|
||||
|
||||
Registries.Component.freeze();
|
||||
|
||||
// |A| => A9 -> A1 -> A
|
||||
// |B| => B3 -> B2 -> B -> |A|
|
||||
// |C| => C -> |B|
|
||||
// |E| => E -> |C|
|
||||
|
||||
new (Registries.Component.get(E))();
|
||||
assert.verifySteps(['A', 'A1', 'A9', 'B', 'B2', 'B3', 'C', 'E']);
|
||||
});
|
||||
|
||||
QUnit.test('mixins?', async function(assert) {
|
||||
assert.expect(12);
|
||||
|
||||
class A {
|
||||
constructor() {
|
||||
assert.step('A');
|
||||
}
|
||||
}
|
||||
Registries.Component.add(A);
|
||||
|
||||
let Mixin = x =>
|
||||
class extends x {
|
||||
constructor() {
|
||||
super();
|
||||
assert.step('Mixin');
|
||||
}
|
||||
mixinMethod() {
|
||||
return 'mixinMethod';
|
||||
}
|
||||
get mixinGetter() {
|
||||
return 'mixinGetter';
|
||||
}
|
||||
};
|
||||
|
||||
// use the mixin when declaring B.
|
||||
let B = x =>
|
||||
class extends Mixin(x) {
|
||||
constructor() {
|
||||
super();
|
||||
assert.step('B');
|
||||
}
|
||||
};
|
||||
Registries.Component.addByExtending(B, A);
|
||||
|
||||
let A1 = x =>
|
||||
class extends x {
|
||||
constructor() {
|
||||
super();
|
||||
assert.step('A1');
|
||||
}
|
||||
};
|
||||
Registries.Component.extend(A, A1);
|
||||
|
||||
Registries.Component.freeze();
|
||||
|
||||
B = Registries.Component.get(B);
|
||||
const b = new B();
|
||||
assert.verifySteps(['A', 'A1', 'Mixin', 'B']);
|
||||
// instance of B should have the mixin properties
|
||||
assert.strictEqual(b.mixinMethod(), 'mixinMethod');
|
||||
assert.strictEqual(b.mixinGetter, 'mixinGetter');
|
||||
|
||||
// instance of A should not have the mixin properties
|
||||
A = Registries.Component.get(A);
|
||||
const a = new A();
|
||||
assert.verifySteps(['A', 'A1']);
|
||||
assert.notOk(a.mixinMethod);
|
||||
assert.notOk(a.mixinGetter);
|
||||
});
|
||||
|
||||
QUnit.test('extending methods', async function(assert) {
|
||||
assert.expect(16);
|
||||
|
||||
class A {
|
||||
foo() {
|
||||
assert.step('A foo');
|
||||
}
|
||||
}
|
||||
Registries.Component.add(A);
|
||||
|
||||
let B = x =>
|
||||
class extends x {
|
||||
bar() {
|
||||
assert.step('B bar');
|
||||
}
|
||||
};
|
||||
Registries.Component.addByExtending(B, A);
|
||||
|
||||
let A1 = x =>
|
||||
class extends x {
|
||||
bar() {
|
||||
assert.step('A1 bar');
|
||||
// should only be for A.
|
||||
}
|
||||
};
|
||||
Registries.Component.extend(A, A1);
|
||||
|
||||
let B1 = x =>
|
||||
class extends x {
|
||||
foo() {
|
||||
super.foo();
|
||||
assert.step('B1 foo');
|
||||
}
|
||||
};
|
||||
Registries.Component.extend(B, B1);
|
||||
|
||||
let C = x =>
|
||||
class extends x {
|
||||
foo() {
|
||||
super.foo();
|
||||
assert.step('C foo');
|
||||
}
|
||||
bar() {
|
||||
super.bar();
|
||||
assert.step('C bar');
|
||||
}
|
||||
};
|
||||
Registries.Component.addByExtending(C, B);
|
||||
|
||||
Registries.Component.freeze();
|
||||
|
||||
A = Registries.Component.get(A);
|
||||
B = Registries.Component.get(B);
|
||||
C = Registries.Component.get(C);
|
||||
const a = new A();
|
||||
const b = new B();
|
||||
const c = new C();
|
||||
|
||||
a.foo();
|
||||
assert.verifySteps(['A foo']);
|
||||
b.foo();
|
||||
assert.verifySteps(['A foo', 'B1 foo']);
|
||||
c.foo();
|
||||
assert.verifySteps(['A foo', 'B1 foo', 'C foo']);
|
||||
|
||||
a.bar();
|
||||
assert.verifySteps(['A1 bar']);
|
||||
b.bar();
|
||||
assert.verifySteps(['B bar']);
|
||||
c.bar();
|
||||
assert.verifySteps(['B bar', 'C bar']);
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
odoo.define('point_of_sale.tests.NumberBuffer', function(require) {
|
||||
'use strict';
|
||||
|
||||
const NumberBuffer = require('point_of_sale.NumberBuffer');
|
||||
const makeTestEnvironment = require('web.test_env');
|
||||
const testUtils = require('web.test_utils');
|
||||
const { mount } = require('@web/../tests/helpers/utils');
|
||||
const { LegacyComponent } = require("@web/legacy/legacy_component");
|
||||
|
||||
const { useState, xml } = owl;
|
||||
|
||||
QUnit.module('unit tests for NumberBuffer', {
|
||||
before() {},
|
||||
});
|
||||
|
||||
QUnit.test('simple fast inputs with capture in between', async function(assert) {
|
||||
assert.expect(3);
|
||||
const target = testUtils.prepareTarget();
|
||||
const env = makeTestEnvironment();
|
||||
|
||||
class Root extends LegacyComponent {
|
||||
setup() {
|
||||
this.state = useState({ buffer: '' });
|
||||
NumberBuffer.activate();
|
||||
NumberBuffer.use({
|
||||
nonKeyboardInputEvent: 'numpad-click-input',
|
||||
state: this.state,
|
||||
});
|
||||
}
|
||||
resetBuffer() {
|
||||
NumberBuffer.capture();
|
||||
NumberBuffer.reset();
|
||||
}
|
||||
onClickOne() {
|
||||
this.trigger('numpad-click-input', { key: '1' });
|
||||
}
|
||||
onClickTwo() {
|
||||
this.trigger('numpad-click-input', { key: '2' });
|
||||
}
|
||||
}
|
||||
Root.template = xml/* html */ `
|
||||
<div>
|
||||
<p><t t-esc="state.buffer" /></p>
|
||||
<button class="one" t-on-click="onClickOne">1</button>
|
||||
<button class="two" t-on-click="onClickTwo">2</button>
|
||||
<button class="reset" t-on-click="resetBuffer">reset</button>
|
||||
</div>
|
||||
`;
|
||||
|
||||
await mount(Root, target, { env });
|
||||
|
||||
const oneButton = target.querySelector('button.one');
|
||||
const twoButton = target.querySelector('button.two');
|
||||
const resetButton = target.querySelector('button.reset');
|
||||
const bufferEl = target.querySelector('p');
|
||||
|
||||
testUtils.dom.click(oneButton);
|
||||
testUtils.dom.click(twoButton);
|
||||
await testUtils.nextTick();
|
||||
assert.strictEqual(bufferEl.textContent, '12');
|
||||
testUtils.dom.click(resetButton);
|
||||
await testUtils.nextTick();
|
||||
assert.strictEqual(bufferEl.textContent, '');
|
||||
testUtils.dom.click(twoButton);
|
||||
testUtils.dom.click(oneButton);
|
||||
await testUtils.nextTick();
|
||||
assert.strictEqual(bufferEl.textContent, '21');
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,165 @@
|
|||
odoo.define('point_of_sale.tests.PosPopupController', function(require) {
|
||||
'use strict';
|
||||
|
||||
const PosPopupController = require('point_of_sale.PosPopupController');
|
||||
const AbstractAwaitablePopup = require('point_of_sale.AbstractAwaitablePopup');
|
||||
const PosComponent = require('point_of_sale.PosComponent');
|
||||
const makeTestEnvironment = require('web.test_env');
|
||||
const testUtils = require('web.test_utils');
|
||||
const Registries = require('point_of_sale.Registries');
|
||||
const { mount } = require('@web/../tests/helpers/utils');
|
||||
|
||||
const { EventBus, useSubEnv, xml } = owl;
|
||||
|
||||
QUnit.module('unit tests for PosPopupController', {
|
||||
before() {
|
||||
Registries.Component.freeze();
|
||||
|
||||
// Note that we are creating new popups here to decouple this test from the pos app.
|
||||
class CustomPopup1 extends AbstractAwaitablePopup {}
|
||||
CustomPopup1.template = xml/* html */`
|
||||
<div class="popup custom-popup-1">
|
||||
<footer>
|
||||
<div class="confirm" t-on-click="confirm">
|
||||
Yes
|
||||
</div>
|
||||
<div class="cancel" t-on-click="cancel">
|
||||
No
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
`;
|
||||
|
||||
class CustomPopup2 extends AbstractAwaitablePopup {}
|
||||
CustomPopup2.template = xml/* html */`
|
||||
<div class="popup custom-popup-2">
|
||||
<footer>
|
||||
<div class="confirm" t-on-click="confirm">
|
||||
Okay
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
`;
|
||||
|
||||
PosPopupController.components = { CustomPopup1, CustomPopup2 };
|
||||
},
|
||||
});
|
||||
|
||||
QUnit.test('allow multiple popups at the same time', async function(assert) {
|
||||
assert.expect(12);
|
||||
|
||||
class Root extends PosComponent {
|
||||
setup() {
|
||||
super.setup();
|
||||
useSubEnv({
|
||||
isDebug: () => false,
|
||||
posbus: new EventBus(),
|
||||
});
|
||||
}
|
||||
}
|
||||
Root.env = makeTestEnvironment();
|
||||
Root.template = xml/* html */ `
|
||||
<div>
|
||||
<PosPopupController />
|
||||
</div>
|
||||
`;
|
||||
|
||||
const root = await mount(Root, testUtils.prepareTarget());
|
||||
|
||||
// Check 1 popup
|
||||
let popup1Promise = root.showPopup('CustomPopup1', {});
|
||||
await testUtils.nextTick();
|
||||
assert.strictEqual(root.el.querySelectorAll('.popup').length, 1);
|
||||
testUtils.dom.click(root.el.querySelector('.modal-dialog .custom-popup-1 .confirm'));
|
||||
let result1 = await popup1Promise;
|
||||
assert.strictEqual(result1.confirmed, true);
|
||||
await testUtils.nextTick();
|
||||
assert.strictEqual(root.el.querySelectorAll('.popup').length, 0);
|
||||
|
||||
// Check multiple popups
|
||||
popup1Promise = root.showPopup('CustomPopup1', {});
|
||||
await testUtils.nextTick();
|
||||
|
||||
// Check if the first popup is shown.
|
||||
assert.strictEqual(root.el.querySelectorAll('.popup').length, 1);
|
||||
|
||||
let popup2Promise = root.showPopup('CustomPopup2', {});
|
||||
await testUtils.nextTick();
|
||||
|
||||
// Check for the second popup.
|
||||
assert.strictEqual(root.el.querySelectorAll('.popup').length, 2);
|
||||
|
||||
// popup 1 should be hidden
|
||||
assert.strictEqual(root.el.querySelectorAll('.modal-dialog.oe_hidden').length, 1);
|
||||
|
||||
// click confirm on popup 2
|
||||
testUtils.dom.click(root.el.querySelector('.modal-dialog .custom-popup-2 .confirm'));
|
||||
await testUtils.nextTick();
|
||||
|
||||
// after confirming on popup 2, only 1 should remain.
|
||||
assert.strictEqual(root.el.querySelectorAll('.popup').length, 1);
|
||||
assert.strictEqual(root.el.querySelectorAll('.modal-dialog .custom-popup-2').length, 0);
|
||||
|
||||
// popup 1 should not be hidden
|
||||
const CustomPopup1 = root.el.querySelector('.modal-dialog')
|
||||
assert.strictEqual(![...CustomPopup1.classList].includes('oe_hidden'), true);
|
||||
testUtils.dom.click(root.el.querySelector('.modal-dialog .custom-popup-1 .cancel'));
|
||||
await testUtils.nextTick();
|
||||
|
||||
// after cancelling popup 1, no popup should remain.
|
||||
assert.strictEqual(root.el.querySelectorAll('.popup').length, 0);
|
||||
|
||||
result1 = await popup1Promise;
|
||||
let result2 = await popup2Promise;
|
||||
assert.strictEqual(result1.confirmed, false); // false because it's cancelled.
|
||||
assert.strictEqual(result2.confirmed, true); // true because it's confirmed.
|
||||
});
|
||||
|
||||
QUnit.test('pressing cancel/confirm key should only close the top popup', async function(assert) {
|
||||
assert.expect(6);
|
||||
|
||||
class Root extends PosComponent {
|
||||
setup() {
|
||||
super.setup();
|
||||
useSubEnv({
|
||||
isDebug: () => false,
|
||||
posbus: new EventBus(),
|
||||
});
|
||||
}
|
||||
}
|
||||
Root.env = makeTestEnvironment();
|
||||
Root.template = xml/* html */ `
|
||||
<div>
|
||||
<PosPopupController />
|
||||
</div>
|
||||
`;
|
||||
|
||||
const root = await mount(Root, testUtils.prepareTarget());
|
||||
|
||||
let popup1Promise = root.showPopup('CustomPopup1', { confirmKey: 'Enter', cancelKey: 'Escape' });
|
||||
await testUtils.nextTick();
|
||||
assert.strictEqual(root.el.querySelectorAll('.popup').length, 1);
|
||||
|
||||
let popup2Promise = root.showPopup('CustomPopup2', { confirmKey: 'Enter', cancelKey: 'Escape' });
|
||||
await testUtils.nextTick();
|
||||
assert.strictEqual(root.el.querySelectorAll('.popup').length, 2);
|
||||
|
||||
// Pressing 'Escape' should cancel the top popup which is the CustomPopup2.
|
||||
testUtils.dom.triggerEvent(window, 'keyup', { key: 'Escape' });
|
||||
await testUtils.nextTick();
|
||||
|
||||
// Therefore, the popup2Promise has now resolved with `confirmed` value = false.
|
||||
const result2 = await popup2Promise;
|
||||
assert.strictEqual(result2.confirmed, false);
|
||||
|
||||
assert.strictEqual(root.el.querySelectorAll('.popup').length, 1);
|
||||
|
||||
testUtils.dom.triggerEvent(window, 'keyup', { key: 'Enter' });
|
||||
await testUtils.nextTick();
|
||||
|
||||
assert.strictEqual(root.el.querySelectorAll('.popup').length, 0);
|
||||
|
||||
const result1 = await popup1Promise;
|
||||
assert.strictEqual(result1.confirmed, true);
|
||||
});
|
||||
});
|
||||
Loading…
Add table
Add a link
Reference in a new issue