import { expect, test } from "@odoo/hoot";
import { animationFrame } from "@odoo/hoot-mock";
import { click, queryFirst } from "@odoo/hoot-dom";
import { Component, xml } from "@odoo/owl";
import { mountWithCleanup } from "@web/../tests/web_test_helpers";
import { Notebook } from "@web/core/notebook/notebook";
test("not rendered if empty slots", async () => {
await mountWithCleanup(Notebook);
expect("div.o_notebook").toHaveCount(0);
});
test("notebook with multiple pages given as slots", async () => {
class Parent extends Component {
static template = xml`
About the bird
Owls are birds from the order Strigiformes which includes over
200 species of mostly solitary and nocturnal birds of prey typified by an upright stance, ...
Their favorite activity: hunting
Owls are called raptors, or birds of prey, which means they use sharp talons and curved bills to hunt, kill, and eat other animals.
TODO find a great secret about OWLs.
`;
static components = { Notebook };
static props = ["*"];
}
await mountWithCleanup(Parent);
expect("div.o_notebook").toHaveCount(1);
expect(".o_notebook").toHaveClass("horizontal", {
message: "default orientation is set as horizontal",
});
expect(".nav").toHaveClass("flex-row", {
message: "navigation container uses the right class to display as horizontal tabs",
});
expect(".o_notebook_headers a.nav-link").toHaveCount(2, {
message: "navigation link is present for each visible page",
});
expect(".o_notebook_headers .nav-item:first-child a").toHaveClass("active", {
message: "first page is selected by default",
});
expect(".active h3").toHaveText("About the bird", {
message: "first page content is displayed by the notebook",
});
await click(".o_notebook_headers .nav-item:nth-child(2) a");
await animationFrame();
expect(".o_notebook_headers .nav-item:nth-child(2) a").toHaveClass("active", {
message: "second page is now selected",
});
expect(".active h3").toHaveText("Their favorite activity: hunting", {
message: "second page content is displayed by the notebook",
});
});
test("notebook with defaultPage props", async () => {
class Parent extends Component {
static template = xml`
About the bird
Owls are birds from the order Strigiformes which includes over
200 species of mostly solitary and nocturnal birds of prey typified by an upright stance, ...
Their favorite activity: hunting
Owls are called raptors, or birds of prey, which means they use sharp talons and curved bills to hunt, kill, and eat other animals.
TODO find a great secret about OWLs.
`;
static components = { Notebook };
static props = ["*"];
}
await mountWithCleanup(Parent);
expect("div.o_notebook").toHaveCount(1);
expect(".o_notebook_headers .nav-item:nth-child(2) a").toHaveClass("active", {
message: "second page is selected by default",
});
expect(".active h3").toHaveText("Their favorite activity: hunting", {
message: "second page content is displayed by the notebook",
});
});
test("notebook with defaultPage set on invisible page", async () => {
class Parent extends Component {
static template = xml`
About the bird
Owls are birds from the order Strigiformes which includes over
200 species of mostly solitary and nocturnal birds of prey typified by an upright stance, ...
Their favorite activity: hunting
Owls are called raptors, or birds of prey, which means they use sharp talons and curved bills to hunt, kill, and eat other animals.
Oooops
TODO find a great secret to reveal about OWLs.
`;
static components = { Notebook };
static props = ["*"];
}
await mountWithCleanup(Parent);
expect(".o_notebook_headers .nav-item a.active").toHaveText("About", {
message: "The first page is selected",
});
});
test("notebook set vertically", async () => {
class Parent extends Component {
static template = xml`
About the bird
Owls are birds from the order Strigiformes which includes over
200 species of mostly solitary and nocturnal birds of prey typified by an upright stance, ...
Their favorite activity: hunting
Owls are called raptors, or birds of prey, which means they use sharp talons and curved bills to hunt, kill, and eat other animals.
`;
static components = { Notebook };
static props = ["*"];
}
await mountWithCleanup(Parent);
expect("div.o_notebook").toHaveCount(1);
expect(".o_notebook").toHaveClass("vertical", {
message: "orientation is set as vertical",
});
expect(".nav").toHaveClass("flex-column", {
message: "navigation container uses the right class to display as vertical buttons",
});
});
test("notebook pages rendered by a template component", async () => {
class NotebookPageRenderer extends Component {
static template = xml`
`;
static props = {
heading: String,
text: String,
};
}
class Parent extends Component {
static template = xml`
Page 1
First page set directly as a slot
Page 4
`;
static components = { Notebook };
static props = ["*"];
setup() {
this.pages = [
{
Component: NotebookPageRenderer,
index: 1,
title: "Page 2",
props: {
heading: "Page 2",
text: "Second page rendered by a template component",
},
},
{
Component: NotebookPageRenderer,
id: "page_three", // required to be set as default page
index: 2,
title: "Page 3",
props: {
heading: "Page 3",
text: "Third page rendered by a template component",
},
},
];
}
}
await mountWithCleanup(Parent);
expect("div.o_notebook").toHaveCount(1);
expect(".o_notebook_headers .nav-item:nth-child(3) a").toHaveClass("active", {
message: "third page is selected by default",
});
await click(".o_notebook_headers .nav-item:nth-child(2) a");
await animationFrame();
expect(".o_notebook_content p").toHaveText("Second page rendered by a template component", {
message: "displayed content corresponds to the current page",
});
});
test("each page is different", async () => {
class Page extends Component {
static template = xml`Coucou
`;
static props = ["*"];
}
class Parent extends Component {
static template = xml``;
static components = { Notebook };
static props = ["*"];
setup() {
this.pages = [
{
Component: Page,
index: 1,
title: "Page 1",
},
{
Component: Page,
index: 2,
title: "Page 2",
},
];
}
}
await mountWithCleanup(Parent);
const firstPage = queryFirst("h3");
expect(firstPage).toBeInstanceOf(HTMLElement);
await click(".o_notebook_headers .nav-item:nth-child(2) a");
await animationFrame();
const secondPage = queryFirst("h3");
expect(secondPage).toBeInstanceOf(HTMLElement);
expect(firstPage).not.toBe(secondPage);
});
test("defaultPage recomputed when isVisible is dynamic", async () => {
let defaultPageVisible = false;
class Parent extends Component {
static components = { Notebook };
static template = xml`
`;
static props = ["*"];
get defaultPageVisible() {
return defaultPageVisible;
}
}
const parent = await mountWithCleanup(Parent);
expect(".page1").toHaveCount(1);
expect(".nav-link.active").toHaveText("page1");
defaultPageVisible = true;
parent.render(true);
await animationFrame();
expect(".page3").toHaveCount(1);
expect(".nav-link.active").toHaveText("page3");
await click(".o_notebook_headers .nav-item:nth-child(2) a");
await animationFrame();
expect(".page2").toHaveCount(1);
expect(".nav-link.active").toHaveText("page2");
parent.render(true);
await animationFrame();
expect(".page2").toHaveCount(1);
expect(".nav-link.active").toHaveText("page2");
});
test("disabled pages are greyed out and can't be toggled", async () => {
class Parent extends Component {
static components = { Notebook };
static template = xml`
`;
static props = ["*"];
}
await mountWithCleanup(Parent);
expect(".page1").toHaveCount(1);
expect(".nav-item:nth-child(2)").toHaveClass("disabled", {
message: "tab of the disabled page is greyed out",
});
await click(".nav-item:nth-child(2) .nav-link");
await animationFrame();
expect(".page1").toHaveCount(1, {
message: "the same page is still displayed",
});
await click(".nav-item:nth-child(3) .nav-link");
await animationFrame();
expect(".page3").toHaveCount(1, {
message: "the third page is now displayed",
});
});
test("icons can be given for each page tab", async () => {
class Parent extends Component {
static components = { Notebook };
static template = xml`
`;
static props = ["*"];
get icons() {
return {
1: "fa-trash",
3: "fa-pencil",
};
}
}
await mountWithCleanup(Parent);
expect(".nav-item:nth-child(1) i").toHaveClass("fa-trash");
expect(".nav-item:nth-child(1)").toHaveText("page1");
expect(".nav-item:nth-child(2) i").toHaveCount(0);
expect(".nav-item:nth-child(2)").toHaveText("page2");
expect(".nav-item:nth-child(3) i").toHaveClass("fa-pencil");
expect(".nav-item:nth-child(3)").toHaveText("page3");
});