diff --git a/addons/mail/static/src/components/activity/tests/activity_tests.js b/addons/mail/static/src/components/activity/tests/activity_tests.js index 60b4f40f444..39fe49d3546 100644 --- a/addons/mail/static/src/components/activity/tests/activity_tests.js +++ b/addons/mail/static/src/components/activity/tests/activity_tests.js @@ -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` -
-

parent

- - - -
- `, - }); - 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: `

some.model_250

`, - 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', diff --git a/addons/mail/static/src/utils/test_utils.js b/addons/mail/static/src/utils/test_utils.js index d9ab377a676..3c064d6d42a 100644 --- a/addons/mail/static/src/utils/test_utils.js +++ b/addons/mail/static/src/utils/test_utils.js @@ -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 }), diff --git a/addons/mail/static/tests/activity_tests.js b/addons/mail/static/tests/activity_tests.js index 85a5410aff0..064e962a9b2 100644 --- a/addons/mail/static/tests/activity_tests.js +++ b/addons/mail/static/tests/activity_tests.js @@ -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} }); diff --git a/addons/mail/static/tests/helpers/mock_models.js b/addons/mail/static/tests/helpers/mock_models.js index 806b923a8e5..6356f20c0b7 100644 --- a/addons/mail/static/tests/helpers/mock_models.js +++ b/addons/mail/static/tests/helpers/mock_models.js @@ -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 }, diff --git a/addons/mail/static/tests/helpers/mock_server.js b/addons/mail/static/tests/helpers/mock_server.js index 3d6241d404c..5e566bc267c 100644 --- a/addons/mail/static/tests/helpers/mock_server.js +++ b/addons/mail/static/tests/helpers/mock_server.js @@ -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, }; }); diff --git a/addons/website_slides/__manifest__.py b/addons/website_slides/__manifest__.py index 7081492b55a..f7fc5a58eb0 100644 --- a/addons/website_slides/__manifest__.py +++ b/addons/website_slides/__manifest__.py @@ -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', ], diff --git a/addons/website_slides/static/src/components/activity/activity_tests.js b/addons/website_slides/static/src/components/activity/activity_tests.js index 9a3f05390da..7c726c50a33 100644 --- a/addons/website_slides/static/src/components/activity/activity_tests.js +++ b/addons/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) { }); }); }); - -}); diff --git a/addons/website_slides/static/src/tests/helpers/mock_models.js b/addons/website_slides/static/src/tests/helpers/mock_models.js new file mode 100644 index 00000000000..7c4ae4b1704 --- /dev/null +++ b/addons/website_slides/static/src/tests/helpers/mock_models.js @@ -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; + }, + +});