[FIX] web: remove lazyloaded controller from stack

... if the current action can't be executed.

Let's assume a form view for a record with a multicompany ir.rule.
If the user switches to another company, the webclient is reloaded,
but he doesn't have access to that record anymore. In this case,
he is redirected to the Home menu.

Before this rev., when he clicked on an app in this situation, it
crashed. This was due to a leftover reference of the failed action
(the lazyloaded, multi-record controller) in the controller stack.

closes odoo/odoo#34994

Signed-off-by: VincentSchippefilt <VincentSchippefilt@users.noreply.github.com>
This commit is contained in:
Aaron Bohy
2019-07-19 12:07:56 +00:00
parent e266c7c98a
commit 04a600486e
2 changed files with 44 additions and 1 deletions
@@ -285,6 +285,7 @@ ActionManager.include({
}
var lazyViewDef;
var lazyControllerID;
if (lazyView) {
// if the main view is lazy-loaded, its (lazy-loaded) controller is inserted
// into the controller stack (so that breadcrumbs can be correctly computed),
@@ -294,6 +295,7 @@ ActionManager.include({
// this controller being lazy-loaded, this call is actually sync
lazyViewDef = self._createViewController(action, lazyView.type, {}, {lazy: true})
.then(function (lazyLoadedController) {
lazyControllerID = lazyLoadedController.jsID;
self.controllerStack.push(lazyLoadedController.jsID);
});
}
@@ -312,7 +314,13 @@ ActionManager.include({
action.controllerID = controller.jsID;
return self._executeAction(action, options);
})
.fail(self._destroyWindowAction.bind(self, action));
.fail(function () {
if (lazyControllerID) {
var index = self.controllerStack.indexOf(lazyControllerID);
self.controllerStack = self.controllerStack.slice(0, index);
}
self._destroyWindowAction(action);
});
});
},
/**
@@ -877,6 +877,41 @@ QUnit.module('ActionManager', {
actionManager.destroy();
});
QUnit.test('lazy loaded multi record view with failing mono record one', function (assert) {
assert.expect(4);
var actionManager = createActionManager({
actions: this.actions,
archs: this.archs,
data: this.data,
mockRPC: function (route, args) {
if (args.method === 'read') {
return $.Deferred().reject();
}
return this._super.apply(this, arguments);
},
});
actionManager.loadState({
action: 3,
id: 2,
view_type: 'form',
}).then(function () {
assert.ok(false, 'should not resolve the deferred');
}).fail(function () {
assert.ok(true, 'should reject the deferred');
});
assert.containsNone(actionManager, '.o_form_view');
assert.containsNone(actionManager, '.o_list_view');
actionManager.doAction(1);
assert.containsOnce(actionManager, '.o_kanban_view');
actionManager.destroy();
});
QUnit.test('change the viewType of the current action', function (assert) {
assert.expect(13);