summaryrefslogtreecommitdiff
path: root/addons/crm/static/tests
diff options
context:
space:
mode:
authorstephanchrst <stephanchrst@gmail.com>2022-05-10 21:51:50 +0700
committerstephanchrst <stephanchrst@gmail.com>2022-05-10 21:51:50 +0700
commit3751379f1e9a4c215fb6eb898b4ccc67659b9ace (patch)
treea44932296ef4a9b71d5f010906253d8c53727726 /addons/crm/static/tests
parent0a15094050bfde69a06d6eff798e9a8ddf2b8c21 (diff)
initial commit 2
Diffstat (limited to 'addons/crm/static/tests')
-rw-r--r--addons/crm/static/tests/crm_rainbowman_tests.js384
-rw-r--r--addons/crm/static/tests/mock_server.js56
-rw-r--r--addons/crm/static/tests/tours/crm_rainbowman.js77
3 files changed, 517 insertions, 0 deletions
diff --git a/addons/crm/static/tests/crm_rainbowman_tests.js b/addons/crm/static/tests/crm_rainbowman_tests.js
new file mode 100644
index 00000000..3a0158d1
--- /dev/null
+++ b/addons/crm/static/tests/crm_rainbowman_tests.js
@@ -0,0 +1,384 @@
+odoo.define('crm.form_rainbowman_tests', function (require) {
+ "use strict";
+
+ var CrmFormView = require('crm.crm_form').CrmFormView;
+ var CrmKanbanView = require('crm.crm_kanban').CrmKanbanView;
+ var testUtils = require('web.test_utils');
+ var createView = testUtils.createView;
+
+ QUnit.module('Crm Rainbowman Triggers', {
+ beforeEach: function () {
+ const format = "YYYY-MM-DD HH:mm:ss";
+ this.data = {
+ 'res.users': {
+ fields: {
+ display_name: { string: 'Name', type: 'char' },
+ },
+ records: [
+ { id: 1, name: 'Mario' },
+ { id: 2, name: 'Luigi' },
+ { id: 3, name: 'Link' },
+ { id: 4, name: 'Zelda' },
+ ],
+ },
+ 'crm.team': {
+ fields: {
+ display_name: { string: 'Name', type: 'char' },
+ member_ids: { string: 'Members', type: 'many2many', relation: 'res.users' },
+ },
+ records: [
+ { id: 1, name: 'Mushroom Kingdom', member_ids: [1, 2] },
+ { id: 2, name: 'Hyrule', member_ids: [3, 4] },
+ ],
+ },
+ 'crm.stage': {
+ fields: {
+ display_name: { string: 'Name', type: 'char' },
+ is_won: { string: 'Is won', type: 'boolean' },
+ },
+ records: [
+ { id: 1, name: 'Start' },
+ { id: 2, name: 'Middle' },
+ { id: 3, name: 'Won', is_won: true},
+ ],
+ },
+ 'crm.lead': {
+ fields: {
+ display_name: { string: 'Name', type: 'char' },
+ planned_revenue: { string: 'Revenue', type: 'float' },
+ stage_id: { string: 'Stage', type: 'many2one', relation: 'crm.stage' },
+ team_id: { string: 'Sales Team', type: 'many2one', relation: 'crm.team' },
+ user_id: { string: 'Salesperson', type: 'many2one', relation: 'res.users' },
+ date_closed: { string: 'Date closed', type: 'datetime' },
+ },
+ records : [
+ { id: 1, name: 'Lead 1', planned_revenue: 5.0, stage_id: 1, team_id: 1, user_id: 1 },
+ { id: 2, name: 'Lead 2', planned_revenue: 5.0, stage_id: 2, team_id: 2, user_id: 4 },
+ { id: 3, name: 'Lead 3', planned_revenue: 3.0, stage_id: 3, team_id: 1, user_id: 1, date_closed: moment().subtract(5, 'days').format(format) },
+ { id: 4, name: 'Lead 4', planned_revenue: 4.0, stage_id: 3, team_id: 2, user_id: 4, date_closed: moment().subtract(23, 'days').format(format) },
+ { id: 5, name: 'Lead 5', planned_revenue: 7.0, stage_id: 3, team_id: 1, user_id: 1, date_closed: moment().subtract(20, 'days').format(format) },
+ { id: 6, name: 'Lead 6', planned_revenue: 4.0, stage_id: 2, team_id: 1, user_id: 2 },
+ { id: 7, name: 'Lead 7', planned_revenue: 1.8, stage_id: 3, team_id: 2, user_id: 3, date_closed: moment().subtract(23, 'days').format(format) },
+ { id: 8, name: 'Lead 8', planned_revenue: 1.9, stage_id: 1, team_id: 2, user_id: 3 },
+ { id: 9, name: 'Lead 9', planned_revenue: 1.5, stage_id: 3, team_id: 2, user_id: 3, date_closed: moment().subtract(5, 'days').format(format) },
+ { id: 10, name: 'Lead 10', planned_revenue: 1.7, stage_id: 2, team_id: 2, user_id: 3 },
+ { id: 11, name: 'Lead 11', planned_revenue: 2.0, stage_id: 3, team_id: 2, user_id: 4, date_closed: moment().subtract(5, 'days').format(format) },
+ ],
+ },
+ };
+ this.testFormView = {
+ arch: `
+ <form js_class="crm_form">
+ <header><field name="stage_id" widget="statusbar" options="{'clickable': '1'}"/></header>
+ <field name="name"/>
+ <field name="planned_revenue"/>
+ <field name="team_id"/>
+ <field name="user_id"/>
+ </form>`,
+ data: this.data,
+ model: 'crm.lead',
+ View: CrmFormView,
+ };
+ this.testKanbanView = {
+ arch: `
+ <kanban js_class="crm_kanban">
+ <templates>
+ <t t-name="kanban-box">
+ <div><field name="name"/></div>
+ </t>
+ </templates>
+ </kanban>`,
+ data: this.data,
+ model: 'crm.lead',
+ View: CrmKanbanView,
+ groupBy: ['stage_id'],
+ };
+ },
+ }, function () {
+ QUnit.test("first lead won, click on statusbar", async function (assert) {
+ assert.expect(2);
+
+ this.testFormView.res_id = 6;
+ this.testFormView.mockRPC = async function (route, args) {
+ const result = await this._super(...arguments);
+ if (args.model === 'crm.lead' && args.method === 'get_rainbowman_message') {
+ assert.step(result || "no rainbowman");
+ }
+ return result;
+ };
+ const form = await createView(this.testFormView);
+
+ await testUtils.dom.click(form.$(".o_statusbar_status button[data-value='3']"));
+ assert.verifySteps(['Go, go, go! Congrats for your first deal.']);
+
+ form.destroy();
+ });
+
+ QUnit.test("first lead won, click on statusbar in edit mode then save", async function (assert) {
+ assert.expect(3);
+
+ const form = await createView(_.extend(this.testFormView, {
+ res_id: 6,
+ mockRPC: async function (route, args) {
+ const result = await this._super(...arguments);
+ if (args.model === 'crm.lead' && args.method === 'get_rainbowman_message') {
+ assert.step(result || "no rainbowman");
+ }
+ return result;
+ },
+ viewOptions: {mode: 'edit'}
+ }));
+
+ await testUtils.dom.click(form.$(".o_statusbar_status button[data-value='3']"));
+ assert.verifySteps([]); // no message displayed yet
+
+ await testUtils.form.clickSave(form);
+ assert.verifySteps(['Go, go, go! Congrats for your first deal.']);
+
+ form.destroy();
+ });
+
+ QUnit.test("team record 30 days, click on statusbar", async function (assert) {
+ assert.expect(2);
+
+ this.testFormView.res_id = 2;
+ this.testFormView.mockRPC = async function (route, args) {
+ const result = await this._super(...arguments);
+ if (args.model === 'crm.lead' && args.method === 'get_rainbowman_message') {
+ assert.step(result || "no rainbowman");
+ }
+ return result;
+ };
+ const form = await createView(this.testFormView);
+
+ await testUtils.dom.click(form.$(".o_statusbar_status button[data-value='3']"));
+ assert.verifySteps(['Boom! Team record for the past 30 days.']);
+
+ form.destroy();
+ });
+
+ QUnit.test("team record 7 days, click on statusbar", async function (assert) {
+ assert.expect(2);
+
+ this.testFormView.res_id = 1;
+ this.testFormView.mockRPC = async function (route, args) {
+ const result = await this._super(...arguments);
+ if (args.model === 'crm.lead' && args.method === 'get_rainbowman_message') {
+ assert.step(result || "no rainbowman");
+ }
+ return result;
+ };
+ const form = await createView(this.testFormView);
+
+ await testUtils.dom.click(form.$(".o_statusbar_status button[data-value='3']"));
+ assert.verifySteps(['Yeah! Deal of the last 7 days for the team.']);
+
+ form.destroy();
+ });
+
+ QUnit.test("user record 30 days, click on statusbar", async function (assert) {
+ assert.expect(2);
+
+ this.testFormView.res_id = 8;
+ this.testFormView.mockRPC = async function (route, args) {
+ const result = await this._super(...arguments);
+ if (args.model === 'crm.lead' && args.method === 'get_rainbowman_message') {
+ assert.step(result || "no rainbowman");
+ }
+ return result;
+ };
+ const form = await createView(this.testFormView);
+
+ await testUtils.dom.click(form.$(".o_statusbar_status button[data-value='3']"));
+ assert.verifySteps(['You just beat your personal record for the past 30 days.']);
+
+ form.destroy();
+ });
+
+ QUnit.test("user record 7 days, click on statusbar", async function (assert) {
+ assert.expect(2);
+
+ this.testFormView.res_id = 10;
+ this.testFormView.mockRPC = async function (route, args) {
+ const result = await this._super(...arguments);
+ if (args.model === 'crm.lead' && args.method === 'get_rainbowman_message') {
+ assert.step(result || "no rainbowman");
+ }
+ return result;
+ };
+ const form = await createView(this.testFormView);
+
+ await testUtils.dom.click(form.$(".o_statusbar_status button[data-value='3']"));
+ assert.verifySteps(['You just beat your personal record for the past 7 days.']);
+
+ form.destroy();
+ });
+
+ QUnit.test("click on stage (not won) on statusbar", async function (assert) {
+ assert.expect(2);
+
+ this.testFormView.res_id = 1;
+ this.testFormView.mockRPC = async function (route, args) {
+ const result = await this._super(...arguments);
+ if (args.model === 'crm.lead' && args.method === 'get_rainbowman_message') {
+ assert.step(result || "no rainbowman");
+ }
+ return result;
+ };
+ const form = await createView(this.testFormView);
+
+ await testUtils.dom.click(form.$(".o_statusbar_status button[data-value='2']"));
+ assert.verifySteps(['no rainbowman']);
+
+ form.destroy();
+ });
+
+ QUnit.test("first lead won, drag & drop kanban", async function (assert) {
+ assert.expect(2);
+
+ this.testKanbanView.mockRPC = async function (route, args) {
+ const result = await this._super(...arguments);
+ if (args.model === 'crm.lead' && args.method === 'get_rainbowman_message') {
+ assert.step(result || "no rainbowman");
+ }
+ return result;
+ };
+ const kanban = await createView(this.testKanbanView);
+
+ kanban.model.defaultGroupedBy = ['stage_id'];
+ await kanban.reload();
+
+ await testUtils.dom.dragAndDrop(kanban.$('.o_kanban_record:contains("Lead 6")'), kanban.$('.o_kanban_group:eq(2)'));
+ assert.verifySteps(['Go, go, go! Congrats for your first deal.']);
+
+ kanban.destroy();
+ });
+
+ QUnit.test("team record 30 days, drag & drop kanban", async function (assert) {
+ assert.expect(2);
+
+ this.testKanbanView.mockRPC = async function (route, args) {
+ const result = await this._super(...arguments);
+ if (args.model === 'crm.lead' && args.method === 'get_rainbowman_message') {
+ assert.step(result || "no rainbowman");
+ }
+ return result;
+ };
+ const kanban = await createView(this.testKanbanView);
+
+ kanban.model.defaultGroupedBy = ['stage_id'];
+ await kanban.reload();
+
+ await testUtils.dom.dragAndDrop(kanban.$('.o_kanban_record:contains("Lead 2")'), kanban.$('.o_kanban_group:eq(2)'));
+ assert.verifySteps(['Boom! Team record for the past 30 days.']);
+
+ kanban.destroy();
+ });
+
+ QUnit.test("team record 7 days, drag & drop kanban", async function (assert) {
+ assert.expect(2);
+
+ this.testKanbanView.mockRPC = async function (route, args) {
+ const result = await this._super(...arguments);
+ if (args.model === 'crm.lead' && args.method === 'get_rainbowman_message') {
+ assert.step(result || "no rainbowman");
+ }
+ return result;
+ };
+ const kanban = await createView(this.testKanbanView);
+
+ kanban.model.defaultGroupedBy = ['stage_id'];
+ await kanban.reload();
+
+ await testUtils.dom.dragAndDrop(kanban.$('.o_kanban_group:eq(0) .o_kanban_record:contains("Lead 1")'), kanban.$('.o_kanban_group:eq(2)'));
+ assert.verifySteps(['Yeah! Deal of the last 7 days for the team.']);
+
+ kanban.destroy();
+ });
+
+ QUnit.test("user record 30 days, drag & drop kanban", async function (assert) {
+ assert.expect(2);
+
+ this.testKanbanView.mockRPC = async function (route, args) {
+ const result = await this._super(...arguments);
+ if (args.model === 'crm.lead' && args.method === 'get_rainbowman_message') {
+ assert.step(result || "no rainbowman");
+ }
+ return result;
+ };
+ const kanban = await createView(this.testKanbanView);
+
+ kanban.model.defaultGroupedBy = ['stage_id'];
+ await kanban.reload();
+
+ await testUtils.dom.dragAndDrop(kanban.$('.o_kanban_record:contains("Lead 8")'), kanban.$('.o_kanban_group:eq(2)'));
+ assert.verifySteps(['You just beat your personal record for the past 30 days.']);
+
+ kanban.destroy();
+ });
+
+ QUnit.test("user record 7 days, drag & drop kanban", async function (assert) {
+ assert.expect(2);
+
+ this.testKanbanView.mockRPC = async function (route, args) {
+ const result = await this._super(...arguments);
+ if (args.model === 'crm.lead' && args.method === 'get_rainbowman_message') {
+ assert.step(result || "no rainbowman");
+ }
+ return result;
+ };
+ const kanban = await createView(this.testKanbanView);
+
+ kanban.model.defaultGroupedBy = ['stage_id'];
+ await kanban.reload();
+
+ await testUtils.dom.dragAndDrop(kanban.$('.o_kanban_record:contains("Lead 10")'), kanban.$('.o_kanban_group:eq(2)'));
+ assert.verifySteps(['You just beat your personal record for the past 7 days.']);
+
+ kanban.destroy();
+ });
+
+ QUnit.test("drag & drop record kanban in stage not won", async function (assert) {
+ assert.expect(2);
+
+ this.testKanbanView.mockRPC = async function (route, args) {
+ const result = await this._super(...arguments);
+ if (args.model === 'crm.lead' && args.method === 'get_rainbowman_message') {
+ assert.step(result || "no rainbowman");
+ }
+ return result;
+ };
+ const kanban = await createView(this.testKanbanView);
+
+ kanban.model.defaultGroupedBy = ['stage_id'];
+ await kanban.reload();
+
+ await testUtils.dom.dragAndDrop(kanban.$('.o_kanban_record:contains("Lead 8")'), kanban.$('.o_kanban_group:eq(1)'));
+ assert.verifySteps(["no rainbowman"]);
+
+ kanban.destroy();
+ });
+
+ QUnit.test("drag & drop record in kanban not grouped by stage_id", async function (assert) {
+ assert.expect(1);
+
+ this.testKanbanView.mockRPC = async function (route, args) {
+ const result = await this._super(...arguments);
+ if (args.model === 'crm.lead' && args.method === 'get_rainbowman_message') {
+ assert.step(result || "no rainbowman");
+ }
+ return result;
+ };
+ this.testKanbanView.groupBy = ['user_id'];
+ const kanban = await createView(this.testKanbanView);
+
+ kanban.model.defaultGroupedBy = ['stage_id'];
+ await kanban.reload();
+
+ await testUtils.dom.dragAndDrop(kanban.$('.o_kanban_group:eq(0) .o_kanban_record:first'), kanban.$('.o_kanban_group:eq(1)'));
+ assert.verifySteps([]); // Should never pass by the rpc
+
+ kanban.destroy();
+ });
+ });
+});
diff --git a/addons/crm/static/tests/mock_server.js b/addons/crm/static/tests/mock_server.js
new file mode 100644
index 00000000..0c6c0fbb
--- /dev/null
+++ b/addons/crm/static/tests/mock_server.js
@@ -0,0 +1,56 @@
+odoo.define('crm.MockServer', function (require) {
+ 'use strict';
+
+ var MockServer = require('web.MockServer');
+
+ MockServer.include({
+ //--------------------------------------------------------------------------
+ // Private
+ //--------------------------------------------------------------------------
+
+ /**
+ * @override
+ * @private
+ */
+ async _performRpc(route, args) {
+ if (args.model === 'crm.lead' && args.method === 'get_rainbowman_message') {
+ let message = false;
+ const records = this.data['crm.lead'].records;
+ const record = records.find(r => r.id === args.args[0][0]);
+ const won_stage = this.data['crm.stage'].records.find(s => s.is_won);
+ if (record.stage_id === won_stage.id && record.user_id && record.team_id && record.planned_revenue > 0) {
+ const now = moment();
+ let query_result = {};
+ // Total won
+ query_result['total_won'] = records.filter(r => r.stage_id === won_stage.id && r.user_id === record.user_id).length;
+ // Max team 30 days
+ const recordsTeam30 = records.filter(r => r.stage_id === won_stage.id && r.team_id === record.team_id && (!r.date_closed || moment.duration(now.diff(moment(r.date_closed))).days() <= 30));
+ query_result['max_team_30'] = Math.max(...recordsTeam30.map(r => r.planned_revenue));
+ // Max team 7 days
+ const recordsTeam7 = records.filter(r => r.stage_id === won_stage.id && r.team_id === record.team_id && (!r.date_closed || moment.duration(now.diff(moment(r.date_closed))).days() <= 7));
+ query_result['max_team_7'] = Math.max(...recordsTeam7.map(r => r.planned_revenue));
+ // Max User 30 days
+ const recordsUser30 = records.filter(r => r.stage_id === won_stage.id && r.user_id === record.user_id && (!r.date_closed || moment.duration(now.diff(moment(r.date_closed))).days() <= 30));
+ query_result['max_user_30'] = Math.max(...recordsUser30.map(r => r.planned_revenue));
+ // Max User 7 days
+ const recordsUser7 = records.filter(r => r.stage_id === won_stage.id && r.user_id === record.user_id && (!r.date_closed || moment.duration(now.diff(moment(r.date_closed))).days() <= 7));
+ query_result['max_user_7'] = Math.max(...recordsUser7.map(r => r.planned_revenue));
+
+ if (query_result.total_won === 1) {
+ message = "Go, go, go! Congrats for your first deal.";
+ } else if (query_result.max_team_30 === record.planned_revenue) {
+ message = "Boom! Team record for the past 30 days.";
+ } else if (query_result.max_team_7 === record.planned_revenue) {
+ message = "Yeah! Deal of the last 7 days for the team.";
+ } else if (query_result.max_user_30 === record.planned_revenue) {
+ message = "You just beat your personal record for the past 30 days.";
+ } else if (query_result.max_user_7 === record.planned_revenue) {
+ message = "You just beat your personal record for the past 7 days.";
+ }
+ }
+ return message;
+ }
+ return this._super(...arguments);
+ },
+ });
+});
diff --git a/addons/crm/static/tests/tours/crm_rainbowman.js b/addons/crm/static/tests/tours/crm_rainbowman.js
new file mode 100644
index 00000000..3cfed895
--- /dev/null
+++ b/addons/crm/static/tests/tours/crm_rainbowman.js
@@ -0,0 +1,77 @@
+odoo.define('crm.tour_crm_rainbowman', function (require) {
+ "use strict";
+
+ var tour = require('web_tour.tour');
+
+ tour.register('crm_rainbowman', {
+ test: true,
+ url: "/web",
+ }, [
+ tour.stepUtils.showAppsMenuItem(),
+ {
+ trigger: ".o_app[data-menu-xmlid='crm.crm_menu_root']",
+ content: "open crm app",
+ }, {
+ trigger: ".o-kanban-button-new",
+ content: "click create",
+ }, {
+ trigger: "input[name=name]",
+ content: "complete name",
+ run: "text Test Lead 1",
+ }, {
+ trigger: "div[name=expected_revenue] > input",
+ content: "complete expected revenue",
+ run: "text 999999997",
+ }, {
+ trigger: "button.o_kanban_add",
+ content: "create lead",
+ }, {
+ trigger: ".o_kanban_record .o_kanban_record_title:contains('Test Lead 1')",
+ content: "move to won stage",
+ run: "drag_and_drop .o_opportunity_kanban .o_kanban_group:eq(3) "
+ }, {
+ trigger: ".o_reward_rainbow",
+ extra_trigger: ".o_reward_rainbow",
+ run: function () {} // check rainbowman is properly displayed
+ }, {
+ trigger: ".o-kanban-button-new",
+ content: "create second lead",
+ }, {
+ trigger: "input[name=name]",
+ content: "complete name",
+ run: "text Test Lead 2",
+ }, {
+ trigger: "div[name=expected_revenue] > input",
+ content: "complete expected revenue",
+ run: "text 999999998",
+ }, {
+ trigger: "button.o_kanban_add",
+ content: "create lead",
+ }, {
+ trigger: ".o_kanban_record .o_kanban_record_title:contains('Test Lead 2')",
+ run: function () {} // wait for the record to be properly created
+ }, {
+ // move first test back to new stage to be able to test rainbowman a second time
+ trigger: ".o_kanban_record .o_kanban_record_title:contains('Test Lead 1')",
+ content: "move back to new stage",
+ run: "drag_and_drop .o_opportunity_kanban .o_kanban_group:eq(0) "
+ }, {
+ trigger: ".o_kanban_record .o_kanban_record_title:contains('Test Lead 2')",
+ content: "click on second lead",
+ }, {
+ trigger: ".o_statusbar_status button[data-value='4']",
+ content: "move lead to won stage",
+ }, {
+ trigger: ".o_statusbar_status button[data-value='1']",
+ extra_trigger: ".o_reward_rainbow",
+ content: "move lead to previous stage & rainbowman appears",
+ }, {
+ trigger: "button[name=action_set_won_rainbowman]",
+ content: "click button mark won",
+ }, {
+ trigger: ".o_menu_brand",
+ extra_trigger: ".o_reward_rainbow",
+ content: "last rainbowman appears",
+ }
+ ]);
+});