[IMP] mail, website_slides: use mock server for activity test

closes odoo/odoo#81502

Related: odoo/enterprise#22941
Signed-off-by: Sébastien Theys (seb) <seb@odoo.com>
This commit is contained in:
Didier (did)
2021-12-17 12:51:39 +00:00
committed by Sébastien Theys
parent f75abaf37e
commit 7d7a1e4029
8 changed files with 499 additions and 314 deletions
@@ -1,24 +1,10 @@
/** @odoo-module **/
import { insert } from '@mail/model/model_field_command';
import {
registerMessagingComponent,
unregisterMessagingComponent,
} from '@mail/utils/messaging_component';
import {
afterEach,
afterNextRender,
beforeEach,
createRootMessagingComponent,
start,
} from '@mail/utils/test_utils';
import { afterEach, afterNextRender, beforeEach, start } from '@mail/utils/test_utils';
import { registerCleanup } from "@web/../tests/helpers/cleanup";
import Bus from 'web.Bus';
import { date_to_str } from 'web.time';
const { Component, tags: { xml } } = owl;
QUnit.module('mail', {}, function () {
QUnit.module('components', {}, function () {
QUnit.module('activity', {}, function () {
@@ -26,19 +12,13 @@ QUnit.module('activity_tests.js', {
beforeEach() {
beforeEach(this);
this.createActivityComponent = async function (activity) {
await createRootMessagingComponent(this, "Activity", {
props: { activityLocalId: activity.localId },
target: this.widget.el,
});
};
this.start = async params => {
const { env, widget } = await start(Object.assign({}, params, {
data: this.data,
}));
const res = await start({ ...params, data: this.data });
const { components, env, widget } = res;
this.components = components;
this.env = env;
this.widget = widget;
return res;
};
},
afterEach() {
@@ -49,12 +29,20 @@ QUnit.module('activity_tests.js', {
QUnit.test('activity simplest layout', async function (assert) {
assert.expect(12);
await this.start();
const activity = this.messaging.models['Activity'].create({
id: 12,
thread: insert({ id: 42, model: 'res.partner' }),
this.data['res.partner'].records.push({
activity_ids: [12],
id: 100,
});
this.data['mail.activity'].records.push({
id: 12,
res_id: 100,
res_model: 'res.partner',
});
const { createChatterContainerComponent } = await this.start();
await createChatterContainerComponent({
threadId: 100,
threadModel: 'res.partner',
});
await this.createActivityComponent(activity);
assert.strictEqual(
document.querySelectorAll('.o_Activity').length,
1,
@@ -120,13 +108,21 @@ QUnit.test('activity simplest layout', async function (assert) {
QUnit.test('activity with note layout', async function (assert) {
assert.expect(3);
await this.start();
const activity = this.messaging.models['Activity'].create({
this.data['res.partner'].records.push({
activity_ids: [12],
id: 100,
});
this.data['mail.activity'].records.push({
id: 12,
note: 'There is no good or bad note',
thread: insert({ id: 42, model: 'res.partner' }),
res_id: 100,
res_model: 'res.partner',
});
const { createChatterContainerComponent } = await this.start();
await createChatterContainerComponent({
threadId: 100,
threadModel: 'res.partner',
});
await this.createActivityComponent(activity);
assert.strictEqual(
document.querySelectorAll('.o_Activity').length,
1,
@@ -147,17 +143,25 @@ QUnit.test('activity with note layout', async function (assert) {
QUnit.test('activity info layout when planned after tomorrow', async function (assert) {
assert.expect(4);
await this.start();
const today = new Date();
const fiveDaysFromNow = new Date();
fiveDaysFromNow.setDate(today.getDate() + 5);
const activity = this.messaging.models['Activity'].create({
dateDeadline: date_to_str(fiveDaysFromNow),
id: 12,
state: 'planned',
thread: insert({ id: 42, model: 'res.partner' }),
this.data['res.partner'].records.push({
activity_ids: [12],
id: 100,
});
this.data['mail.activity'].records.push({
date_deadline: date_to_str(fiveDaysFromNow),
id: 12,
res_id: 100,
res_model: 'res.partner',
state: 'planned',
});
const { createChatterContainerComponent } = await this.start();
await createChatterContainerComponent({
threadId: 100,
threadModel: 'res.partner',
});
await this.createActivityComponent(activity);
assert.strictEqual(
document.querySelectorAll('.o_Activity').length,
1,
@@ -182,17 +186,25 @@ QUnit.test('activity info layout when planned after tomorrow', async function (a
QUnit.test('activity info layout when planned tomorrow', async function (assert) {
assert.expect(4);
await this.start();
const today = new Date();
const tomorrow = new Date();
tomorrow.setDate(today.getDate() + 1);
const activity = this.messaging.models['Activity'].create({
dateDeadline: date_to_str(tomorrow),
id: 12,
state: 'planned',
thread: insert({ id: 42, model: 'res.partner' }),
this.data['res.partner'].records.push({
activity_ids: [12],
id: 100,
});
this.data['mail.activity'].records.push({
date_deadline: date_to_str(tomorrow),
id: 12,
res_id: 100,
res_model: 'res.partner',
state: 'planned',
});
const { createChatterContainerComponent } = await this.start();
await createChatterContainerComponent({
threadId: 100,
threadModel: 'res.partner',
});
await this.createActivityComponent(activity);
assert.strictEqual(
document.querySelectorAll('.o_Activity').length,
1,
@@ -217,15 +229,22 @@ QUnit.test('activity info layout when planned tomorrow', async function (assert)
QUnit.test('activity info layout when planned today', async function (assert) {
assert.expect(4);
await this.start();
const today = new Date();
const activity = this.messaging.models['Activity'].create({
dateDeadline: date_to_str(today),
id: 12,
state: 'today',
thread: insert({ id: 42, model: 'res.partner' }),
this.data['res.partner'].records.push({
activity_ids: [12],
id: 100,
});
this.data['mail.activity'].records.push({
date_deadline: date_to_str(new Date()),
id: 12,
res_id: 100,
res_model: 'res.partner',
state: 'today',
});
const { createChatterContainerComponent } = await this.start();
await createChatterContainerComponent({
threadId: 100,
threadModel: 'res.partner',
});
await this.createActivityComponent(activity);
assert.strictEqual(
document.querySelectorAll('.o_Activity').length,
1,
@@ -250,17 +269,25 @@ QUnit.test('activity info layout when planned today', async function (assert) {
QUnit.test('activity info layout when planned yesterday', async function (assert) {
assert.expect(4);
await this.start();
const today = new Date();
const yesterday = new Date();
yesterday.setDate(today.getDate() - 1);
const activity = this.messaging.models['Activity'].create({
dateDeadline: date_to_str(yesterday),
id: 12,
state: 'overdue',
thread: insert({ id: 42, model: 'res.partner' }),
this.data['res.partner'].records.push({
activity_ids: [12],
id: 100,
});
this.data['mail.activity'].records.push({
date_deadline: date_to_str(yesterday),
id: 12,
res_id: 100,
res_model: 'res.partner',
state: 'overdue',
});
const { createChatterContainerComponent } = await this.start();
await createChatterContainerComponent({
threadId: 100,
threadModel: 'res.partner',
});
await this.createActivityComponent(activity);
assert.strictEqual(
document.querySelectorAll('.o_Activity').length,
1,
@@ -285,17 +312,25 @@ QUnit.test('activity info layout when planned yesterday', async function (assert
QUnit.test('activity info layout when planned before yesterday', async function (assert) {
assert.expect(4);
await this.start();
const today = new Date();
const fiveDaysBeforeNow = new Date();
fiveDaysBeforeNow.setDate(today.getDate() - 5);
const activity = this.messaging.models['Activity'].create({
dateDeadline: date_to_str(fiveDaysBeforeNow),
id: 12,
state: 'overdue',
thread: insert({ id: 42, model: 'res.partner' }),
this.data['res.partner'].records.push({
activity_ids: [12],
id: 100,
});
this.data['mail.activity'].records.push({
date_deadline: date_to_str(fiveDaysBeforeNow),
id: 12,
res_id: 100,
res_model: 'res.partner',
state: 'overdue',
});
const { createChatterContainerComponent } = await this.start();
await createChatterContainerComponent({
threadId: 100,
threadModel: 'res.partner',
});
await this.createActivityComponent(activity);
assert.strictEqual(
document.querySelectorAll('.o_Activity').length,
1,
@@ -320,13 +355,21 @@ QUnit.test('activity info layout when planned before yesterday', async function
QUnit.test('activity with a summary layout', async function (assert) {
assert.expect(4);
await this.start();
const activity = this.messaging.models['Activity'].create({
id: 12,
summary: 'test summary',
thread: insert({ id: 42, model: 'res.partner' }),
this.data['res.partner'].records.push({
activity_ids: [12],
id: 100,
});
this.data['mail.activity'].records.push({
id: 12,
res_id: 100,
res_model: 'res.partner',
summary: 'test summary',
});
const { createChatterContainerComponent } = await this.start();
await createChatterContainerComponent({
threadId: 100,
threadModel: 'res.partner',
});
await this.createActivityComponent(activity);
assert.strictEqual(
document.querySelectorAll('.o_Activity').length,
1,
@@ -352,13 +395,21 @@ QUnit.test('activity with a summary layout', async function (assert) {
QUnit.test('activity without summary layout', async function (assert) {
assert.expect(5);
await this.start();
const activity = this.messaging.models['Activity'].create({
id: 12,
thread: insert({ id: 42, model: 'res.partner' }),
type: insert({ id: 1, displayName: "Fake type" }),
this.data['res.partner'].records.push({
activity_ids: [12],
id: 100,
});
this.data['mail.activity'].records.push({
activity_type_id: 1,
id: 12,
res_id: 100,
res_model: 'res.partner',
});
const { createChatterContainerComponent } = await this.start();
await createChatterContainerComponent({
threadId: 100,
threadModel: 'res.partner',
});
await this.createActivityComponent(activity);
assert.strictEqual(
document.querySelectorAll('.o_Activity').length,
1,
@@ -371,7 +422,7 @@ QUnit.test('activity without summary layout', async function (assert) {
);
assert.strictEqual(
document.querySelector('.o_Activity_type').textContent.trim(),
"Fake type",
"Email",
"activity details should have the activity type display name in type section"
);
assert.strictEqual(
@@ -389,20 +440,26 @@ QUnit.test('activity without summary layout', async function (assert) {
QUnit.test('activity details toggle', async function (assert) {
assert.expect(5);
await this.start();
const today = new Date();
const tomorrow = new Date();
tomorrow.setDate(today.getDate() + 1);
const activity = this.messaging.models['Activity'].create({
creator: insert({ id: 1, display_name: "Admin" }),
dateCreate: date_to_str(today),
dateDeadline: date_to_str(tomorrow),
id: 12,
state: 'planned',
thread: insert({ id: 42, model: 'res.partner' }),
type: insert({ id: 1, displayName: "Fake type" }),
this.data['res.partner'].records.push({
activity_ids: [12],
id: 100,
});
this.data['mail.activity'].records.push({
create_date: date_to_str(today),
create_uid: 1,
date_deadline: date_to_str(tomorrow),
id: 12,
res_id: 100,
res_model: 'res.partner',
});
const { createChatterContainerComponent } = await this.start();
await createChatterContainerComponent({
threadId: 100,
threadModel: 'res.partner',
});
await this.createActivityComponent(activity);
assert.strictEqual(
document.querySelectorAll('.o_Activity').length,
1,
@@ -441,21 +498,33 @@ QUnit.test('activity details toggle', async function (assert) {
QUnit.test('activity details layout', async function (assert) {
assert.expect(11);
await this.start();
const today = new Date();
const tomorrow = new Date();
tomorrow.setDate(today.getDate() + 1);
const activity = this.messaging.models['Activity'].create({
assignee: insert({ id: 10, display_name: "Pauvre pomme" }),
creator: insert({ id: 1, display_name: "Admin" }),
dateCreate: date_to_str(today),
dateDeadline: date_to_str(tomorrow),
id: 12,
state: 'planned',
thread: insert({ id: 42, model: 'res.partner' }),
type: insert({ id: 1, displayName: "Fake type" }),
this.data['res.users'].records.push({
id: 10,
name: 'Pauvre pomme',
});
this.data['res.partner'].records.push({
activity_ids: [12],
id: 100,
});
this.data['mail.activity'].records.push({
activity_type_id: 1,
create_date: date_to_str(today),
create_uid: 2,
date_deadline: date_to_str(tomorrow),
id: 12,
res_id: 100,
res_model: 'res.partner',
state: 'planned',
user_id: 10,
});
const { createChatterContainerComponent } = await this.start();
await createChatterContainerComponent({
threadId: 100,
threadModel: 'res.partner',
});
await this.createActivityComponent(activity);
assert.strictEqual(
document.querySelectorAll('.o_Activity').length,
1,
@@ -487,7 +556,7 @@ QUnit.test('activity details layout', async function (assert) {
);
assert.strictEqual(
document.querySelector('.o_Activity_details .o_Activity_type').textContent,
"Fake type",
"Email",
"activity details type should be 'Fake type'"
);
assert.strictEqual(
@@ -520,13 +589,26 @@ QUnit.test('activity details layout', async function (assert) {
QUnit.test('activity with mail template layout', async function (assert) {
assert.expect(8);
await this.start();
const activity = this.messaging.models['Activity'].create({
id: 12,
mailTemplates: insert({ id: 1, name: "Dummy mail template" }),
thread: insert({ id: 42, model: 'res.partner' }),
this.data['res.partner'].records.push({
activity_ids: [12],
id: 100,
});
this.data['mail.template'].records.push({
id: 1,
name: "Dummy mail template",
});
this.data['mail.activity'].records.push({
activity_type_id: 1,
id: 12,
mail_template_ids: [1],
res_id: 100,
res_model: 'res.partner',
});
const { createChatterContainerComponent } = await this.start();
await createChatterContainerComponent({
threadId: 100,
threadModel: 'res.partner',
});
await this.createActivityComponent(activity);
assert.strictEqual(
document.querySelectorAll('.o_Activity').length,
1,
@@ -606,16 +688,26 @@ QUnit.test('activity with mail template: preview mail', async function (assert)
);
});
await this.start({ env: { bus } });
const activity = this.messaging.models['Activity'].create({
id: 12,
mailTemplates: insert({
id: 1,
name: "Dummy mail template",
}),
thread: insert({ id: 42, model: 'res.partner' }),
this.data['res.partner'].records.push({
activity_ids: [12],
id: 42,
});
this.data['mail.template'].records.push({
id: 1,
name: "Dummy mail template",
});
this.data['mail.activity'].records.push({
activity_type_id: 1,
id: 12,
mail_template_ids: [1],
res_id: 42,
res_model: 'res.partner',
});
const { createChatterContainerComponent } = await this.start({ env: { bus } });
await createChatterContainerComponent({
threadId: 42,
threadModel: 'res.partner',
});
await this.createActivityComponent(activity);
assert.strictEqual(
document.querySelectorAll('.o_Activity').length,
1,
@@ -637,7 +729,22 @@ QUnit.test('activity with mail template: preview mail', async function (assert)
QUnit.test('activity with mail template: send mail', async function (assert) {
assert.expect(7);
await this.start({
this.data['res.partner'].records.push({
activity_ids: [12],
id: 42,
});
this.data['mail.template'].records.push({
id: 1,
name: "Dummy mail template",
});
this.data['mail.activity'].records.push({
activity_type_id: 1,
id: 12,
mail_template_ids: [1],
res_id: 42,
res_model: 'res.partner',
});
const { createChatterContainerComponent } = await this.start({
async mockRPC(route, args) {
if (args.method === 'activity_send_mail') {
assert.step('activity_send_mail');
@@ -650,15 +757,10 @@ QUnit.test('activity with mail template: send mail', async function (assert) {
}
},
});
const activity = this.messaging.models['Activity'].create({
id: 12,
mailTemplates: insert({
id: 1,
name: "Dummy mail template",
}),
thread: insert({ id: 42, model: 'res.partner' }),
await createChatterContainerComponent({
threadId: 42,
threadModel: 'res.partner',
});
await this.createActivityComponent(activity);
assert.strictEqual(
document.querySelectorAll('.o_Activity').length,
1,
@@ -680,17 +782,23 @@ QUnit.test('activity with mail template: send mail', async function (assert) {
QUnit.test('activity upload document is available', async function (assert) {
assert.expect(3);
await this.start();
const today = new Date();
const tomorrow = new Date();
tomorrow.setDate(today.getDate() + 1);
const activity = this.messaging.models['Activity'].create({
canWrite: true,
category: 'upload_file',
id: 12,
thread: insert({ id: 42, model: 'res.partner' }),
this.data['res.partner'].records.push({
activity_ids: [12],
id: 100,
});
this.data['mail.activity'].records.push({
activity_category: 'upload_file',
activity_type_id: 1,
can_write: true,
id: 12,
res_id: 100,
res_model: 'res.partner',
});
const { createChatterContainerComponent } = await this.start();
await createChatterContainerComponent({
threadId: 100,
threadModel: 'res.partner',
});
await this.createActivityComponent(activity);
assert.strictEqual(
document.querySelectorAll('.o_Activity').length,
1,
@@ -711,18 +819,23 @@ QUnit.test('activity upload document is available', async function (assert) {
QUnit.test('activity click on mark as done', async function (assert) {
assert.expect(4);
await this.start();
const today = new Date();
const tomorrow = new Date();
tomorrow.setDate(today.getDate() + 1);
const activity = this.messaging.models['Activity'].create({
canWrite: true,
category: 'not_upload_file',
id: 12,
thread: insert({ id: 42, model: 'res.partner' }),
this.data['res.partner'].records.push({
activity_ids: [12],
id: 100,
});
this.data['mail.activity'].records.push({
activity_category: 'default',
activity_type_id: 1,
can_write: true,
id: 12,
res_id: 100,
res_model: 'res.partner',
});
const { createChatterContainerComponent } = await this.start();
await createChatterContainerComponent({
threadId: 100,
threadModel: 'res.partner',
});
await this.createActivityComponent(activity);
assert.strictEqual(
document.querySelectorAll('.o_Activity').length,
1,
@@ -756,18 +869,23 @@ QUnit.test('activity click on mark as done', async function (assert) {
QUnit.test('activity mark as done popover should focus feedback input on open [REQUIRE FOCUS]', async function (assert) {
assert.expect(3);
await this.start();
const today = new Date();
const tomorrow = new Date();
tomorrow.setDate(today.getDate() + 1);
const activity = this.messaging.models['Activity'].create({
canWrite: true,
category: 'not_upload_file',
id: 12,
thread: insert({ id: 42, model: 'res.partner' }),
this.data['res.partner'].records.push({
activity_ids: [12],
id: 100,
});
this.data['mail.activity'].records.push({
activity_category: 'default',
activity_type_id: 1,
can_write: true,
id: 12,
res_id: 100,
res_model: 'res.partner',
});
const { createChatterContainerComponent } = await this.start();
await createChatterContainerComponent({
threadId: 100,
threadModel: 'res.partner',
});
await this.createActivityComponent(activity);
assert.containsOnce(
document.body,
'.o_Activity',
@@ -822,14 +940,27 @@ QUnit.test('activity click on edit', async function (assert) {
);
});
await this.start({ env: { bus } });
const activity = this.messaging.models['Activity'].create({
canWrite: true,
id: 12,
mailTemplates: insert({ id: 1, name: "Dummy mail template" }),
thread: insert({ id: 42, model: 'res.partner' }),
this.data['res.partner'].records.push({
activity_ids: [12],
id: 42,
});
this.data['mail.template'].records.push({
id: 1,
name: "Dummy mail template",
});
this.data['mail.activity'].records.push({
activity_type_id: 1,
can_write: true,
id: 12,
mail_template_ids: [1],
res_id: 42,
res_model: 'res.partner',
});
const { createChatterContainerComponent } = await this.start({ env: { bus } });
await createChatterContainerComponent({
threadId: 42,
threadModel: 'res.partner',
});
await this.createActivityComponent(activity);
assert.strictEqual(
document.querySelectorAll('.o_Activity').length,
1,
@@ -851,6 +982,10 @@ QUnit.test('activity click on edit', async function (assert) {
QUnit.test('activity edition', async function (assert) {
assert.expect(14);
this.data['res.partner'].records.push({
activity_ids: [12],
id: 42,
});
this.data['mail.activity'].records.push({
can_write: true,
icon: 'fa-times',
@@ -889,15 +1024,11 @@ QUnit.test('activity edition', async function (assert) {
this.data['mail.activity'].records[0].icon = 'fa-check';
payload.options.on_close();
});
await this.start({ env: { bus } });
const activity = this.messaging.models['Activity'].insert(
this.messaging.models['Activity'].convertData(
this.data['mail.activity'].records[0]
)
);
await this.createActivityComponent(activity);
const { createChatterContainerComponent } = await this.start({ env: { bus } });
await createChatterContainerComponent({
threadId: 42,
threadModel: 'res.partner',
});
assert.containsOnce(
document.body,
'.o_Activity',
@@ -946,7 +1077,18 @@ QUnit.test('activity edition', async function (assert) {
QUnit.test('activity click on cancel', async function (assert) {
assert.expect(7);
await this.start({
this.data['res.partner'].records.push({
activity_ids: [12],
id: 100,
});
this.data['mail.activity'].records.push({
activity_type_id: 1,
can_write: true,
id: 12,
res_id: 100,
res_model: 'res.partner',
});
const { createChatterContainerComponent } = await this.start({
async mockRPC(route, args) {
if (route === '/web/dataset/call_kw/mail.activity/unlink') {
assert.step('unlink');
@@ -958,45 +1100,10 @@ QUnit.test('activity click on cancel', async function (assert) {
}
},
});
const activity = this.messaging.models['Activity'].create({
canWrite: true,
id: 12,
mailTemplates: insert({
id: 1,
name: "Dummy mail template",
}),
thread: insert({ id: 42, model: 'res.partner' }),
await createChatterContainerComponent({
threadId: 100,
threadModel: 'res.partner',
});
// Create a parent component to surround the Activity component in order to be able
// to check that activity component has been destroyed
class ParentComponent extends Component {
/**
* @returns {Activity}
*/
get activity() {
return this.messaging.models['Activity'].get(this.props.activityLocalId);
}
}
ParentComponent.env = this.env;
Object.assign(ParentComponent, {
props: { activityLocalId: String },
template: xml`
<div>
<p>parent</p>
<t t-if="activity">
<Activity activityLocalId="activity.localId"/>
</t>
</div>
`,
});
registerMessagingComponent(ParentComponent);
registerCleanup(() => unregisterMessagingComponent(ParentComponent));
await createRootMessagingComponent(this, "ParentComponent", {
props: { activityLocalId: activity.localId },
target: this.widget.el,
});
assert.strictEqual(
document.querySelectorAll('.o_Activity').length,
1,
@@ -1026,16 +1133,24 @@ QUnit.test('activity mark done popover close on ESCAPE', async function (assert)
// This test is not in activity_mark_done_popover_tests.js as it requires the activity mark done
// component to have a parent in order to allow testing interactions the popover.
assert.expect(2);
await this.start();
const activity = this.messaging.models['Activity'].create({
canWrite: true,
category: 'not_upload_file',
this.data['res.partner'].records.push({
activity_ids: [12],
id: 100,
});
this.data['mail.activity'].records.push({
activity_category: 'default',
activity_type_id: 1,
can_write: true,
id: 12,
thread: insert({ id: 42, model: 'res.partner' }),
res_id: 100,
res_model: 'res.partner',
});
const { createChatterContainerComponent } = await this.start();
await createChatterContainerComponent({
threadId: 100,
threadModel: 'res.partner',
});
await this.createActivityComponent(activity);
await afterNextRender(() => {
document.querySelector('.o_Activity_markDoneButton').click();
});
@@ -1061,14 +1176,24 @@ QUnit.test('activity mark done popover click on discard', async function (assert
// component to have a parent in order to allow testing interactions the popover.
assert.expect(3);
await this.start();
const activity = this.messaging.models['Activity'].create({
canWrite: true,
category: 'not_upload_file',
id: 12,
thread: insert({ id: 42, model: 'res.partner' }),
this.data['res.partner'].records.push({
activity_ids: [12],
id: 100,
});
await this.createActivityComponent(activity);
this.data['mail.activity'].records.push({
activity_category: 'default',
activity_type_id: 1,
can_write: true,
id: 12,
res_id: 100,
res_model: 'res.partner',
});
const { createChatterContainerComponent } = await this.start();
await createChatterContainerComponent({
threadId: 100,
threadModel: 'res.partner',
});
await afterNextRender(() => {
document.querySelector('.o_Activity_markDoneButton').click();
});
@@ -1114,15 +1239,25 @@ QUnit.test('data-oe-id & data-oe-model link redirection on click', async functio
);
assert.step('do-action:openFormView_some.model_250');
});
await this.start({ env: { bus } });
const activity = this.messaging.models['Activity'].create({
canWrite: true,
category: 'not_upload_file',
this.data['res.partner'].records.push({
activity_ids: [12],
id: 100,
});
this.data['mail.activity'].records.push({
activity_category: 'default',
activity_type_id: 1,
can_write: true,
id: 12,
note: `<p><a href="#" data-oe-id="250" data-oe-model="some.model">some.model_250</a></p>`,
thread: insert({ id: 42, model: 'res.partner' }),
res_id: 100,
res_model: 'res.partner',
});
const { createChatterContainerComponent } = await this.start({ env: { bus } });
await createChatterContainerComponent({
threadId: 100,
threadModel: 'res.partner',
});
await this.createActivityComponent(activity);
assert.containsOnce(
document.body,
'.o_Activity_note',
@@ -410,6 +410,15 @@ async function createRootMessagingComponent(self, componentName, { props = {}, t
await createRootComponent(self, getMessagingComponent(componentName), { props, target });
}
function getCreateChatterContainerComponent({ components, env, widget }) {
return async function createChatterContainerComponent(props) {
await createRootMessagingComponent({ components, env }, "ChatterContainer", {
props,
target: widget.el,
});
};
}
function getCreateComposerComponent({ components, env, modelManager, widget }) {
return async function createComposerComponent(composer, props) {
const composerView = modelManager.messaging.models['ComposerView'].create({
@@ -798,6 +807,7 @@ async function start(param0 = {}) {
await waitUntilEventPromise;
return {
...result,
createChatterContainerComponent: getCreateChatterContainerComponent({ components, env: testEnv, widget }),
createComposerComponent: getCreateComposerComponent({ components, env: testEnv, modelManager, widget }),
createComposerSuggestionComponent: getCreateComposerSuggestionComponent({ components, env: testEnv, modelManager, widget }),
createMessageComponent: getCreateMessageComponent({ components, env: testEnv, modelManager, widget }),
+5 -5
View File
@@ -330,10 +330,10 @@ QUnit.test('activity view: activity widget', async function (assert) {
await testUtils.dom.click(today.find('.o_closest_deadline'));
assert.hasClass(dropdown,'show', "dropdown should be displayed");
assert.ok(dropdown.find('.o_activity_color_today:contains(Today)').length, "Title should be today");
assert.ok(dropdown.find('.o_activity_title_entry[data-activity-id="2"]:first div:contains(template8)').length,
"template8 should be available");
assert.ok(dropdown.find('.o_activity_title_entry[data-activity-id="2"]:eq(1) div:contains(template9)').length,
"template9 should be available");
assert.ok(dropdown.find('.o_activity_title_entry[data-activity-id="2"]:first div:contains(Template1)').length,
"Template1 should be available");
assert.ok(dropdown.find('.o_activity_title_entry[data-activity-id="2"]:eq(1) div:contains(Template2)').length,
"Template2 should be available");
await testUtils.dom.click(dropdown.find('.o_activity_title_entry[data-activity-id="2"]:first .o_activity_template_preview'));
await testUtils.dom.click(dropdown.find('.o_activity_title_entry[data-activity-id="2"]:first .o_activity_template_send'));
@@ -642,7 +642,7 @@ QUnit.test("Schedule activity dialog uses the same search view as activity view"
function mockRPC(route, args) {
if (args.method === "load_views") {
assert.step(JSON.stringify(args.kwargs.views));
}
}
}
const webClient = await createWebClient({ serverData, mockRPC, legacyParams: {withLegacyMockServer: true} });
@@ -42,24 +42,29 @@ export class MockModels {
activity_type_id: { string: "Activity type", type: "many2one", relation: "mail.activity.type" },
can_write: { string: "Can write", type: "boolean" },
chaining_type: { string: 'Chaining Type', type: 'selection', selection: [['suggest', 'Suggest Next Activity'], ['trigger', 'Trigger Next Activity']], default: 'suggest' },
create_date: { string: "Create Date", type: "date", default() { return moment().format('YYYY-MM-DD'); } },
create_uid: { string: "Created By", type: "many2one", relation: 'res.users' },
display_name: { string: "Display name", type: "char" },
date_deadline: { string: "Due Date", type: "date", default() { return moment().format('YYYY-MM-DD'); } },
display_name: { string: "Display name", type: "char" },
icon: { type: 'char' },
mail_template_ids: { string: "Mail templates", type: "many2many", relation: "mail.template" },
note: { string: "Note", type: "html" },
res_id: { type: 'integer' },
request_partner_id: { string: "requesting partner", type: 'many2one', relation: 'res.partner' },
res_id: { string: 'Related document id', type: 'integer' },
res_model: { type: 'char' },
state: { string: 'State', type: 'selection', selection: [['overdue', 'Overdue'], ['today', 'Today'], ['planned', 'Planned']] },
summary: { string: "Summary", type: "char" },
user_id: { string: "Assigned to", type: "many2one", relation: 'res.users' },
},
records: [],
},
'mail.activity.type': {
fields: {
chaining_type: { string: 'Chaining Type', type: 'selection', selection: [['suggest', 'Suggest Next Activity'], ['trigger', 'Trigger Next Activity']], default: 'suggest' },
category: { string: 'Category', type: 'selection', selection: [['default', 'Other'], ['upload_file', 'Upload File']] },
chaining_type: { string: 'Chaining Type', type: 'selection', selection: [['suggest', 'Suggest Next Activity'], ['trigger', 'Trigger Next Activity']], default: 'suggest' },
decoration_type: { string: "Decoration Type", type: "selection", selection: [['warning', 'Alert'], ['danger', 'Error']] },
icon: { string: 'icon', type: "char" },
mail_template_ids: { string: "Mail templates", type: "many2many", relation: "mail.template" },
name: { string: "Name", type: "char" },
},
records: [
@@ -187,6 +192,12 @@ export class MockModels {
},
records: [],
},
'mail.template': {
fields: {
name: { string: "Name", type: "char" },
},
records: [],
},
'res.users.settings': {
fields: {
is_discuss_sidebar_category_channel_open: { string: "Is Discuss Sidebar Category Channel Open?", type: 'boolean', default: true },
+30 -14
View File
@@ -137,16 +137,8 @@ MockServer.include({
}
// mail.activity methods
if (args.model === 'mail.activity' && args.method === 'activity_format') {
let res = this._mockRead(args.model, args.args, args.kwargs);
res = res.map(function (record) {
if (record.mail_template_ids) {
record.mail_template_ids = record.mail_template_ids.map(function (template_id) {
return { id: template_id, name: "template" + template_id };
});
}
return record;
});
return res;
return this._mockMailActivityActivityFormat(args);
}
if (args.model === 'mail.activity' && args.method === 'get_activity_data') {
const res_model = args.args[0] || args.kwargs.res_model;
@@ -307,6 +299,30 @@ MockServer.include({
// Private Mocked Routes
//--------------------------------------------------------------------------
/**
* Simulates `activity_format` on `mail.activity`.
*
* @private
* @param {Object} args
* @returns {Object[]}
*/
_mockMailActivityActivityFormat(args) {
let res = this._mockRead(args.model, args.args, args.kwargs);
res = res.map(record => {
if (record.mail_template_ids) {
record.mail_template_ids = record.mail_template_ids.map(template_id => {
const template = this._getRecords('mail.template', [['id', '=', template_id]])[0];
return {
id: template.id,
name: template.name,
};
});
}
return record;
});
return res;
},
/**
* Simulates the `/mail/attachment/delete` route.
*
@@ -569,13 +585,13 @@ MockServer.include({
});
return {
activity_types: activityTypes.map(function (type) {
activity_types: activityTypes.map((type) => {
let mailTemplates = [];
if (type.mail_template_ids) {
mailTemplates = type.mail_template_ids.map(function (id) {
const template = _.findWhere(self.data['mail.template'].records, { id: id });
mailTemplates = type.mail_template_ids.map((template_id) => {
const template = this._getRecords('mail.template', [['id', '=', template_id]])[0];
return {
id: id,
id: template.id,
name: template.name,
};
});
+3
View File
@@ -110,6 +110,9 @@ Featuring
'website_slides/static/lib/pdfslidesviewer/PDFSlidesViewer.js',
'website_slides/static/src/js/slides_embed.js',
],
'web.tests_assets': [
'website_slides/static/src/tests/helpers/mock_models.js',
],
'web.qunit_suite_tests': [
'website_slides/static/src/components/activity/activity_tests.js',
],
@@ -1,13 +1,6 @@
odoo.define('website_slides/static/src/tests/activity_tests.js', function (require) {
'use strict';
/** @odoo-module **/
const { insert } = require('@mail/model/model_field_command');
const {
afterEach,
beforeEach,
createRootMessagingComponent,
start,
} = require('@mail/utils/test_utils');
import { afterEach, beforeEach, start } from '@mail/utils/test_utils';
QUnit.module('website_slides', {}, function () {
QUnit.module('components', {}, function () {
@@ -15,20 +8,13 @@ QUnit.module('activity', {}, function () {
QUnit.module('activity_tests.js', {
beforeEach() {
beforeEach(this);
this.createActivityComponent = async activity => {
await createRootMessagingComponent(this, "Activity", {
props: { activityLocalId: activity.localId },
target: this.widget.el,
});
};
this.start = async params => {
const { env, widget } = await start(Object.assign({}, params, {
data: this.data,
}));
const res = await start({ ...params, data: this.data });
const { components, env, widget } = res;
this.components = components;
this.env = env;
this.widget = widget;
return res;
};
},
afterEach() {
@@ -39,7 +25,19 @@ QUnit.module('activity_tests.js', {
QUnit.test('grant course access', async function (assert) {
assert.expect(8);
await this.start({
this.data['res.partner'].records.push({ id: 5 });
this.data['slide.channel'].records.push({
activity_ids: [12],
id: 100,
});
this.data['mail.activity'].records.push({
can_write: true,
id: 12,
res_id: 100,
request_partner_id: 5,
res_model: 'slide.channel',
});
const { createChatterContainerComponent } = await this.start({
async mockRPC(route, args) {
if (args.method === 'action_grant_access') {
assert.strictEqual(args.args.length, 1);
@@ -51,23 +49,10 @@ QUnit.test('grant course access', async function (assert) {
return this._super(...arguments);
},
});
const activity = this.messaging.models['Activity'].create({
id: 100,
canWrite: true,
thread: insert({
id: 100,
model: 'slide.channel',
}),
requestingPartner: insert({
id: 5,
displayName: "Pauvre pomme",
}),
type: insert({
id: 1,
displayName: "Access Request",
}),
await createChatterContainerComponent({
threadId: 100,
threadModel: 'slide.channel',
});
await this.createActivityComponent(activity);
assert.containsOnce(document.body, '.o_Activity', "should have activity component");
assert.containsOnce(document.body, '.o_Activity_grantAccessButton', "should have grant access button");
@@ -79,7 +64,19 @@ QUnit.test('grant course access', async function (assert) {
QUnit.test('refuse course access', async function (assert) {
assert.expect(8);
await this.start({
this.data['res.partner'].records.push({ id: 5 });
this.data['slide.channel'].records.push({
activity_ids: [12],
id: 100,
});
this.data['mail.activity'].records.push({
can_write: true,
id: 12,
res_id: 100,
request_partner_id: 5,
res_model: 'slide.channel',
});
const { createChatterContainerComponent } = await this.start({
async mockRPC(route, args) {
if (args.method === 'action_refuse_access') {
assert.strictEqual(args.args.length, 1);
@@ -91,23 +88,10 @@ QUnit.test('refuse course access', async function (assert) {
return this._super(...arguments);
},
});
const activity = this.messaging.models['Activity'].create({
id: 100,
canWrite: true,
thread: insert({
id: 100,
model: 'slide.channel',
}),
requestingPartner: insert({
id: 5,
displayName: "Pauvre pomme",
}),
type: insert({
id: 1,
displayName: "Access Request",
}),
await createChatterContainerComponent({
threadId: 100,
threadModel: 'slide.channel',
});
await this.createActivityComponent(activity);
assert.containsOnce(document.body, '.o_Activity', "should have activity component");
assert.containsOnce(document.body, '.o_Activity_refuseAccessButton', "should have refuse access button");
@@ -119,5 +103,3 @@ QUnit.test('refuse course access', async function (assert) {
});
});
});
});
@@ -0,0 +1,28 @@
/** @odoo-module **/
import { MockModels } from '@mail/../tests/helpers/mock_models';
import { patch } from 'web.utils';
patch(MockModels, 'website_slides/static/tests/helpers/mock_models.js', {
//----------------------------------------------------------------------
// Public
//----------------------------------------------------------------------
/**
* @override
*/
generateData() {
const data = this._super(...arguments);
Object.assign(data, {
'slide.channel': {
fields: {
activity_ids: { string: "Activities", type: 'one2many', relation: 'mail.activity' },
},
records: [],
},
});
return data;
},
});