[IMP] mail: adapt activity qunit test suite
The activity view has been refactored and improved so the qunit test suite needed to be adapted. More tests have also been added to test new features (progressbar, schedule an activity, etc.) and the method 'get_activity' has been correctly mocked (the result was previously hardcoded). Task 1894990
This commit is contained in:
committed by
Martin Geubelle
parent
ff6415b63c
commit
983d098794
@@ -7,70 +7,6 @@ var testUtils = require('web.test_utils');
|
||||
var createActionManager = testUtils.createActionManager;
|
||||
|
||||
var createView = testUtils.createView;
|
||||
var ACTIVITY_DATA = {
|
||||
"grouped_activities":{
|
||||
"13":{
|
||||
"1":{
|
||||
"count":1,
|
||||
"state":"planned",
|
||||
"o_closest_deadline":"2018-08-16",
|
||||
"ids":[
|
||||
1
|
||||
]
|
||||
}
|
||||
},
|
||||
"30":{
|
||||
"1":{
|
||||
"count":1,
|
||||
"state":"today",
|
||||
"o_closest_deadline":"2018-08-16",
|
||||
"ids":[
|
||||
2
|
||||
]
|
||||
},
|
||||
"2":{
|
||||
"count":2,
|
||||
"state":"overdue",
|
||||
"o_closest_deadline":"2018-09-16",
|
||||
"ids":[
|
||||
3
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"activity_types":[
|
||||
[
|
||||
1,
|
||||
"Email",
|
||||
[
|
||||
{
|
||||
"id":9,
|
||||
"name":"Task: Rating Request"
|
||||
},
|
||||
{
|
||||
"id":8,
|
||||
"name":"Task: Reception Acknowledgment"
|
||||
}
|
||||
]
|
||||
],
|
||||
[
|
||||
2,
|
||||
"Call",
|
||||
[]
|
||||
]
|
||||
],
|
||||
"model":"task",
|
||||
"res_ids":[
|
||||
[
|
||||
30,
|
||||
"Office planning"
|
||||
],
|
||||
[
|
||||
13,
|
||||
"Meeting Room Furnitures"
|
||||
]
|
||||
]
|
||||
};
|
||||
|
||||
QUnit.module('mail', {}, function () {
|
||||
QUnit.module('activity view', {
|
||||
@@ -79,11 +15,18 @@ QUnit.module('activity view', {
|
||||
task: {
|
||||
fields: {
|
||||
id: {string: 'ID', type: 'integer'},
|
||||
foo: {string: "Foo", type: "char"},
|
||||
activity_ids: {
|
||||
string: 'Activities',
|
||||
type: 'one2many',
|
||||
relation: 'mail.activity',
|
||||
relation_field: 'res_id',
|
||||
},
|
||||
},
|
||||
records: [
|
||||
{id: 13},
|
||||
{id: 30},
|
||||
]
|
||||
{id: 13, foo: 'Meeting Room Furnitures', activity_ids: [1]},
|
||||
{id: 30, foo: 'Office planning', activity_ids: [2, 3]},
|
||||
],
|
||||
},
|
||||
partner: {
|
||||
fields: {
|
||||
@@ -96,6 +39,7 @@ QUnit.module('activity view', {
|
||||
},
|
||||
'mail.activity': {
|
||||
fields: {
|
||||
res_id: { string: 'Related document id', type: 'integer' },
|
||||
activity_type_id: { string: "Activity type", type: "many2one", relation: "mail.activity.type" },
|
||||
display_name: { string: "Display name", type: "char" },
|
||||
date_deadline: { string: "Due Date", type: "date" },
|
||||
@@ -111,6 +55,7 @@ QUnit.module('activity view', {
|
||||
records:[
|
||||
{
|
||||
id: 1,
|
||||
res_id: 13,
|
||||
display_name: "An activity",
|
||||
date_deadline: moment().add(3, "days").format("YYYY-MM-DD"), // now
|
||||
can_write: true,
|
||||
@@ -121,6 +66,7 @@ QUnit.module('activity view', {
|
||||
user_id:2,
|
||||
},{
|
||||
id: 2,
|
||||
res_id: 30,
|
||||
display_name: "An activity",
|
||||
date_deadline: moment().format("YYYY-MM-DD"), // now
|
||||
can_write: true,
|
||||
@@ -130,6 +76,7 @@ QUnit.module('activity view', {
|
||||
user_id:2,
|
||||
},{
|
||||
id: 3,
|
||||
res_id: 30,
|
||||
display_name: "An activity",
|
||||
date_deadline: moment().subtract(2, "days").format("YYYY-MM-DD"), // now
|
||||
can_write: true,
|
||||
@@ -151,62 +98,116 @@ QUnit.module('activity view', {
|
||||
},
|
||||
'mail.activity.type': {
|
||||
fields: {
|
||||
mail_template_ids: { string: "Mail templates", type: "many2many", relation: "mail.template" },
|
||||
name: { string: "Name", type: "char" },
|
||||
},
|
||||
records: [
|
||||
{ id: 1, name: "Email" },
|
||||
{ id: 1, name: "Email", mail_template_ids: [8, 9]},
|
||||
{ id: 2, name: "Call" },
|
||||
{ id: 3, name: "Call for Demo" },
|
||||
{ id: 4, name: "To Do" },
|
||||
],
|
||||
},
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
var activityDateFormat = function (date) {
|
||||
return date.toLocaleDateString(moment().locale(), { day: 'numeric', month: 'short' });
|
||||
};
|
||||
|
||||
QUnit.test('activity view: simple activity rendering', async function (assert) {
|
||||
assert.expect(7);
|
||||
assert.expect(14);
|
||||
var activity = await createView({
|
||||
View: ActivityView,
|
||||
model: 'task',
|
||||
data: this.data,
|
||||
arch: '<activity string="Task"/>',
|
||||
mockRPC: function(route, args) {
|
||||
if (args.method === 'get_activity_data') {
|
||||
return Promise.resolve(ACTIVITY_DATA);
|
||||
}
|
||||
return this._super(route, args);
|
||||
arch: '<activity string="Task">' +
|
||||
'<templates>' +
|
||||
'<div t-name="activity-box">' +
|
||||
'<field name="foo"/>' +
|
||||
'</div>' +
|
||||
'</templates>' +
|
||||
'</activity>',
|
||||
intercepts: {
|
||||
do_action: function (event) {
|
||||
assert.deepEqual(event.data.action, {
|
||||
context: {
|
||||
default_res_id: 30,
|
||||
default_res_model: "task",
|
||||
default_activity_type_id: 3,
|
||||
},
|
||||
res_id: false,
|
||||
res_model: "mail.activity",
|
||||
target: "new",
|
||||
type: "ir.actions.act_window",
|
||||
view_mode: "form",
|
||||
view_type: "form",
|
||||
views: [[false, "form"]]
|
||||
},
|
||||
"should do a do_action with correct parameters");
|
||||
event.data.options.on_close();
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
assert.containsOnce(activity, 'table',
|
||||
'should have a table');
|
||||
assert.ok(activity.$('table thead tr:first th:nth-child(2) span:first:contains(Email)').length,
|
||||
'should contain "Email" in header of first column');
|
||||
assert.ok(activity.$('table thead tr:first th:nth-child(3) span:first:contains(Call)').length,
|
||||
'should contain "Call" in header of second column');
|
||||
var $th1 = activity.$('table thead tr:first th:nth-child(2)');
|
||||
assert.containsOnce($th1, 'span:first:contains(Email)', 'should contain "Email" in header of first column');
|
||||
assert.containsOnce($th1, '.o_kanban_counter', 'should contain a progressbar in header of first column');
|
||||
assert.hasAttrValue($th1.find('.o_kanban_counter_progress .progress-bar:first'), 'data-original-title', '1 planned',
|
||||
'the counter progressbars should be correctly displayed');
|
||||
assert.hasAttrValue($th1.find('.o_kanban_counter_progress .progress-bar:nth-child(2)'), 'data-original-title', '1 today',
|
||||
'the counter progressbars should be correctly displayed');
|
||||
var $th2 = activity.$('table thead tr:first th:nth-child(3)');
|
||||
assert.containsOnce($th2, 'span:first:contains(Call)', 'should contain "Call" in header of second column');
|
||||
assert.hasAttrValue($th2.find('.o_kanban_counter_progress .progress-bar:last'), 'data-original-title', '1 overdue',
|
||||
'the counter progressbars should be correctly displayed');
|
||||
assert.containsNone(activity, 'table thead tr:first th:nth-child(4) .o_kanban_counter',
|
||||
'should not contain a progressbar in header of 3rd column');
|
||||
assert.ok(activity.$('table tbody tr:first td:first:contains(Office planning)').length,
|
||||
'should contain "Office planning" in first colum of first row');
|
||||
assert.ok(activity.$('table tbody tr:nth-child(2) td:first:contains(Meeting Room Furnitures)').length,
|
||||
'should contain "Meeting Room Furnitures" in first colum of second row');
|
||||
assert.ok(activity.$('table tbody tr:first td:nth-child(2).today .o_closest_deadline:contains(Aug 16)').length,
|
||||
'should contain an activity for today with date Aug 16 in second cell of first line');
|
||||
assert.ok(activity.$('table tbody tr:nth-child(2) td:nth-child(2).planned .o_closest_deadline:contains(Aug 16)').length,
|
||||
'should contain a planned activity with date Aug 16 in second cell of second line');
|
||||
|
||||
var today = activityDateFormat(new Date());
|
||||
|
||||
assert.ok(activity.$('table tbody tr:first td:nth-child(2).today .o_closest_deadline:contains(' + today + ')').length,
|
||||
'should contain an activity for today in second cell of first line ' + today);
|
||||
var td = 'table tbody tr:nth-child(1) td.o_activity_empty_cell';
|
||||
assert.containsN(activity, td, 2, 'should contain an empty cell as no activity scheduled yet.');
|
||||
|
||||
// schedule an activity (this triggers a do_action)
|
||||
testUtils.fields.editAndTrigger(activity.$(td + ':first'), null, ['mouseenter', 'click']);
|
||||
assert.containsOnce(activity, 'table tfoot tr .o_record_selector',
|
||||
'should contain search more selector to choose the record to schedule an activity for it');
|
||||
|
||||
activity.destroy();
|
||||
});
|
||||
|
||||
QUnit.test('activity view: no content rendering', async function (assert) {
|
||||
assert.expect(2);
|
||||
|
||||
// remove activities from tasks
|
||||
this.data.task.records.forEach(function (task) {
|
||||
task.activity_ids = false;
|
||||
});
|
||||
|
||||
// remove activity types
|
||||
this.data['mail.activity.type'].records = [];
|
||||
|
||||
var activity = await createView({
|
||||
View: ActivityView,
|
||||
model: 'task',
|
||||
data: this.data,
|
||||
arch: '<activity string="Task"/>',
|
||||
mockRPC: function (route, args) {
|
||||
if (args.method === 'get_activity_data') {
|
||||
return Promise.resolve({ activity_types: [] });
|
||||
}
|
||||
return this._super(route, args);
|
||||
},
|
||||
arch: '<activity string="Task">' +
|
||||
'<templates>' +
|
||||
'<div t-name="activity-box">' +
|
||||
'<field name="foo"/>' +
|
||||
'</div>' +
|
||||
'</templates>' +
|
||||
'</activity>',
|
||||
});
|
||||
|
||||
assert.containsOnce(activity, '.o_view_nocontent',
|
||||
@@ -224,16 +225,19 @@ QUnit.test('activity view: batch send mail on activity', async function (assert)
|
||||
View: ActivityView,
|
||||
model: 'task',
|
||||
data: this.data,
|
||||
arch: '<activity string="Task"/>',
|
||||
arch: '<activity string="Task">' +
|
||||
'<templates>' +
|
||||
'<div t-name="activity-box">' +
|
||||
'<field name="foo"/>' +
|
||||
'</div>' +
|
||||
'</templates>' +
|
||||
'</activity>',
|
||||
mockRPC: function(route, args) {
|
||||
if (args.method === 'activity_send_mail'){
|
||||
assert.step(JSON.stringify(args.args));
|
||||
return Promise.resolve();
|
||||
}
|
||||
if (args.method === 'get_activity_data') {
|
||||
return Promise.resolve(ACTIVITY_DATA);
|
||||
}
|
||||
return this._super(route, args);
|
||||
return this._super.apply(this, arguments);
|
||||
},
|
||||
});
|
||||
assert.notOk(activity.$('table thead tr:first th:nth-child(2) span:nth-child(2) .dropdown-menu.show').length,
|
||||
@@ -243,12 +247,12 @@ QUnit.test('activity view: batch send mail on activity', async function (assert)
|
||||
assert.ok(activity.$('table thead tr:first th:nth-child(2) span:nth-child(2) .dropdown-menu.show').length,
|
||||
'dropdown should have appeared');
|
||||
|
||||
testUtils.dom.click(activity.$('table thead tr:first th:nth-child(2) span:nth-child(2) .dropdown-menu.show .o_send_mail_template:first:contains(Task: Rating Request)'));
|
||||
testUtils.dom.click(activity.$('table thead tr:first th:nth-child(2) span:nth-child(2) .dropdown-menu.show .o_send_mail_template:contains(Template2)'));
|
||||
assert.notOk(activity.$('table thead tr:first th:nth-child(2) span:nth-child(2) .dropdown-menu.show').length,
|
||||
'dropdown shouldn\'t be displayed');
|
||||
|
||||
testUtils.dom.click(activity.$('table thead tr:first th:nth-child(2) span:nth-child(2) i.fa-ellipsis-v'));
|
||||
testUtils.dom.click(activity.$('table thead tr:first th:nth-child(2) span:nth-child(2) .dropdown-menu.show .o_send_mail_template:nth-child(2):contains(Task: Reception Acknowledgment)'));
|
||||
testUtils.dom.click(activity.$('table thead tr:first th:nth-child(2) span:nth-child(2) .dropdown-menu.show .o_send_mail_template:contains(Template1)'));
|
||||
assert.verifySteps([
|
||||
'[[13,30],9]', // send mail template 9 on tasks 13 and 30
|
||||
'[[13,30],8]', // send mail template 8 on tasks 13 and 30
|
||||
@@ -263,7 +267,13 @@ QUnit.test('activity view: activity widget', async function (assert) {
|
||||
View: ActivityView,
|
||||
model: 'task',
|
||||
data: this.data,
|
||||
arch: '<activity string="Task"/>',
|
||||
arch: '<activity string="Task">' +
|
||||
'<templates>' +
|
||||
'<div t-name="activity-box">' +
|
||||
'<field name="foo"/>' +
|
||||
'</div>' +
|
||||
'</templates>'+
|
||||
'</activity>',
|
||||
mockRPC: function(route, args) {
|
||||
if (args.method === 'activity_send_mail'){
|
||||
assert.deepEqual([[30],8],args.args, "Should send template 8 on record 30");
|
||||
@@ -276,10 +286,7 @@ QUnit.test('activity view: activity widget', async function (assert) {
|
||||
assert.step('action_feedback_schedule_next');
|
||||
return Promise.resolve({serverGeneratedAction: true});
|
||||
}
|
||||
if (args.method === 'get_activity_data') {
|
||||
return Promise.resolve(ACTIVITY_DATA);
|
||||
}
|
||||
return this._super(route, args);
|
||||
return this._super.apply(this, arguments);
|
||||
},
|
||||
intercepts: {
|
||||
do_action: function (ev) {
|
||||
@@ -354,7 +361,13 @@ QUnit.test('activity view: no group_by_menu and no time_range_menu', async funct
|
||||
views: [[false, 'activity']],
|
||||
}],
|
||||
archs: {
|
||||
'task,false,activity': '<activity></activity>',
|
||||
'task,false,activity': '<activity string="Task">' +
|
||||
'<templates>' +
|
||||
'<div t-name="activity-box">' +
|
||||
'<field name="foo"/>' +
|
||||
'</div>' +
|
||||
'</templates>' +
|
||||
'</activity>',
|
||||
'task,false,search': '<search></search>',
|
||||
},
|
||||
data: this.data,
|
||||
@@ -365,9 +378,8 @@ QUnit.test('activity view: no group_by_menu and no time_range_menu', async funct
|
||||
if (args.method === 'get_activity_data') {
|
||||
assert.deepEqual(args.kwargs.context, {lang: 'zz_ZZ'},
|
||||
'The context should have been passed');
|
||||
return Promise.resolve(ACTIVITY_DATA);
|
||||
}
|
||||
return this._super(route, args);
|
||||
return this._super.apply(this, arguments);
|
||||
},
|
||||
});
|
||||
|
||||
@@ -382,5 +394,69 @@ QUnit.test('activity view: no group_by_menu and no time_range_menu', async funct
|
||||
actionManager.destroy();
|
||||
});
|
||||
|
||||
QUnit.test('activity view: search more to schedule an activity for a record of a respecting model', async function (assert) {
|
||||
assert.expect(5);
|
||||
_.extend(this.data.task.fields, {
|
||||
name: { string: "Name", type: "char" },
|
||||
});
|
||||
this.data.task.records[2] = { id: 31, name: "Task 3" };
|
||||
var activity = await createView({
|
||||
View: ActivityView,
|
||||
model: 'task',
|
||||
data: this.data,
|
||||
arch: '<activity string="Task">' +
|
||||
'<templates>' +
|
||||
'<div t-name="activity-box">' +
|
||||
'<field name="foo"/>' +
|
||||
'</div>' +
|
||||
'</templates>' +
|
||||
'</activity>',
|
||||
archs: {
|
||||
"task,false,list": '<tree string="Task"><field name="name"/></tree>',
|
||||
"task,false,search": '<search></search>',
|
||||
},
|
||||
mockRPC: function(route, args) {
|
||||
if (args.method === 'name_search') {
|
||||
args.kwargs.name = "Task";
|
||||
}
|
||||
return this._super.apply(this, arguments);
|
||||
},
|
||||
intercepts: {
|
||||
do_action: function (ev) {
|
||||
assert.step('doAction');
|
||||
var expectedAction = {
|
||||
context: {
|
||||
default_res_id: { id: 31, display_name: undefined },
|
||||
default_res_model: "task",
|
||||
},
|
||||
name: "Schedule Activity",
|
||||
res_id: false,
|
||||
res_model: "mail.activity",
|
||||
target: "new",
|
||||
type: "ir.actions.act_window",
|
||||
view_mode: "form",
|
||||
view_type: "form",
|
||||
views: [[false, "form"]],
|
||||
};
|
||||
assert.deepEqual(ev.data.action, expectedAction,
|
||||
"should execute an action with correct params");
|
||||
ev.data.options.on_close();
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
assert.containsOnce(activity, 'table tfoot tr .o_record_selector',
|
||||
'should contain search more selector to choose the record to schedule an activity for it');
|
||||
await testUtils.dom.click(activity.$('table tfoot tr .o_record_selector'));
|
||||
// search create dialog
|
||||
var $modal = $('.modal-lg');
|
||||
assert.strictEqual($modal.find('.o_data_row').length, 3, "all tasks should be available to select");
|
||||
// select a record to schedule an activity for it (this triggers a do_action)
|
||||
testUtils.dom.click($modal.find('.o_data_row:last'));
|
||||
assert.verifySteps(['doAction']);
|
||||
|
||||
activity.destroy();
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
@@ -48,6 +48,81 @@ MockServer.include({
|
||||
});
|
||||
return previews;
|
||||
},
|
||||
/**
|
||||
* Simulate the 'get_activity_method' on 'mail.activity'
|
||||
*
|
||||
* @private
|
||||
* @return {Object}
|
||||
*/
|
||||
_mockGetActivityData: function (args) {
|
||||
var self = this;
|
||||
|
||||
var domain = args.kwargs.domain;
|
||||
var model = args.kwargs.res_model;
|
||||
var records = this._getRecords(model, domain);
|
||||
|
||||
var activityTypes = this._getRecords('mail.activity.type', []);
|
||||
var activityIds = _.pluck(records, 'activity_ids').flat();
|
||||
|
||||
var groupedActivities = {};
|
||||
var resIdToDeadline = {};
|
||||
var groups = self._mockReadGroup('mail.activity', {
|
||||
domain: [['id', 'in', activityIds]],
|
||||
fields: ['res_id', 'activity_type_id', 'ids:array_agg(id)', 'date_deadline:min(date_deadline)'],
|
||||
groupby: ['res_id', 'activity_type_id'],
|
||||
lazy: false,
|
||||
});
|
||||
groups.forEach(function (group) {
|
||||
// mockReadGroup doesn't correctly return all asked fields
|
||||
var activites = self._getRecords('mail.activity', group.__domain);
|
||||
group.activity_type_id = group.activity_type_id[0];
|
||||
var minDate;
|
||||
activites.forEach(function (activity) {
|
||||
if (!minDate || moment(activity.date_deadline) < moment(minDate)) {
|
||||
minDate = activity.date_deadline;
|
||||
}
|
||||
});
|
||||
group.date_deadline = minDate;
|
||||
resIdToDeadline[group.res_id] = minDate;
|
||||
var state;
|
||||
if (group.date_deadline === moment().format("YYYY-MM-DD")) {
|
||||
state = 'today';
|
||||
} else if (moment(group.date_deadline) > moment()) {
|
||||
state = 'planned';
|
||||
} else {
|
||||
state = 'overdue';
|
||||
}
|
||||
if (!groupedActivities[group.res_id]) {
|
||||
groupedActivities[group.res_id] = {};
|
||||
}
|
||||
groupedActivities[group.res_id][group.activity_type_id] = {
|
||||
count: group.__count,
|
||||
state: state,
|
||||
o_closest_deadline: group.date_deadline,
|
||||
ids: _.pluck(activites, 'id'),
|
||||
};
|
||||
});
|
||||
|
||||
return {
|
||||
activity_types: activityTypes.map(function (type) {
|
||||
var mailTemplates = [];
|
||||
if (type.mail_template_ids) {
|
||||
mailTemplates = type.mail_template_ids.map(function (id) {
|
||||
var template = _.findWhere(self.data['mail.template'].records, {id: id});
|
||||
return {
|
||||
id: id,
|
||||
name: template.name,
|
||||
};
|
||||
});
|
||||
}
|
||||
return [type.id, type.display_name, mailTemplates];
|
||||
}),
|
||||
activity_res_ids: _.sortBy(_.pluck(records, 'id'), function (id) {
|
||||
return moment(resIdToDeadline[id]);
|
||||
}),
|
||||
grouped_activities: groupedActivities,
|
||||
};
|
||||
},
|
||||
/**
|
||||
* Simulate the '/mail/init_messaging' route
|
||||
*
|
||||
@@ -201,6 +276,9 @@ MockServer.include({
|
||||
if (args.method === 'channel_fetched') {
|
||||
return Promise.resolve();
|
||||
}
|
||||
if (args.method === 'get_activity_data') {
|
||||
return Promise.resolve(this._mockGetActivityData(args));
|
||||
}
|
||||
if (args.method === 'message_fetch') {
|
||||
return Promise.resolve(this._mockMessageFetch(args));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user