Odoo18-Base/addons/web/static/tests/core/macro.test.js
KaySar12 8a9c49514f
Some checks are pending
Setup Native Action / native (3.12.7) (push) Waiting to run
Setup Native Action / docker (3.12.7) (push) Waiting to run
update base web lib
2025-05-23 14:51:51 +07:00

259 lines
7.2 KiB
JavaScript

import { beforeEach, expect, test } from "@odoo/hoot";
import { advanceTime, animationFrame, click, edit, queryOne } from "@odoo/hoot-dom";
import { Component, useState, xml } from "@odoo/owl";
import { mountWithCleanup, patchWithCleanup } from "@web/../tests/web_test_helpers";
import { Macro } from "@web/core/macro";
let macro;
async function waitForMacro() {
for (let i = 0; i < 50; i++) {
await animationFrame();
await advanceTime(265);
if (macro.isComplete) {
return;
}
}
if (!macro.isComplete) {
throw new Error(`Macro is not complete`);
}
}
beforeEach(() => {
patchWithCleanup(Macro.prototype, {
start() {
super.start(...arguments);
macro = this;
},
});
});
function onTextChange(element, callback) {
const observer = new MutationObserver((mutations) => {
for (const mutation of mutations) {
if (mutation.type === "characterData" || mutation.type === "childList") {
callback(element.textContent);
}
}
});
observer.observe(element, {
characterData: true,
childList: true,
subtree: true,
});
return observer;
}
class TestComponent extends Component {
static template = xml`
<div class="counter">
<p><button class="btn inc" t-on-click="() => this.state.value++">increment</button></p>
<p><button class="btn dec" t-on-click="() => this.state.value--">decrement</button></p>
<p><button class="btn double" t-on-click="() => this.state.value = 2*this.state.value">double</button></p>
<span class="value"><t t-esc="state.value"/></span>
<input />
</div>`;
static props = ["*"];
setup() {
this.state = useState({ value: 0 });
}
}
test("simple use", async () => {
await mountWithCleanup(TestComponent);
new Macro({
name: "test",
steps: [
{
trigger: "button.inc",
async action(trigger) {
await click(trigger);
},
},
],
}).start(queryOne(".counter"));
const span = queryOne("span.value");
expect(span).toHaveText("0");
onTextChange(span, expect.step);
await waitForMacro();
expect.verifySteps(["1"]);
});
test("multiple steps", async () => {
await mountWithCleanup(TestComponent);
const span = queryOne("span.value");
expect(span).toHaveText("0");
new Macro({
name: "test",
steps: [
{
trigger: "button.inc",
async action(trigger) {
await click(trigger);
},
},
{
trigger: () => (span.textContent === "1" ? span : null),
},
{
trigger: "button.inc",
async action(trigger) {
await click(trigger);
},
},
],
}).start(queryOne(".counter"));
onTextChange(span, expect.step);
await waitForMacro();
expect.verifySteps(["1", "2"]);
});
test("can input values", async () => {
await mountWithCleanup(TestComponent);
const input = queryOne("input");
new Macro({
name: "test",
steps: [
{
trigger: "div.counter input",
async action(trigger) {
await click(trigger);
await edit("aaron", { confirm: "blur" });
},
},
],
}).start(queryOne(".counter"));
expect(input).toHaveValue("");
await waitForMacro();
expect(input).toHaveValue("aaron");
});
test("a step can have no trigger", async () => {
await mountWithCleanup(TestComponent);
const input = queryOne("input");
new Macro({
name: "test",
steps: [
{ action: () => expect.step("1") },
{ action: () => expect.step("2") },
{
trigger: "div.counter input",
async action(trigger) {
await click(trigger);
await edit("aaron", { confirm: "blur" });
},
},
{ action: () => expect.step("3") },
],
}).start(queryOne(".counter"));
expect(input).toHaveValue("");
await waitForMacro();
expect(input).toHaveValue("aaron");
expect.verifySteps(["1", "2", "3"]);
});
test("onStep function is called at each step", async () => {
await mountWithCleanup(TestComponent);
const span = queryOne("span.value");
expect(span).toHaveText("0");
new Macro({
name: "test",
onStep: (el, step, index) => {
expect.step(index);
},
steps: [
{
action: () => {
console.log("brol");
},
},
{
trigger: "button.inc",
async action(trigger) {
await click(trigger);
},
},
],
}).start(queryOne(".counter"));
await waitForMacro();
expect(span).toHaveText("1");
expect.verifySteps([0, 1]);
});
test("trigger can be a function returning an htmlelement", async () => {
await mountWithCleanup(TestComponent);
const span = queryOne("span.value");
expect(span).toHaveText("0");
new Macro({
name: "test",
steps: [
{
trigger: () => queryOne("button.inc"),
async action(trigger) {
await click(trigger);
},
},
],
}).start(queryOne(".counter"));
expect(span).toHaveText("0");
await waitForMacro();
expect(span).toHaveText("1");
});
test("macro wait element is visible to do action", async () => {
await mountWithCleanup(TestComponent);
const span = queryOne("span.value");
const button = queryOne("button.inc");
button.classList.add("d-none");
expect(span).toHaveText("0");
new Macro({
name: "test",
timeout: 1000,
steps: [
{
trigger: "button.inc",
action: () => {
expect.step("element is now visible");
},
},
],
onError: (error) => {
expect.step(error);
},
}).start(queryOne(".counter"));
advanceTime(500);
button.classList.remove("d-none");
await waitForMacro();
expect.verifySteps(["element is now visible"]);
});
test("macro timeout if element is not visible", async () => {
await mountWithCleanup(TestComponent);
const span = queryOne("span.value");
const button = queryOne("button.inc");
button.classList.add("d-none");
expect(span).toHaveText("0");
const macro = new Macro({
name: "test",
timeout: 1000,
steps: [
{
trigger: "button.inc",
action: () => {
expect.step("element is now visible");
},
},
],
onError: (error) => {
expect.step(error.message);
},
});
macro.start(queryOne(".counter"));
await waitForMacro();
expect.verifySteps(["TIMEOUT step failed to complete within 1000 ms."]);
});