[FIX] web: owl compatibility test helper fix
The `afternextrender` helper is meant to be used in some tests that want to do something after owl has completed all its work following a specific action. It is useful when the action may cause some additional renders, so waiting for one nextTick is not enough. Unfortunately, it has a bug: it waits for Owl scheduler to be empty. But in some cases, when a component is destroyed because of an error, the scheduler task list will not be cleared until the next render completes. It is implemented that way in Owl to reduce the amount of work it does. But this means that in some testing scenarios, the afterNextRender promise will simply not be resolved, since there is no upcoming render to clear the tasklist. With this commit, we just avoid the issue by ignoring the fibers coming from destroyed component. Note that I think that it is not a good semantic for tests, as it is a little bit too "black-boxy". Ideally, we should rather wait for something in the DOM. There is a waitUntil helper somewhere that may be useful for this situation closes odoo/odoo#115229 X-original-commit: ca8d1e7ea74120dd088c78bb4916aa994e852a0f Signed-off-by: Aaron Bohy (aab) <aab@odoo.com> Signed-off-by: Géry Debongnie <ged@odoo.com>
This commit is contained in:
@@ -4,12 +4,21 @@
|
||||
const stopPromises = [];
|
||||
const schedulers = new Set();
|
||||
|
||||
function isRunning(scheduler) {
|
||||
for (const fiber of scheduler.tasks) {
|
||||
if (fiber.node.status !== 2) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function hookIntoScheduler(scheduler) {
|
||||
const { flush: originalFlush } = scheduler;
|
||||
scheduler.flush = function flush() {
|
||||
originalFlush.call(this, ...arguments);
|
||||
window.requestAnimationFrame(() => {
|
||||
if ([...schedulers].every(({ tasks }) => tasks.size === 0)) {
|
||||
if ([...schedulers].every((scheduler) => !isRunning(scheduler))) {
|
||||
while (stopPromises.length) {
|
||||
stopPromises.pop().resolve();
|
||||
}
|
||||
@@ -47,10 +56,11 @@
|
||||
const stopError = new Error("Timeout: the render didn't stop.");
|
||||
// Set up the timeout to reject if no render happens.
|
||||
let timeoutNoRender;
|
||||
|
||||
const timeoutProm = new Promise((resolve, reject) => {
|
||||
timeoutNoRender = setTimeout(() => {
|
||||
let error = startError;
|
||||
const runningSchedulers = [...schedulers].filter(({ tasks }) => tasks.size > 0);
|
||||
const runningSchedulers = [...schedulers].filter(isRunning);
|
||||
if (runningSchedulers.length) {
|
||||
error = stopError;
|
||||
}
|
||||
@@ -82,7 +92,7 @@
|
||||
await new Promise(function (resolve) {
|
||||
setTimeout(() => window.requestAnimationFrame(() => resolve()));
|
||||
});
|
||||
if ([...schedulers].some(({ tasks }) => tasks.size > 0)) {
|
||||
if ([...schedulers].some(isRunning)) {
|
||||
await afterNextRender(() => {}, timeoutDelay);
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user