Files
owl/tests/components/style_class.test.ts
T
2022-02-11 10:18:01 +01:00

238 lines
7.7 KiB
TypeScript

import { Component, mount, useState, xml } from "../../src";
import { makeTestFixture, nextTick, snapshotEverything } from "../helpers";
snapshotEverything();
let fixture: HTMLElement;
beforeEach(() => {
fixture = makeTestFixture();
});
describe("style and class handling", () => {
test("can set style and class inside component", async () => {
class Test extends Component {
static template = xml`
<div style="font-weight:bold;" class="some-class">world</div>
`;
}
await mount(Test, fixture);
expect(fixture.innerHTML).toBe(`<div style="font-weight:bold;" class="some-class">world</div>`);
});
test("can set class on sub component, as prop", async () => {
class Child extends Component {
static template = xml`<div t-att-class="props.class">child</div>`;
}
class Parent extends Component {
static template = xml`<Child class="'some-class'" />`;
static components = { Child };
}
await mount(Parent, fixture);
expect(fixture.innerHTML).toBe(`<div class="some-class">child</div>`);
});
test("no class is set is parent does not give it as prop", async () => {
class Child extends Component {
static template = xml`<div t-att-class="props.class">child</div>`;
}
class Parent extends Component {
static template = xml`<Child />`;
static components = { Child };
}
await mount(Parent, fixture);
expect(fixture.innerHTML).toBe(`<div>child</div>`);
});
test("no class is set is child ignores it", async () => {
class Child extends Component {
static template = xml`<div>child</div>`;
}
class Parent extends Component {
static template = xml`<Child class="'hey'"/>`;
static components = { Child };
}
await mount(Parent, fixture);
expect(fixture.innerHTML).toBe(`<div>child</div>`);
});
test("empty class attribute is not added on widget root el", async () => {
class Child extends Component {
static template = xml`<span t-att-class="props.class"/>`;
}
class Parent extends Component {
static template = xml`<div><Child class=""/></div>`;
static components = { Child };
}
await mount(Parent, fixture);
expect(fixture.innerHTML).toBe(`<div><span></span></div>`);
});
test("can set more than one class on sub component", async () => {
class Child extends Component {
static template = xml`<div t-att-class="props.class">child</div>`;
}
class Parent extends Component {
static template = xml`<Child class="'a b'" />`;
static components = { Child };
}
await mount(Parent, fixture);
expect(fixture.innerHTML).toBe(`<div class="a b">child</div>`);
});
test("component class and parent class combine together", async () => {
class Child extends Component {
static template = xml`<div class="child" t-att-class="props.class">child</div>`;
}
class Parent extends Component {
static template = xml`<Child class="'from parent'" />`;
static components = { Child };
}
await mount(Parent, fixture);
expect(fixture.innerHTML).toBe(`<div class="child from parent">child</div>`);
});
test("can set class on sub sub component", async () => {
class ChildChild extends Component {
static template = xml`<div t-att-class="props.class">childchild</div>`;
}
class Child extends Component {
static template = xml`<ChildChild class="(props.class || '') + ' fromchild'" />`;
static components = { ChildChild };
}
class Parent extends Component {
static template = xml`<Child class="'fromparent'" />`;
static components = { Child };
}
await mount(Parent, fixture);
expect(fixture.innerHTML).toBe(`<div class="fromparent fromchild">childchild</div>`);
});
test("can set class on multi root component", async () => {
class Child extends Component {
static template = xml`<div>a</div><span t-att-class="props.class">b</span>`;
}
class Parent extends Component {
static template = xml`<Child class="'fromparent'" />`;
static components = { Child };
}
await mount(Parent, fixture);
expect(fixture.innerHTML).toBe(`<div>a</div><span class="fromparent">b</span>`);
});
test("class on sub component, which is switched to another", async () => {
class ChildA extends Component {
static template = xml`<div t-att-class="props.class">a</div>`;
}
class ChildB extends Component {
static template = xml`<span t-att-class="props.class">b</span>`;
}
class Child extends Component {
static template = xml`<ChildA class="props.class" t-if="props.child==='a'"/><ChildB class="props.class" t-else=""/>`;
static components = { ChildA, ChildB };
}
class Parent extends Component {
static template = xml`<Child class="'someclass'" child="state.child" />`;
static components = { Child };
state = useState({ child: "a" });
}
const parent = await mount(Parent, fixture);
expect(fixture.innerHTML).toBe(`<div class="someclass">a</div>`);
parent.state.child = "b";
await nextTick();
expect(fixture.innerHTML).toBe(`<span class="someclass">b</span>`);
});
// test("t-att-class is properly added/removed on widget root el", async () => {
// class Child extends Component {
// static template = xml`<div class="c"/>`;
// }
// class Parent extends Component {
// static template = xml`<div><Child t-att-class="{a:state.a, b:state.b}"/></div>`;
// static components = { Child };
// state = useState({ a: true, b: false });
// }
// const widget = await mount(Parent, fixture);
// expect(fixture.innerHTML).toBe(`<div><div class="c a"></div></div>`);
// widget.state.a = false;
// widget.state.b = true;
// await nextTick();
// expect(fixture.innerHTML).toBe(`<div><div class="c b"></div></div>`);
// });
test("class with extra whitespaces", async () => {
class Child extends Component {
static template = xml`<div t-att-class="props.class"/>`;
}
class Parent extends Component {
static template = xml`<Child class="'a b c d'"/>`;
static components = { Child };
}
await mount(Parent, fixture);
expect(fixture.innerHTML).toBe(`<div class="a b c d"></div>`);
});
test("class with extra whitespaces (variation)", async () => {
class Child extends Component {
static template = xml`<div t-att-class="props.class"/>`;
}
class Parent extends Component {
static template = xml`<p><Child class="'a b c d'"/></p>`;
static components = { Child };
}
await mount(Parent, fixture);
expect(fixture.innerHTML).toBe(`<p><div class="a b c d"></div></p>`);
});
test("t-att-class is properly added/removed on widget root el (v2)", async () => {
let child: any = null;
class Child extends Component {
static template = xml`<span class="c" t-att-class="{ d: state.d, ...props.class }"/>`;
state = useState({ d: true });
setup() {
child = this;
}
}
class Parent extends Component {
static template = xml`
<div>
<Child class="{ b: state.b }" />
</div>`;
static components = { Child };
state = useState({ b: true });
}
const widget = await mount(Parent, fixture);
const span = fixture.querySelector("span")!;
expect(span.className).toBe("c d b");
widget.state.b = false;
await nextTick();
expect(span.className).toBe("c d");
child.state.d = false;
await nextTick();
expect(span.className).toBe("c");
widget.state.b = true;
await nextTick();
expect(span.className).toBe("c b");
child.state.d = true;
await nextTick();
expect(span.className).toBe("c b d");
});
});