Files
owl/web/static/tests/widget.test.ts
T

185 lines
5.1 KiB
TypeScript
Raw Normal View History

2019-01-24 10:33:11 +01:00
import { Widget, WEnv } from "../src/ts/core/widget";
import { QWeb } from "../src/ts/core/qweb_vdom";
2019-01-16 13:19:58 +01:00
2019-01-23 14:28:41 +01:00
interface Type<T> extends Function {
new (...args: any[]): T;
}
type TestEnv = WEnv;
2019-01-23 22:52:50 +01:00
type TestWidget = Widget<TestEnv>;
2019-01-23 11:12:54 +01:00
function makeWidget(W: Type<TestWidget>): TestWidget {
2019-01-16 13:19:58 +01:00
const env = {
2019-01-23 22:52:50 +01:00
qweb: new QWeb()
2019-01-16 13:19:58 +01:00
};
const w = new W(env);
2019-01-16 13:19:58 +01:00
return w;
}
async function click(el: HTMLElement) {
el.click();
return Promise.resolve();
}
const template = `
<div><t t-esc="state.counter"/><button t-on-click="inc">Inc</button></div>
`;
2019-01-24 10:33:11 +01:00
class Counter extends Widget<TestEnv> {
2019-01-16 13:19:58 +01:00
name = "counter";
template = template;
state = {
counter: 0
};
inc() {
this.updateState({ counter: this.state.counter + 1 });
}
}
describe("basic widget properties", () => {
test("has no el after creation", async () => {
const widget = makeWidget(Widget);
expect(widget.el).toBe(null);
});
test("can be mounted", async () => {
const widget = makeWidget(Widget);
const target = document.createElement("div");
await widget.mount(target);
expect(target.innerHTML).toBe("<div></div>");
});
test("can be clicked on and updated", async () => {
const counter = makeWidget(Counter);
const target = document.createElement("div");
await counter.mount(target);
expect(target.innerHTML).toBe("<div>0<button>Inc</button></div>");
await click((<HTMLElement>counter.el).getElementsByTagName("button")[0]);
expect(target.innerHTML).toBe("<div>1<button>Inc</button></div>");
});
2019-01-21 14:38:44 +01:00
test("widget style and classname", async () => {
2019-01-23 11:12:54 +01:00
class StyledWidget extends Widget<TestEnv> {
2019-01-21 15:54:18 +01:00
template = `<div style="font-weight:bold;" class="some-class">world</div>`;
2019-01-21 14:38:44 +01:00
}
const widget = makeWidget(StyledWidget);
const target = document.createElement("div");
await widget.mount(target);
2019-01-21 15:54:18 +01:00
expect(target.innerHTML).toBe(
`<div style="font-weight:bold;" class="some-class">world</div>`
);
2019-01-21 14:38:44 +01:00
});
2019-01-16 13:19:58 +01:00
});
2019-01-16 23:03:51 +01:00
describe("lifecycle hooks", () => {
test("willStart hook is called", async () => {
let willstart = false;
2019-01-23 11:12:54 +01:00
class HookWidget extends Widget<TestEnv> {
2019-01-16 23:03:51 +01:00
async willStart() {
willstart = true;
}
}
const widget = makeWidget(HookWidget);
const target = document.createElement("div");
await widget.mount(target);
expect(willstart).toBe(true);
});
test("mounted hook is not called if not in DOM", async () => {
let mounted = false;
2019-01-23 11:12:54 +01:00
class HookWidget extends Widget<TestEnv> {
2019-01-16 23:03:51 +01:00
async mounted() {
mounted = true;
}
}
const widget = makeWidget(HookWidget);
const target = document.createElement("div");
await widget.mount(target);
expect(mounted).toBe(false);
});
2019-01-21 14:54:13 +01:00
test("mounted hook is called if mounted in DOM", async () => {
let mounted = false;
2019-01-23 11:12:54 +01:00
class HookWidget extends Widget<TestEnv> {
2019-01-21 14:54:13 +01:00
async mounted() {
mounted = true;
}
}
const widget = makeWidget(HookWidget);
const target = document.createElement("div");
document.body.appendChild(target);
await widget.mount(target);
expect(mounted).toBe(true);
2019-01-21 15:54:18 +01:00
target.remove();
2019-01-21 14:54:13 +01:00
});
2019-01-21 16:26:51 +01:00
test("mounted hook is called on subwidgets, in proper order", async () => {
expect.assertions(2);
let parentMounted = false;
let childMounted = false;
2019-01-23 11:12:54 +01:00
class ParentWidget extends Widget<TestEnv> {
2019-01-23 22:52:50 +01:00
name = "a";
2019-01-21 16:26:51 +01:00
template = `<div>Hello<t t-widget="child"/></div>`;
widgets = { child: ChildWidget };
async mounted() {
expect(childMounted).toBe(false);
parentMounted = true;
}
}
2019-01-23 11:12:54 +01:00
class ChildWidget extends Widget<TestEnv> {
2019-01-21 16:26:51 +01:00
async mounted() {
expect(parentMounted).toBe(true);
childMounted = true;
}
}
const widget = makeWidget(ParentWidget);
const target = document.createElement("div");
document.body.appendChild(target);
await widget.mount(target);
target.remove();
});
2019-01-16 23:03:51 +01:00
});
describe("destroy method", () => {
test("destroy remove the widget from the DOM", async () => {
const widget = makeWidget(Widget);
const target = document.body;
await widget.mount(target);
expect(document.contains(widget.el)).toBe(true);
widget.destroy();
expect(document.contains(widget.el)).toBe(false);
});
});
2019-01-20 14:46:36 +01:00
describe("composition", () => {
2019-01-23 11:12:54 +01:00
class WidgetA extends Widget<TestEnv> {
2019-01-21 15:54:18 +01:00
name = "a";
template = `<div>Hello<t t-widget="b"/></div>`;
widgets = { b: WidgetB };
2019-01-21 15:46:29 +01:00
}
2019-01-20 14:46:36 +01:00
2019-01-23 11:12:54 +01:00
class WidgetB extends Widget<TestEnv> {
2019-01-21 15:54:18 +01:00
template = `<div>world</div>`;
2019-01-21 15:46:29 +01:00
}
test("a widget with a sub widget", async () => {
2019-01-20 14:46:36 +01:00
const widget = makeWidget(WidgetA);
const target = document.createElement("div");
await widget.mount(target);
expect(target.innerHTML).toBe("<div>Hello<div>world</div></div>");
});
2019-01-21 15:46:29 +01:00
test("t-refs on widget are widgets", async () => {
2019-01-23 11:12:54 +01:00
class WidgetC extends Widget<TestEnv> {
2019-01-21 15:54:18 +01:00
name = "a";
2019-01-21 16:26:51 +01:00
template = `<div>Hello<t t-ref="mywidgetb" t-widget="b"/></div>`;
2019-01-21 15:54:18 +01:00
widgets = { b: WidgetB };
}
2019-01-21 15:46:29 +01:00
const widget = makeWidget(WidgetC);
const target = document.createElement("div");
await widget.mount(target);
expect(widget.refs.mywidgetb instanceof WidgetB).toBe(true);
});
2019-01-20 14:46:36 +01:00
});