Files

279 lines
9.2 KiB
JavaScript

import { HtmlField } from "@html_editor/fields/html_field";
import { htmlEditorVersions } from "@html_editor/html_migrations/html_migrations_utils";
import { mockKnowledgeCommentsService } from "@knowledge/../tests/knowledge_test_helpers";
import { WithLazyLoading } from "@knowledge/components/with_lazy_loading/with_lazy_loading";
import { EmbeddedViewLinkComponent } from "@knowledge/editor/embedded_components/backend/embedded_view_link/embedded_view_link";
import { EmbeddedView } from "@knowledge/views/embedded_view";
import { defineMailModels } from "@mail/../tests/mail_test_helpers";
import { before, beforeEach, describe, expect, test } from "@odoo/hoot";
import { onMounted, toRaw } from "@odoo/owl";
import {
defineModels,
fields,
models,
patchWithCleanup,
defineActions,
getService,
mountWithCleanup,
onRpc,
} from "@web/../tests/web_test_helpers";
import { Deferred } from "@web/core/utils/concurrency";
import { SearchModel } from "@web/search/search_model";
import { WebClient } from "@web/webclient/webclient";
const VERSIONS = htmlEditorVersions();
const CURRENT_VERSION = VERSIONS.at(-1);
const searchModelState = JSON.stringify({
nextGroupId: 2,
nextGroupNumber: 2,
nextId: 2,
query: [{ searchItemId: 1 }],
searchItems: {
1: {
description: "myFavorite",
isDefault: true,
domain: [["name", "ilike", "view"]],
context: {},
userId: 1,
type: "favorite",
id: 1,
groupId: 1,
groupNumber: 1,
orderBy: [],
},
},
searchPanelInfo: {
className: "",
viewTypes: ["list"],
loaded: false,
shouldReload: false,
},
sections: [],
});
const embeddedViewProps = {
viewProps: {
actionXmlId: "knowledge_article_action_test",
context: {
knowledge_search_model_state: searchModelState,
},
displayName: "Articles List",
favoriteFilters: {
customFavorite: {
name: "customFavorite",
is_default: false,
model_id: "article",
domain: [["name", "ilike", "view"]],
context: {},
user_id: 1,
},
},
id: "embedid",
viewType: "list",
},
};
const embeddedViewLinkProps = {
viewProps: {
actionXmlId: "knowledge_article_action_test",
context: {
knowledge_search_model_state: searchModelState,
},
displayName: "Articles List",
viewType: "list",
},
};
class Article extends models.Model {
body = fields.Html({ trim: true });
name = fields.Char();
sequence = fields.Integer();
_records = [
{
id: 1,
name: "view_2.0",
body: `
<div data-embedded="view" data-embedded-props='${JSON.stringify(
embeddedViewProps
)}'></div>
<p><br></p>`,
sequence: 1,
},
{
id: 2,
name: "viewLink_2.0",
body: `
<p>
<span data-embedded="viewLink" data-embedded-props='${JSON.stringify(
embeddedViewLinkProps
)}'></span>
</p>
`,
sequence: 2,
},
];
_views = {
list: `
<list default_order="sequence" string="Articles">
<field name="sequence" widget="handle"/>
<field name="name"/>
</list>
`,
form: `
<form js_class="knowledge_article_view_form">
<sheet>
<div class="o_knowledge_editor">
<field name="body" widget="knowledge_html"/>
</div>
</sheet>
</form>
`,
search: `
<search></search>
`,
};
}
defineMailModels();
defineModels([Article]);
onRpc("get_sidebar_articles", () => ({ articles: [], favorite_ids: [] }));
// Prevent instantiation of the color picker
onRpc("render_public_asset", () => false);
onRpc("has_access", () => true);
defineActions([
{
id: 1,
xml_id: "knowledge_article_action_test",
name: "articleTest",
res_model: "article",
type: "ir.actions.act_window",
views: [
[false, "form"],
[false, "list"],
],
},
]);
describe("test migration of embedded views and view links filters", () => {
let htmlFieldComponent;
beforeEach(() => {
patchWithCleanup(HtmlField.prototype, {
setup() {
super.setup();
htmlFieldComponent = this;
},
});
});
test("Ensure that embedded views filters and favorites have their `user_id` field converted to `user_ids`", async function () {
const searchModelPromise = new Deferred();
before(() => {
mockKnowledgeCommentsService();
patchWithCleanup(WithLazyLoading.prototype, {
setup() {
super.setup();
onMounted(() => {
this.state.isLoaded = true;
});
},
});
patchWithCleanup(EmbeddedView.prototype, {
async loadView() {
await super.loadView(...arguments);
patchWithCleanup(this.withSearchProps.SearchModel.prototype, {
async load() {
await super.load(...arguments);
if (this.context.knowledgeEmbeddedViewId === "embedid") {
searchModelPromise.resolve(this);
}
},
});
},
});
});
await mountWithCleanup(WebClient);
await getService("action").doAction("knowledge_article_action_test", {
props: { resId: 1 },
viewType: "form",
});
const searchModel = await searchModelPromise;
expect(searchModel.query).toEqual([{ searchItemId: 1 }]);
const myFavorite = searchModel.searchItems[1];
expect(myFavorite.description).toEqual("myFavorite");
expect(toRaw(myFavorite.userIds)).toEqual([]);
expect(myFavorite.userId).toEqual(undefined);
const customFavorite = searchModel.searchItems[2];
expect(customFavorite.description).toEqual("customFavorite");
expect(toRaw(customFavorite.userIds)).toEqual([]);
expect(customFavorite.userId).toEqual(undefined);
expect(
htmlFieldComponent.editor
.getElContent()
.querySelector(`[data-oe-version="${CURRENT_VERSION}"]`)
).toHaveCount(1);
});
test("Ensure that embedded views links filters have their `user_id` field converted to `user_ids`", async function () {
const viewLinkPromise = new Deferred();
const searchModelPromise = new Deferred();
let saveSearchModel = false;
before(() => {
mockKnowledgeCommentsService();
patchWithCleanup(SearchModel.prototype, {
async load() {
await super.load(...arguments);
if (saveSearchModel) {
searchModelPromise.resolve(this);
}
},
/**
* This method is voided for the test because it overwrites
* favorites with real favorite records data (which are not
* defined here).
* For the purpose of this test, only the data contained in the
* searchModel state should be tested (to ensure that the
* upgrade actually happened). In a real situation,
* _reconciliateFavorites will also "fix" some properties
* with the most up to date information from actual irFilters
* records, but that is done independently from the JS upgrade.
*/
_reconciliateFavorites() {},
});
patchWithCleanup(EmbeddedViewLinkComponent.prototype, {
setup() {
super.setup();
onMounted(() => {
viewLinkPromise.resolve(this);
});
},
});
});
await mountWithCleanup(WebClient);
await getService("action").doAction("knowledge_article_action_test", {
props: { resId: 2 },
viewType: "form",
});
const viewLink = await viewLinkPromise;
expect(
htmlFieldComponent.editor
.getElContent()
.querySelector(`[data-oe-version="${CURRENT_VERSION}"]`)
).toHaveCount(1);
saveSearchModel = true;
viewLink.openViewLink();
const searchModel = await searchModelPromise;
expect(searchModel.query).toEqual([{ searchItemId: 1 }]);
const myFavorite = searchModel.searchItems[1];
expect(myFavorite.description).toEqual("myFavorite");
expect(toRaw(myFavorite.userIds)).toEqual([]);
expect(myFavorite.userId).toEqual(undefined);
});
});