diff --git a/addons/web/static/src/core/field_service.js b/addons/web/static/src/core/field_service.js index 99555dd17a2..87bdd35be26 100644 --- a/addons/web/static/src/core/field_service.js +++ b/addons/web/static/src/core/field_service.js @@ -12,6 +12,7 @@ import { registry } from "@web/core/registry"; export const fieldService = { dependencies: ["orm"], + async: ["loadFields", "loadPath", "loadPropertyDefinitions"], start(env, { orm }) { const cache = new Cache( (resModel, options) => { diff --git a/addons/web/static/tests/core/field_service_tests.js b/addons/web/static/tests/core/field_service_tests.js index c18fe3249ce..a9deba1c053 100644 --- a/addons/web/static/tests/core/field_service_tests.js +++ b/addons/web/static/tests/core/field_service_tests.js @@ -3,6 +3,9 @@ import { fieldService } from "@web/core/field_service"; import { makeTestEnv } from "@web/../tests/helpers/mock_env"; import { registry } from "@web/core/registry"; +import { Component, useState, xml } from "@odoo/owl"; +import { useService } from "@web/core/utils/hooks"; +import { getFixture, makeDeferred, mount, nextTick } from "@web/../tests/helpers/utils"; const serviceRegistry = registry.category("services"); @@ -270,3 +273,65 @@ QUnit.test("does not store loadFields calls in cache when failed", async (assert assert.verifySteps(["fields_get", "fields_get"]); }); + +QUnit.test("async method loadFields is protected", async (assert) => { + assert.expect(7); + + let callFieldService; + class Child extends Component { + static template = xml` +
+ `; + setup() { + this.fieldService = useService("field"); + callFieldService = async () => { + assert.step("loadFields called"); + await this.fieldService.loadFields("tortoise"); + assert.step("loadFields result get"); + }; + } + } + + class Parent extends Component { + static components = { Child }; + static template = xml` + + + + `; + setup() { + this.state = useState({ displayChild: true }); + } + } + + const target = getFixture(); + const def = makeDeferred(); + const env = await makeTestEnv({ + serverData, + async mockRPC() { + await def; + }, + }); + const parent = await mount(Parent, target, { env }); + + assert.containsOnce(target, ".o_child_component"); + + callFieldService(); + assert.verifySteps(["loadFields called"]); + + parent.state.displayChild = false; + await nextTick(); + + def.resolve(); + await nextTick(); + + assert.verifySteps([]); + + try { + await callFieldService(); + } catch (e) { + assert.step(e.message); + } + + assert.verifySteps(["loadFields called", "Component is destroyed"]); +});