/** @odoo-module **/ import { getFixture, legacyExtraNextTick, patchWithCleanup } from "@web/../tests/helpers/utils"; import { getFacetTexts, removeFacet, saveFavorite, setupControlPanelFavoriteMenuRegistry, setupControlPanelServiceRegistry, switchView, toggleFavoriteMenu, toggleMenu, toggleMenuItem, toggleSaveFavorite, } from "@web/../tests/search/helpers"; import { createWebClient, doAction } from "@web/../tests/webclient/helpers"; import { _lt } from "@web/core/l10n/translation"; import { registry } from "@web/core/registry"; import { ControlPanel } from "@web/search/control_panel/control_panel"; import { SearchModel } from "@web/search/search_model"; import AbstractView from "web.AbstractView"; import ActionModel from "web.ActionModel"; import { mock } from "web.test_utils"; import legacyViewRegistry from "web.view_registry"; import { browser } from "@web/core/browser/browser"; import { LegacyComponent } from "@web/legacy/legacy_component"; import { xml } from "@odoo/owl"; const viewRegistry = registry.category("views"); let serverData; let target; QUnit.module("LegacyViews", (hooks) => { hooks.beforeEach(async () => { target = getFixture(); serverData = { models: { foo: { fields: { display_name: { string: "Displayed name", type: "char" }, foo: { string: "Foo", type: "char", default: "My little Foo Value", store: true, sortable: true, }, date_field: { string: "Date", type: "date", store: true, sortable: true }, float_field: { string: "Float", type: "float" }, bar: { string: "Bar", type: "many2one", relation: "partner", store: true, sortable: true, }, }, records: [], }, }, views: { "foo,false,legacy_toy": ``, "foo,false,toy": ``, "foo,false,search": ` `, }, }; setupControlPanelFavoriteMenuRegistry(); setupControlPanelServiceRegistry(); class ToyController extends LegacyComponent {} ToyController.template = xml`
`; ToyController.components = { ControlPanel}; viewRegistry.add("toy", { type: "toy", display_name: _lt("Toy view"), multiRecord: true, searchMenuTypes: ["filter", "groupBy", "comparison", "favorite"], Controller: ToyController, }); const LegacyToyView = AbstractView.extend({ display_name: _lt("Legacy toy view"), icon: "fa fa-bars", multiRecord: true, viewType: "legacy_toy", searchMenuTypes: ["filter", "groupBy", "comparison", "favorite"], }); legacyViewRegistry.add("legacy_toy", LegacyToyView); }); QUnit.module("State Mappings"); QUnit.test( "legacy and new views can share search model state (no favorite)", async function (assert) { assert.expect(10); const unpatchDate = mock.patchDate(2021, 6, 1, 10, 0, 0); const webClient = await createWebClient({ serverData }); await doAction(webClient, { name: "Action name", res_model: "foo", type: "ir.actions.act_window", views: [ [false, "toy"], [false, "legacy_toy"], ], context: { search_default_foo: "ABC", search_default_true_domain: 1, search_default_date_domain: 1, search_default_group_by_bar: 50, search_default_group_by_date_field: 1, }, }); assert.containsOnce(target, ".o_switch_view.o_toy.active"); assert.deepEqual( getFacetTexts(target).map((s) => s.replace(/\s/, "")), [ "FooABC", "TrueDomainorDate Filter: July 2021", "DateGroupBy: Month>Bar", ] ); await toggleMenu(target, "Comparison"); await toggleMenuItem(target, "Date Filter: Previous Period"); assert.deepEqual( getFacetTexts(target).map((s) => s.replace(/\s/, "")), [ "FooABC", "TrueDomainorDate Filter: July 2021", "DateGroupBy: Month>Bar", "DateFilter: Previous Period", ] ); await switchView(target, "legacy_toy"); await legacyExtraNextTick(); assert.containsOnce(target, ".o_switch_view.o_legacy_toy.active"); assert.deepEqual( getFacetTexts(target).map((s) => s.replace(/\s/, "")), [ "FooABC", "TrueDomainorDate Filter: July 2021", "DateGroupBy: Month>Bar", "DateFilter: Previous Period", ] ); await removeFacet(target, 1); assert.deepEqual( getFacetTexts(target).map((s) => s.replace(/\s/, "")), [ "FooABC", "DateGroupBy: Month>Bar", ] ); await switchView(target, "toy"); assert.containsOnce(target, ".o_switch_view.o_toy.active"); assert.deepEqual( getFacetTexts(target).map((s) => s.replace(/\s/, "")), [ "FooABC", "DateGroupBy: Month>Bar", ] ); // Check if update works await removeFacet(target, 1); assert.deepEqual( getFacetTexts(target).map((s) => s.replace(/\s/, "")), [ "FooABC", ] ); await switchView(target, "legacy_toy"); assert.deepEqual( getFacetTexts(target).map((s) => s.replace(/\s/, "")), [ "FooABC", ] ); unpatchDate(); } ); QUnit.test( "legacy and new views can share search model state (favorite)", async function (assert) { assert.expect(6); serverData.models.foo.filters = [ { context: "{}", domain: "[['foo', '=', 'qsdf']]", id: 7, is_default: true, name: "My favorite", sort: "[]", user_id: [2, "Mitchell Admin"], }, ]; const webClient = await createWebClient({ serverData }); await doAction(webClient, { name: "Action name", res_model: "foo", type: "ir.actions.act_window", views: [ [false, "toy"], [false, "legacy_toy"], ], }); assert.containsOnce(target, ".o_switch_view.o_toy.active"); assert.deepEqual(getFacetTexts(target), ["My favorite"]); await switchView(target, "legacy_toy"); await legacyExtraNextTick(); assert.containsOnce(target, ".o_switch_view.o_legacy_toy.active"); assert.deepEqual(getFacetTexts(target), ["My favorite"]); await switchView(target, "toy"); assert.containsOnce(target, ".o_switch_view.o_toy.active"); assert.deepEqual(getFacetTexts(target), ["My favorite"]); } ); QUnit.test( "newly created favorite in a new view can be used in a legacy view", async function (assert) { assert.expect(5); patchWithCleanup(browser, { setTimeout: (fn) => fn() }); const webClient = await createWebClient({ serverData, mockRPC(_, args) { if (args.method === "create_or_replace") { assert.ok(typeof args.args[0].domain === "string"); return 7; // fake serverId to simulate the creation of // the favorite in db. } }, }); await doAction(webClient, { name: "Action name", res_model: "foo", type: "ir.actions.act_window", views: [ [false, "toy"], [false, "legacy_toy"], ], }); assert.containsOnce(target, ".o_switch_view.o_toy.active"); await toggleFavoriteMenu(target); await toggleSaveFavorite(target); await saveFavorite(target); assert.deepEqual(getFacetTexts(target), ["Action name"]); await switchView(target, "legacy_toy"); await legacyExtraNextTick(); assert.containsOnce(target, ".o_switch_view.o_legacy_toy.active"); assert.deepEqual(getFacetTexts(target), ["Action name"]); } ); QUnit.test( "legacy and new views with search model extensions can share search model state", async function (assert) { assert.expect(16); serverData.views[ "foo,1,legacy_toy" ] = ``; class SearchModelExtension extends SearchModel { setup() { super.setup(...arguments); this.toyExtension = { locationId: "Grand-Rosière" }; } exportState() { const exportedState = super.exportState(...arguments); exportedState.toyExtension = this.toyExtension; return exportedState; } _importState(state) { super._importState(state); this.toyExtension = state.toyExtension; assert.step(JSON.stringify(state.toyExtension)); } } const ToyView = viewRegistry.get("toy"); ToyView.SearchModel = SearchModelExtension; class ToyExtension extends ActionModel.Extension { importState(state) { super.importState(state); // done even if state is undefined in legacy code assert.step(JSON.stringify(state) || "no state"); } prepareState() { Object.assign(this.state, { locationId: "The place to be", }); } } ActionModel.registry.add("toyExtension", ToyExtension); const LegacyToyView = legacyViewRegistry.get("legacy_toy"); const LegacyToyViewWithExtension = LegacyToyView.extend({ _createSearchModel(params, extraExtensions = {}) { Object.assign(extraExtensions, { toyExtension: {} }); return this._super(params, extraExtensions); }, }); legacyViewRegistry.add("legacy_toy_with_extension", LegacyToyViewWithExtension); const webClient = await createWebClient({ serverData }); await doAction(webClient, { name: "Action name", res_model: "foo", type: "ir.actions.act_window", views: [ [false, "toy"], [1, "legacy_toy"], ], }); assert.containsOnce(target, ".o_switch_view.o_toy.active"); await switchView(target, "legacy_toy"); await legacyExtraNextTick(); assert.containsOnce(target, ".o_switch_view.o_legacy_toy.active"); assert.verifySteps([`{"locationId":"Grand-Rosière"}`]); await switchView(target, "toy"); assert.containsOnce(target, ".o_switch_view.o_toy.active"); assert.verifySteps([`{"locationId":"Grand-Rosière"}`]); await doAction(webClient, { name: "Action name", res_model: "foo", type: "ir.actions.act_window", views: [ [1, "legacy_toy"], [false, "toy"], ], }); await legacyExtraNextTick(); assert.containsOnce(target, ".o_switch_view.o_legacy_toy.active"); assert.verifySteps([`no state`]); await switchView(target, "toy"); assert.containsOnce(target, ".o_switch_view.o_toy.active"); assert.verifySteps([`{"locationId":"The place to be"}`]); await switchView(target, "legacy_toy"); await legacyExtraNextTick(); assert.containsOnce(target, ".o_switch_view.o_legacy_toy.active"); assert.verifySteps([`{"locationId":"The place to be"}`]); } ); });