Odoo18-Base/enterprise-17.0/knowledge/static/tests/knowledge_external_embeds_tests.js
2025-01-06 10:57:38 +07:00

199 lines
8.0 KiB
JavaScript

/** @odoo-module */
import {
click,
editInput,
makeDeferred,
nextTick,
patchWithCleanup,
triggerEvent
} from "@web/../tests/helpers/utils";
import { EmbeddedViewBehavior } from "@knowledge/components/behaviors/embedded_view_behavior/embedded_view_behavior";
import { EmbeddedViewManager } from "@knowledge/components/behaviors/embedded_view_behavior/embedded_view_manager";
import { makeView, setupViewRegistries } from "@web/../tests/views/helpers";
import { HtmlField } from "@web_editor/js/backend/html_field";
import { onMounted } from "@odoo/owl";
let serverData;
let htmlFieldReadyPromise;
let embedMountedPromise;
/**
* Insert an embedded kanban view inside a Knowledge article
* @param {HTMLElement} htmlField - Object HtmlField of Knowledge
* @param {HTMLElement} action - Server action used for the embed
*/
const insertKanbanEmbed = async (htmlField, action) => {
const wysiwyg = htmlField.wysiwyg;
wysiwyg.odooEditor.observerUnactive();
await wysiwyg._insertEmbeddedView(null, action, 'kanban', 'External Kanban');
await htmlFieldReadyPromise;
await htmlField.mountBehaviors();
wysiwyg.odooEditor.observerActive();
await nextTick();
};
/**
* This module is testing that the hotkey service works as intended when we have an external embed.
* This means that when, e.g., when pressing the 'Enter' key inside the embed should have no impact
* on the article. Pressing 'Enter' inside the article should also not trigger an event inside
* the embedded view.
* Testing ensures us that the hotkey service still works as intended inside Knowledge, if not we
* would need to change its use for embedded views.
*/
QUnit.module("Knowledge External Embeds Tests", (hooks) => {
hooks.beforeEach(() => {
htmlFieldReadyPromise = makeDeferred();
embedMountedPromise = makeDeferred();
patchWithCleanup(HtmlField.prototype, {
async startWysiwyg() {
await super.startWysiwyg(...arguments);
htmlFieldReadyPromise.resolve(this);
}
});
patchWithCleanup(EmbeddedViewBehavior.prototype, {
async setup() {
super.setup(...arguments);
await this.loadData();
this.state.waiting = false;
},
// Override intersection observer for testing.
async setupIntersectionObserver() {
await this.loadData();
this.state.waiting = false;
}
});
patchWithCleanup(EmbeddedViewManager.prototype, {
setup() {
super.setup(...arguments);
onMounted(() => {
embedMountedPromise.resolve();
});
},
});
serverData = {
models: {
knowledge_article: {
fields: {
display_name: {string: "Displayed name", type: "char"},
full_width: {string: "Is Full Width ?", type: "boolean"},
body: {string: "Body", type: 'html'},
},
records: [{
id: 1,
display_name: "My Article",
body: `<p class="embedded_view_target"><br/></p>
<p class="regular_html_field_node"><br/></p>`,
full_width: false
}]
},
quick_create: {
fields: {
int: { string: 'Integer', type: 'int', sortable: true },
name: { type: 'char', string: "Name given" },
state: { type: 'boolean', string: "Done?" }
},
records: [{
id: 1,
int: 42,
state: true,
name: "Answer to life"
}, {
id: 2,
int: 42,
state: true,
name: "My age"
}, {
id: 3,
int: 69,
state: false,
name: "Funny number"
}]
}
},
actions: {
actionExternalKanban: {
id: 99,
xml_id: "action_external_kanban",
name: "External Kanban",
res_model: "quick_create",
type: "ir.actions.act_window",
views: [[1, "kanban"]],
},
},
views: {
"quick_create,1,kanban":
`<kanban on_create="quick_create" quick_create="1" default_group_by="state">
<field name="int"/>
<templates>
<t t-name="kanban-box">
<div>
<field name="name"/>
</div>
</t>
</templates>
</kanban>`,
"quick_create,1,search": "<search></search>"
},
};
setupViewRegistries();
});
QUnit.test('Testing normal hotkey behavior: kanban embed', async function (assert) {
assert.expect(3);
await makeView({
type: "form",
resModel: "knowledge_article",
serverData,
arch: `<form js_class="knowledge_article_view_form">
<sheet>
<div>
<field name="full_width" readonly="1"/>
<div class="o_knowledge_editor d-flex flex-grow-1">
<field name="body" widget="knowledge_article_html_field"/>
</div>
</div>
</sheet>
</form>`,
resId: 1,
mockRPC(route, { method, model }){
if (model === "knowledge_article") {
switch (method) {
case "get_sidebar_articles":
return {articles: [], favorite_ids: []};
}
}
}
});
const htmlField = await htmlFieldReadyPromise;
await insertKanbanEmbed(htmlField, serverData.actions.actionExternalKanban);
// Embedded views trigger full width
assert.equal(document.querySelector('.o_field_boolean[name="full_width"] input').value, 'on');
const editable = htmlField.wysiwyg.odooEditor.editable;
const regularHtmlFieldNode = editable.querySelector('.regular_html_field_node');
await embedMountedPromise;
const embedViewWrapperNode = editable.querySelector('.o_knowledge_behavior_anchor.o_knowledge_behavior_type_embedded_view')
await click(editable, '.o_kanban_group:nth-of-type(1) .o_kanban_quick_add');
await nextTick();
// input data that will create a new record via quick_create
const input = embedViewWrapperNode.querySelector('.o_required_modifier > input');
await editInput(input, null, "Hello World");
await triggerEvent(embedViewWrapperNode, null, 'keydown', { key: 'Enter'});
assert.containsOnce(embedViewWrapperNode, '.o_kanban_record span:contains(Hello World)', "The record should be created");
// filling the input for a record that will not be created
await editInput(input, null, "Not created");
// trigger the focusout to remove the active element from ui service
await triggerEvent(input, null, 'focusout');
await nextTick();
await click(regularHtmlFieldNode, '');
await nextTick();
await triggerEvent(regularHtmlFieldNode, null, 'keydown', {key: 'Enter'});
const value = embedViewWrapperNode.querySelector('.o_kanban_quick_create input').value;
assert.strictEqual(value, 'Not created', 'The quick_create should not have been triggered');
});
});