replace stale web_editor with html_editor and html_builder for 19.0

web_editor was removed in Odoo 19.0 and replaced by html_editor
and html_builder. The old web_editor was incorrectly included in
the 19.0 vanilla import.

🤖 assisted by claude
This commit is contained in:
Ernad Husremovic 2026-03-09 15:31:13 +01:00
parent 4b94f0abc5
commit f866779561
1513 changed files with 396049 additions and 358525 deletions

View file

@ -0,0 +1,105 @@
import { before, describe, expect, test } from "@odoo/hoot";
import { animationFrame, queryOne } from "@odoo/hoot-dom";
import { setupInteractionWhiteList, startInteractions } from "@web/../tests/public/helpers";
import {
EmbeddedComponentInteraction,
getEmbeddingMap,
} from "@html_editor/public/embedded_components/embedded_component_interaction";
import { patchWithCleanup } from "@web/../tests/web_test_helpers";
import { EmbeddedWrapperMixin, embedding } from "@html_editor/../tests/_helpers/embedded_component";
import { getEditableDescendants } from "@html_editor/others/embedded_component_utils";
setupInteractionWhiteList("html_editor.embedded_component");
describe.current.tags("interaction_dev");
function setupEmbeddedComponentsWhitelist(embeddings) {
before(() => {
patchWithCleanup(EmbeddedComponentInteraction.prototype, {
getEmbedding(name) {
return getEmbeddingMap(embeddings).get(name);
},
});
});
}
describe("Mount and Destroy embedded components", () => {
test("Can mount and destroy embedded components in editable descendants", async () => {
const SimpleEmbeddedWrapper = EmbeddedWrapperMixin("deep");
setupEmbeddedComponentsWhitelist([
embedding("wrapper", SimpleEmbeddedWrapper, (host) => ({ host }), {
getEditableDescendants,
}),
]);
const { core } = await startInteractions(
`<div data-embedded="wrapper">
<div data-embedded-editable="deep">
<div data-embedded="wrapper">
<div data-embedded-editable="deep">
<p>deep</p>
</div>
</div>
</div>
</div>`
);
await animationFrame();
expect(queryOne("#wrapwrap")).toHaveInnerHTML(
`<div data-embedded="wrapper">
<owl-root contenteditable="false" data-oe-protected="true" style="display: contents;">
<div class="deep">
<div data-embedded-editable="deep">
<div data-embedded="wrapper">
<owl-root contenteditable="false" data-oe-protected="true" style="display: contents;">
<div class="deep">
<div data-embedded-editable="deep">
<p>deep</p>
</div>
</div>
</owl-root>
</div>
</div>
</div>
</owl-root>
</div>`
);
core.stopInteractions();
expect(queryOne("#wrapwrap")).toHaveInnerHTML(
`<div data-embedded="wrapper">
<div data-embedded-editable="deep">
<div data-embedded="wrapper">
<div data-embedded-editable="deep">
<p>deep</p>
</div>
</div>
</div>
</div>`
);
});
test("Keep existing HTML content and do not crash when encountering an unknown data-embedded value", async () => {
await startInteractions(
`<div data-embedded="wrapper">
<div data-embedded-editable="deep">
<div data-embedded="wrapper">
<div data-embedded-editable="deep">
<p>deep</p>
</div>
</div>
</div>
</div>`
);
await animationFrame();
expect(queryOne("#wrapwrap")).toHaveInnerHTML(
`<div data-embedded="wrapper">
<div data-embedded-editable="deep">
<div data-embedded="wrapper">
<div data-embedded-editable="deep">
<p>deep</p>
</div>
<owl-root contenteditable="false" data-oe-protected="true" style="display: contents;"></owl-root>
</div>
</div>
<owl-root contenteditable="false" data-oe-protected="true" style="display: contents;"></owl-root>
</div>`
);
});
});

View file

@ -0,0 +1,76 @@
import { HtmlUpgradeManager } from "@html_editor/html_migrations/html_upgrade_manager";
import { afterEach, beforeEach, describe, expect, test } from "@odoo/hoot";
import { animationFrame, queryOne } from "@odoo/hoot-dom";
import { setupInteractionWhiteList, startInteractions } from "@web/../tests/public/helpers";
import { patchWithCleanup } from "@web/../tests/web_test_helpers";
import { registry } from "@web/core/registry";
import { setupMigrateFunctions } from "@html_editor/../tests/public/html_migrations_test_utils";
setupInteractionWhiteList("html_editor.html_migrations");
describe.current.tags("interaction_dev");
describe("Public HTML migration only run once per interaction", () => {
beforeEach(() => {
registry
.category("html_editor_upgrade")
.category("1.1")
.add(
"test_public_html_migrations",
"@html_editor/../tests/public/html_migrations_test_utils"
);
patchWithCleanup(HtmlUpgradeManager.prototype, {
processForUpgrade() {
expect.step("html upgrade");
return super.processForUpgrade(...arguments);
},
});
});
afterEach(() => {
registry
.category("html_editor_upgrade")
.category("1.1")
.remove("test_public_html_migrations");
});
test("HTML migration is not executed if interactions are restarted", async () => {
setupMigrateFunctions([
(container) => {
container.querySelector("div").replaceChildren(document.createTextNode("after"));
},
]);
const { core } = await startInteractions(`<div data-oe-version="1.0">before</div>`);
expect.verifySteps(["html upgrade"]);
expect(queryOne("#wrapwrap")).toHaveInnerHTML(`<div>after</div>`);
core.stopInteractions();
await core.startInteractions();
expect.verifySteps([]);
expect(queryOne("#wrapwrap")).toHaveInnerHTML(`<div>after</div>`);
});
test("HTML migration is not attempted again and has no consequence on the DOM if it failed", async () => {
setupMigrateFunctions([
() => {
expect.step("html upgrade attempt");
throw new Error("failed html migration");
},
]);
const { core } = await startInteractions(`<div data-oe-version="1.0">before</div>`);
expect.verifySteps(["html upgrade", "html upgrade attempt"]);
expect(queryOne("#wrapwrap")).toHaveInnerHTML(`<div>before</div>`);
core.stopInteractions();
await core.startInteractions();
expect.verifySteps([]);
expect(queryOne("#wrapwrap")).toHaveInnerHTML(`<div>before</div>`);
});
});
describe("public html migration to editor version 1.1", () => {
test("replace excalidraw embedded component by a link", async () => {
await startInteractions(
`<div><p data-oe-version="1.0">Hello World</p><div data-embedded="draw" data-embedded-props='{"source": "https://excalidraw.com"}'/></div>`
);
await animationFrame();
expect(queryOne("#wrapwrap")).toHaveInnerHTML(
`<div><p>Hello World</p><p><a href="https://excalidraw.com">https://excalidraw.com</a></p></div>`
);
});
});

View file

@ -0,0 +1,23 @@
import { before } from "@odoo/hoot";
import { patchWithCleanup } from "@web/../tests/web_test_helpers";
const migrateCallbacks = {};
export function migrate(container, env) {
for (const callback of Object.values(migrateCallbacks)) {
callback(container, env);
}
}
/**
* @param {Array} callbacks
*/
export function setupMigrateFunctions(callbacks) {
before(() => {
const newCallbacks = {};
for (let i = 0; i < callbacks.length; i++) {
newCallbacks[i] = callbacks[i];
}
patchWithCleanup(migrateCallbacks, newCallbacks);
});
}