Files
odoo_source/addons/web/static/tests/views/layout_tests.js
T
3f086af2fd [REF] web: Layout: simpler and more generic API
With owl2, the `el` of components if no longer available. One must
use a t-ref instead. However, higher order components don't have
their own html element. This was the case of the View component.

However, it makes sense for this component to be the owner of the
view root element, which was previously owned by the Layout.

This commit refactors the View/Layout architecture s.t. the root
element is now owned by the View, and simplifies/generalizes the
Layout in the process. The Layout is no longer tied to the notion
of views, and can thus be used in client actions as well.

closes odoo/odoo#85639

Related: odoo/enterprise#24903
Signed-off-by: Aaron Bohy (aab) <aab@odoo.com>
Co-authored-by: Michael (mcm) <mcm@odoo.com>
Co-authored-by: Samuel Degueldre <sad@odoo.com>
2022-03-03 09:10:50 +00:00

261 lines
8.6 KiB
JavaScript

/** @odoo-module **/
import { getFixture, mount } from "@web/../tests/helpers/utils";
import { makeWithSearch, setupControlPanelServiceRegistry } from "@web/../tests/search/helpers";
import { dialogService } from "@web/core/dialog/dialog_service";
import { registry } from "@web/core/registry";
import { Layout } from "@web/search/layout";
import { getDefaultConfig } from "@web/views/view";
import { makeTestEnv } from "@web/../tests/helpers/mock_env";
const { Component, xml, useChildSubEnv } = owl;
const serviceRegistry = registry.category("services");
let target;
let serverData;
QUnit.module("Views", (hooks) => {
hooks.beforeEach(() => {
serverData = {
models: {
foo: {
fields: {
aaa: {
type: "selection",
selection: [
["a", "A"],
["b", "B"],
],
},
},
records: [],
},
},
views: {
"foo,false,search": /* xml */ `
<search>
<searchpanel>
<field name="aaa" />
</searchpanel>
</search>`,
},
};
setupControlPanelServiceRegistry();
serviceRegistry.add("dialog", dialogService);
target = getFixture();
});
QUnit.module("Layout");
QUnit.test("Simple rendering", async (assert) => {
class ToyComponent extends Component {}
ToyComponent.template = xml`
<Layout className="'o_view_sample_data'">
<div class="toy_content" />
</Layout>`;
ToyComponent.components = { Layout };
const env = await makeTestEnv({ config: {} });
await mount(ToyComponent, getFixture(), { env });
assert.containsOnce(target, ".o_view_sample_data");
assert.containsNone(target, ".o_control_panel");
assert.containsNone(target, ".o_component_with_search_panel");
assert.containsNone(target, ".o_search_panel");
assert.containsOnce(target, ".o_content > .toy_content");
});
QUnit.test("Simple rendering: with search", async (assert) => {
class ToyComponent extends Component {}
ToyComponent.template = xml`
<Layout>
<t t-set-slot="control-panel-top-right">
<div class="toy_search_bar" />
</t>
<div class="toy_content" />
</Layout>`;
ToyComponent.components = { Layout };
await makeWithSearch({
serverData,
Component: ToyComponent,
resModel: "foo",
searchViewId: false,
});
assert.containsOnce(target, ".o_control_panel .o_cp_top_right .toy_search_bar");
assert.containsOnce(target, ".o_component_with_search_panel .o_search_panel");
assert.containsNone(target, ".o_cp_searchview");
assert.containsOnce(target, ".o_content > .toy_content");
});
QUnit.test("Nested layouts", async (assert) => {
// Component C: bottom (no control panel)
class ToyC extends Component {
setup() {
useChildSubEnv({
searchModel: {
display: {
controlPanel: false,
searchPanel: true,
},
},
});
}
}
ToyC.template = xml`
<Layout className="'toy_c'">
<div class="toy_c_content" />
</Layout>`;
ToyC.components = { Layout };
// Component B: center (with custom search panel)
class SearchPanel extends Component {}
SearchPanel.template = xml`<div class="o_toy_search_panel" />`;
class ToyB extends Component {
setup() {
useChildSubEnv({
config: {
...getDefaultConfig(),
SearchPanel,
},
});
}
}
ToyB.template = xml`
<Layout className="'toy_b'">
<t t-set-slot="control-panel-top-right">
<div class="toy_b_breadcrumbs" />
</t>
<ToyC />
</Layout>`;
ToyB.components = { Layout, ToyC };
// Component A: top
class ToyA extends Component {}
ToyA.template = xml`
<Layout className="'toy_a'">
<t t-set-slot="control-panel-top-right">
<div class="toy_a_search" />
</t>
<ToyB />
</Layout>`;
ToyA.components = { Layout, ToyB };
await makeWithSearch({
serverData,
Component: ToyA,
resModel: "foo",
searchViewId: false,
});
assert.containsOnce(target, ".o_content.toy_a .o_content.toy_b .o_content.toy_c"); // Full chain of contents
assert.containsN(target, ".o_control_panel", 2); // Component C has hidden its control panel
assert.containsN(target, ".o_content.o_component_with_search_panel", 3);
assert.containsOnce(target, ".o_search_panel"); // Standard search panel
assert.containsN(target, ".o_toy_search_panel", 2); // Custom search panels
assert.containsOnce(target, ".toy_a_search");
assert.containsOnce(target, ".toy_b_breadcrumbs");
assert.containsOnce(target, ".toy_c_content");
});
QUnit.test("Custom control panel", async (assert) => {
class ToyComponent extends Component {}
ToyComponent.template = xml`
<Layout>
<div class="o_toy_content" />
</Layout>`;
ToyComponent.components = { Layout };
class ControlPanel extends Component {}
ControlPanel.template = xml`<div class="o_toy_search_panel" />`;
await makeWithSearch({
serverData,
Component: ToyComponent,
resModel: "foo",
searchViewId: false,
config: { ControlPanel },
});
assert.containsOnce(target, ".o_toy_content");
assert.containsOnce(target, ".o_toy_search_panel");
assert.containsNone(target, ".o_control_panel");
});
QUnit.test("Custom search panel", async (assert) => {
class ToyComponent extends Component {}
ToyComponent.template = xml`
<Layout>
<div class="o_toy_content" />
</Layout>`;
ToyComponent.components = { Layout };
class SearchPanel extends Component {}
SearchPanel.template = xml`<div class="o_toy_search_panel" />`;
await makeWithSearch({
serverData,
Component: ToyComponent,
resModel: "foo",
searchViewId: false,
config: { SearchPanel },
});
assert.containsOnce(target, ".o_toy_content");
assert.containsOnce(target, ".o_toy_search_panel");
assert.containsNone(target, ".o_search_panel");
});
QUnit.test("Custom banner: no bannerRoute in env", async (assert) => {
class ToyComponent extends Component {}
ToyComponent.template = xml`
<Layout>
<div class="o_toy_content" />
</Layout>`;
ToyComponent.components = { Layout };
class Banner extends Component {}
Banner.template = xml`<div class="o_toy_banner" />`;
await makeWithSearch({
serverData,
Component: ToyComponent,
resModel: "foo",
searchViewId: false,
config: { Banner },
});
assert.containsOnce(target, ".o_toy_content");
assert.containsNone(target, ".o_toy_banner");
});
QUnit.test("Custom banner: with bannerRoute in env", async (assert) => {
class ToyComponent extends Component {}
ToyComponent.template = xml`
<Layout>
<div class="o_toy_content" />
</Layout>`;
ToyComponent.components = { Layout };
class Banner extends Component {}
Banner.template = xml`<div class="o_toy_banner" />`;
await makeWithSearch({
serverData,
Component: ToyComponent,
resModel: "foo",
searchViewId: false,
config: { Banner, bannerRoute: "toy/banner/route" },
});
assert.containsOnce(target, ".o_toy_content");
assert.containsOnce(target, ".o_toy_banner");
});
});