This commit is a significant rewriting of client-side discuss, chatter, chat window, and messaging menu using OWL. The behavior should be broadly the same, with some slight functional changes here and there. From a technical standpoint, the code of messaging is mainly organized in 2 main groups of modules: - models, which are logical entities that depict the client-side state of messaging as a whole. - components, which are in charge of displaying information from models. This refactoring also introduces new JS guidelines regarding folder structure (/static) and naming rules for JS modules. Community PR: https://github.com/odoo/odoo/pull/39023 Enterprise PR: https://github.com/odoo/enterprise/pull/6249 Task-1914207 This PR is a collaborative work by Alexandre, Julien, Sébastien and Xavier, with the precious help of Lucas to speed it up towards the end. closes odoo/odoo#39023 Related: odoo/enterprise#6249 Signed-off-by: Alexandre Kühn (aku) <aku@odoo.com> Co-authored-by: Alexandre Kühn <aku@odoo.com> Co-authored-by: Julien Giannone <jgi@odoo.com> Co-authored-by: Lucas Perais <lpe@odoo.com> Co-authored-by: Sébastien Theys <seb@odoo.com> Co-authored-by: Xavier Dubuc <xdu@odoo.com>
432 lines
11 KiB
JavaScript
432 lines
11 KiB
JavaScript
odoo.define('mail/static/src/utils/timer/timer_tests.js', function (require) {
|
|
'use strict';
|
|
|
|
const {
|
|
afterEach: utilsAfterEach,
|
|
beforeEach: utilsBeforeEach,
|
|
start,
|
|
} = require('mail/static/src/utils/test_utils.js');
|
|
const Timer = require('mail/static/src/utils/timer/timer.js');
|
|
const { nextTick } = require('mail/static/src/utils/test_utils.js');
|
|
|
|
const { TimerClearedError } = Timer;
|
|
|
|
QUnit.module('mail', {}, function () {
|
|
QUnit.module('utils', {}, function () {
|
|
QUnit.module('timer', {}, function () {
|
|
QUnit.module('timer_tests.js', {
|
|
beforeEach() {
|
|
utilsBeforeEach(this);
|
|
this.timers = [];
|
|
|
|
this.start = async (...args) => {
|
|
const { env, widget } = await start(...args);
|
|
this.env = env;
|
|
this.widget = widget;
|
|
};
|
|
},
|
|
afterEach() {
|
|
utilsAfterEach(this);
|
|
// Important: tests should cleanly intercept cancelation errors that
|
|
// may result from this teardown.
|
|
this.widget.destroy();
|
|
for (const timer of this.timers) {
|
|
timer.clear();
|
|
}
|
|
},
|
|
});
|
|
|
|
QUnit.test('timer does not timeout on initialization', async function (assert) {
|
|
assert.expect(3);
|
|
|
|
await this.start({
|
|
hasTimeControl: true,
|
|
});
|
|
|
|
let hasTimedOut = false;
|
|
this.timers.push(
|
|
new Timer(
|
|
this.env,
|
|
() => hasTimedOut = true,
|
|
0
|
|
)
|
|
);
|
|
|
|
assert.notOk(
|
|
hasTimedOut,
|
|
"timer should not have timed out on immediate initialization"
|
|
);
|
|
|
|
await this.env.testUtils.advanceTime(0);
|
|
assert.notOk(
|
|
hasTimedOut,
|
|
"timer should not have timed out from initialization after 0ms"
|
|
);
|
|
|
|
await this.env.testUtils.advanceTime(1000 * 1000);
|
|
assert.notOk(
|
|
hasTimedOut,
|
|
"timer should not have timed out from initialization after 1000s"
|
|
);
|
|
});
|
|
|
|
QUnit.test('timer start (duration: 0ms)', async function (assert) {
|
|
assert.expect(2);
|
|
|
|
await this.start({
|
|
hasTimeControl: true,
|
|
});
|
|
|
|
let hasTimedOut = false;
|
|
this.timers.push(
|
|
new Timer(
|
|
this.env,
|
|
() => hasTimedOut = true,
|
|
0
|
|
)
|
|
);
|
|
|
|
this.timers[0].start();
|
|
assert.notOk(
|
|
hasTimedOut,
|
|
"timer should not have timed out immediately after start"
|
|
);
|
|
|
|
await this.env.testUtils.advanceTime(0);
|
|
assert.ok(
|
|
hasTimedOut,
|
|
"timer should have timed out on start after 0ms"
|
|
);
|
|
});
|
|
|
|
QUnit.test('timer start observe termination (duration: 0ms)', async function (assert) {
|
|
assert.expect(6);
|
|
|
|
await this.start({
|
|
hasTimeControl: true,
|
|
});
|
|
|
|
let hasTimedOut = false;
|
|
this.timers.push(
|
|
new Timer(
|
|
this.env,
|
|
() => {
|
|
hasTimedOut = true;
|
|
return 'timeout_result';
|
|
},
|
|
0
|
|
)
|
|
);
|
|
|
|
this.timers[0].start()
|
|
.then(result => {
|
|
assert.strictEqual(
|
|
result,
|
|
'timeout_result',
|
|
"value returned by start should be value returned by function on timeout"
|
|
);
|
|
assert.step('timeout');
|
|
});
|
|
await nextTick();
|
|
assert.notOk(
|
|
hasTimedOut,
|
|
"timer should not have timed out immediately after start"
|
|
);
|
|
assert.verifySteps(
|
|
[],
|
|
"timer.start() should not have yet observed timeout"
|
|
);
|
|
|
|
await this.env.testUtils.advanceTime(0);
|
|
assert.ok(
|
|
hasTimedOut,
|
|
"timer should have timed out on start after 0ms"
|
|
);
|
|
assert.verifySteps(
|
|
['timeout'],
|
|
"timer.start() should have observed timeout after 0ms"
|
|
);
|
|
});
|
|
|
|
QUnit.test('timer start (duration: 1000s)', async function (assert) {
|
|
assert.expect(5);
|
|
|
|
await this.start({
|
|
hasTimeControl: true,
|
|
});
|
|
|
|
let hasTimedOut = false;
|
|
this.timers.push(
|
|
new Timer(
|
|
this.env,
|
|
() => hasTimedOut = true,
|
|
1000 * 1000
|
|
)
|
|
);
|
|
|
|
this.timers[0].start();
|
|
assert.notOk(
|
|
hasTimedOut,
|
|
"timer should not have timed out immediately after start"
|
|
);
|
|
|
|
await this.env.testUtils.advanceTime(0);
|
|
assert.notOk(
|
|
hasTimedOut,
|
|
"timer should not have timed out on start after 0ms"
|
|
);
|
|
|
|
await this.env.testUtils.advanceTime(1000);
|
|
assert.notOk(
|
|
hasTimedOut,
|
|
"timer should not have timed out on start after 1000ms"
|
|
);
|
|
|
|
await this.env.testUtils.advanceTime(998 * 1000 + 999);
|
|
assert.notOk(
|
|
hasTimedOut,
|
|
"timer should not have timed out on start after 9999ms"
|
|
);
|
|
|
|
await this.env.testUtils.advanceTime(1);
|
|
assert.ok(
|
|
hasTimedOut,
|
|
"timer should have timed out on start after 10s"
|
|
);
|
|
});
|
|
|
|
QUnit.test('[no cancelation intercept] timer start then immediate clear (duration: 0ms)', async function (assert) {
|
|
assert.expect(4);
|
|
|
|
await this.start({
|
|
hasTimeControl: true,
|
|
});
|
|
|
|
let hasTimedOut = false;
|
|
this.timers.push(
|
|
new Timer(
|
|
this.env,
|
|
() => hasTimedOut = true,
|
|
0
|
|
)
|
|
);
|
|
|
|
this.timers[0].start();
|
|
assert.notOk(
|
|
hasTimedOut,
|
|
"timer should not have timed out immediately after start"
|
|
);
|
|
|
|
this.timers[0].clear();
|
|
assert.notOk(
|
|
hasTimedOut,
|
|
"timer should not have timed out immediately after start and clear"
|
|
);
|
|
|
|
await this.env.testUtils.advanceTime(0);
|
|
assert.notOk(
|
|
hasTimedOut,
|
|
"timer should not have timed out after 0ms of clear"
|
|
);
|
|
|
|
await this.env.testUtils.advanceTime(1000);
|
|
assert.notOk(
|
|
hasTimedOut,
|
|
"timer should not have timed out after 1s of clear"
|
|
);
|
|
});
|
|
|
|
QUnit.test('[no cancelation intercept] timer start then clear before timeout (duration: 1000ms)', async function (assert) {
|
|
assert.expect(4);
|
|
|
|
await this.start({
|
|
hasTimeControl: true,
|
|
});
|
|
|
|
let hasTimedOut = false;
|
|
this.timers.push(
|
|
new Timer(
|
|
this.env,
|
|
() => hasTimedOut = true,
|
|
1000
|
|
)
|
|
);
|
|
|
|
this.timers[0].start();
|
|
assert.notOk(
|
|
hasTimedOut,
|
|
"timer should not have timed out immediately after start"
|
|
);
|
|
|
|
await this.env.testUtils.advanceTime(999);
|
|
assert.notOk(
|
|
hasTimedOut,
|
|
"timer should not have timed out immediately after 999ms of start"
|
|
);
|
|
|
|
this.timers[0].clear();
|
|
await this.env.testUtils.advanceTime(1);
|
|
assert.notOk(
|
|
hasTimedOut,
|
|
"timer should not have timed out after 1ms of clear that happens 999ms after start (globally 1s await)"
|
|
);
|
|
|
|
await this.env.testUtils.advanceTime(1000);
|
|
assert.notOk(
|
|
hasTimedOut,
|
|
"timer should not have timed out after 1001ms after clear (timer fully cleared)"
|
|
);
|
|
});
|
|
|
|
QUnit.test('[no cancelation intercept] timer start then reset before timeout (duration: 1000ms)', async function (assert) {
|
|
assert.expect(5);
|
|
|
|
await this.start({
|
|
hasTimeControl: true,
|
|
});
|
|
|
|
let hasTimedOut = false;
|
|
this.timers.push(
|
|
new Timer(
|
|
this.env,
|
|
() => hasTimedOut = true,
|
|
1000
|
|
)
|
|
);
|
|
|
|
this.timers[0].start();
|
|
assert.notOk(
|
|
hasTimedOut,
|
|
"timer should not have timed out immediately after start"
|
|
);
|
|
|
|
await this.env.testUtils.advanceTime(999);
|
|
assert.notOk(
|
|
hasTimedOut,
|
|
"timer should not have timed out after 999ms of start"
|
|
);
|
|
|
|
this.timers[0].reset();
|
|
await this.env.testUtils.advanceTime(1);
|
|
assert.notOk(
|
|
hasTimedOut,
|
|
"timer should not have timed out after 1ms of reset which happens 999ms after start"
|
|
);
|
|
|
|
await this.env.testUtils.advanceTime(998);
|
|
assert.notOk(
|
|
hasTimedOut,
|
|
"timer should not have timed out after 999ms of reset"
|
|
);
|
|
|
|
await this.env.testUtils.advanceTime(1);
|
|
assert.ok(
|
|
hasTimedOut,
|
|
"timer should not have timed out after 1s of reset"
|
|
);
|
|
});
|
|
|
|
QUnit.test('[with cancelation intercept] timer start then immediate clear (duration: 0ms)', async function (assert) {
|
|
assert.expect(5);
|
|
|
|
await this.start({
|
|
hasTimeControl: true,
|
|
});
|
|
|
|
let hasTimedOut = false;
|
|
this.timers.push(
|
|
new Timer(
|
|
this.env,
|
|
() => hasTimedOut = true,
|
|
0,
|
|
{ silentCancelationErrors: false }
|
|
)
|
|
);
|
|
|
|
this.timers[0].start()
|
|
.then(() => {
|
|
throw new Error("timer.start() should not be resolved (should have been canceled by clear)");
|
|
})
|
|
.catch(error => {
|
|
assert.ok(
|
|
error instanceof TimerClearedError,
|
|
"Should generate a Timer cleared error (from `.clear()`)"
|
|
);
|
|
assert.step('timer_cleared');
|
|
});
|
|
assert.notOk(
|
|
hasTimedOut,
|
|
"timer should not have timed out immediately after start"
|
|
);
|
|
await nextTick();
|
|
assert.verifySteps([], "should not have observed cleared timer (timer not yet cleared)");
|
|
|
|
this.timers[0].clear();
|
|
await nextTick();
|
|
assert.verifySteps(
|
|
['timer_cleared'],
|
|
"timer.start() should have observed it has been cleared"
|
|
);
|
|
});
|
|
|
|
QUnit.test('[with cancelation intercept] timer start then immediate reset (duration: 0ms)', async function (assert) {
|
|
assert.expect(9);
|
|
|
|
await this.start({
|
|
hasTimeControl: true,
|
|
});
|
|
|
|
let hasTimedOut = false;
|
|
this.timers.push(
|
|
new Timer(
|
|
this.env,
|
|
() => hasTimedOut = true,
|
|
0,
|
|
{ silentCancelationErrors: false }
|
|
)
|
|
);
|
|
|
|
this.timers[0].start()
|
|
.then(() => {
|
|
throw new Error("timer.start() should not observe a timeout");
|
|
})
|
|
.catch(error => {
|
|
assert.ok(error instanceof TimerClearedError, "Should generate a Timer cleared error (from `.reset()`)");
|
|
assert.step('timer_cleared');
|
|
});
|
|
assert.notOk(
|
|
hasTimedOut,
|
|
"timer should not have timed out immediately after start"
|
|
);
|
|
await nextTick();
|
|
assert.verifySteps([], "should not have observed cleared timer (timer not yet cleared)");
|
|
|
|
this.timers[0].reset()
|
|
.then(() => assert.step('timer_reset_timeout'));
|
|
await nextTick();
|
|
assert.verifySteps(
|
|
['timer_cleared'],
|
|
"timer.start() should have observed it has been cleared"
|
|
);
|
|
assert.notOk(
|
|
hasTimedOut,
|
|
"timer should not have timed out immediately after reset"
|
|
);
|
|
|
|
await this.env.testUtils.advanceTime(0);
|
|
assert.ok(
|
|
hasTimedOut,
|
|
"timer should have timed out after reset timeout"
|
|
);
|
|
assert.verifySteps(
|
|
['timer_reset_timeout'],
|
|
"timer.reset() should have observed it has timed out"
|
|
);
|
|
});
|
|
|
|
});
|
|
});
|
|
});
|
|
|
|
});
|