mirror of
https://github.com/bringout/oca-ocb-hr.git
synced 2026-04-26 13:52:00 +02:00
Initial commit: Hr packages
This commit is contained in:
commit
62531cd146
2820 changed files with 1432848 additions and 0 deletions
|
|
@ -0,0 +1,114 @@
|
|||
/** @odoo-module **/
|
||||
|
||||
import { UPDATE_BUS_PRESENCE_DELAY } from '@bus/im_status_service';
|
||||
|
||||
import { start, startServer } from '@mail/../tests/helpers/test_utils';
|
||||
|
||||
QUnit.module('hr_holidays', {}, function () {
|
||||
QUnit.module('components', {}, function () {
|
||||
QUnit.module('persona_im_status_icon_tests.js');
|
||||
|
||||
QUnit.test('on leave & online', async function (assert) {
|
||||
assert.expect(2);
|
||||
|
||||
const pyEnv = await startServer();
|
||||
const partnerId = pyEnv['res.partner'].create({ im_status: 'leave_online' });
|
||||
const mailChannelId = pyEnv['mail.channel'].create({});
|
||||
pyEnv['mail.message'].create({
|
||||
author_id: partnerId,
|
||||
body: 'not empty',
|
||||
model: 'mail.channel',
|
||||
res_id: mailChannelId,
|
||||
});
|
||||
const { advanceTime, afterNextRender, openDiscuss } = await start({
|
||||
discuss: {
|
||||
params: {
|
||||
default_active_id: mailChannelId,
|
||||
},
|
||||
},
|
||||
hasTimeControl: true,
|
||||
});
|
||||
await openDiscuss();
|
||||
await afterNextRender(() => advanceTime(UPDATE_BUS_PRESENCE_DELAY));
|
||||
assert.hasClass(
|
||||
document.querySelector('.o_PersonaImStatusIcon_icon'),
|
||||
'o-online',
|
||||
"persona IM status icon should have online status rendering"
|
||||
);
|
||||
assert.hasClass(
|
||||
document.querySelector('.o_PersonaImStatusIcon_icon'),
|
||||
'fa-plane',
|
||||
"persona IM status icon should have leave status rendering"
|
||||
);
|
||||
});
|
||||
|
||||
QUnit.test('on leave & away', async function (assert) {
|
||||
assert.expect(2);
|
||||
|
||||
const pyEnv = await startServer();
|
||||
const partnerId = pyEnv['res.partner'].create({ im_status: 'leave_away' });
|
||||
const mailChannelId = pyEnv['mail.channel'].create({});
|
||||
pyEnv['mail.message'].create({
|
||||
author_id: partnerId,
|
||||
body: 'not empty',
|
||||
model: 'mail.channel',
|
||||
res_id: mailChannelId,
|
||||
});
|
||||
const { advanceTime, afterNextRender, openDiscuss } = await start({
|
||||
discuss: {
|
||||
params: {
|
||||
default_active_id: mailChannelId,
|
||||
},
|
||||
},
|
||||
hasTimeControl: true,
|
||||
});
|
||||
await openDiscuss();
|
||||
await afterNextRender(() => advanceTime(UPDATE_BUS_PRESENCE_DELAY));
|
||||
assert.hasClass(
|
||||
document.querySelector('.o_PersonaImStatusIcon_icon'),
|
||||
'o-away',
|
||||
"persona IM status icon should have away status rendering"
|
||||
);
|
||||
assert.hasClass(
|
||||
document.querySelector('.o_PersonaImStatusIcon_icon'),
|
||||
'fa-plane',
|
||||
"persona IM status icon should have leave status rendering"
|
||||
);
|
||||
});
|
||||
|
||||
QUnit.test('on leave & offline', async function (assert) {
|
||||
assert.expect(2);
|
||||
|
||||
const pyEnv = await startServer();
|
||||
const partnerId = pyEnv['res.partner'].create({ im_status: 'leave_offline' });
|
||||
const mailChannelId = pyEnv['mail.channel'].create({});
|
||||
pyEnv['mail.message'].create({
|
||||
author_id: partnerId,
|
||||
body: 'not empty',
|
||||
model: 'mail.channel',
|
||||
res_id: mailChannelId,
|
||||
});
|
||||
const { advanceTime, afterNextRender, openDiscuss } = await start({
|
||||
discuss: {
|
||||
params: {
|
||||
default_active_id: mailChannelId,
|
||||
},
|
||||
},
|
||||
hasTimeControl: true,
|
||||
});
|
||||
await openDiscuss();
|
||||
await afterNextRender(() => advanceTime(UPDATE_BUS_PRESENCE_DELAY));
|
||||
assert.hasClass(
|
||||
document.querySelector('.o_PersonaImStatusIcon_icon'),
|
||||
'o-offline',
|
||||
"persona IM status icon should have offline status rendering"
|
||||
);
|
||||
assert.hasClass(
|
||||
document.querySelector('.o_PersonaImStatusIcon_icon'),
|
||||
'fa-plane',
|
||||
"persona IM status icon should have leave status rendering"
|
||||
);
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,103 @@
|
|||
/** @odoo-module **/
|
||||
|
||||
import {
|
||||
start,
|
||||
startServer,
|
||||
} from '@mail/../tests/helpers/test_utils';
|
||||
|
||||
QUnit.module('mail', {}, function () {
|
||||
QUnit.module('components', {}, function () {
|
||||
QUnit.module('thread_icon_tests.js');
|
||||
|
||||
QUnit.test('thread icon of a chat when correspondent is on leave & online', async function (assert) {
|
||||
assert.expect(2);
|
||||
|
||||
const pyEnv = await startServer();
|
||||
const resPartnerId1 = pyEnv['res.partner'].create({
|
||||
im_status: 'leave_online',
|
||||
name: 'Demo',
|
||||
});
|
||||
pyEnv['mail.channel'].create({
|
||||
channel_member_ids: [
|
||||
[0, 0, { partner_id: pyEnv.currentPartnerId }],
|
||||
[0, 0, { partner_id: resPartnerId1 }],
|
||||
],
|
||||
channel_type: 'chat',
|
||||
});
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss();
|
||||
|
||||
assert.containsOnce(
|
||||
document.body,
|
||||
'.o_ThreadIcon_online',
|
||||
"thread icon should have online status rendering"
|
||||
);
|
||||
assert.hasClass(
|
||||
document.querySelector('.o_ThreadIcon_online'),
|
||||
'fa-plane',
|
||||
"thread icon should have leave status rendering"
|
||||
);
|
||||
});
|
||||
|
||||
QUnit.test('thread icon of a chat when correspondent is on leave & away', async function (assert) {
|
||||
assert.expect(2);
|
||||
|
||||
const pyEnv = await startServer();
|
||||
const resPartnerId1 = pyEnv['res.partner'].create({
|
||||
im_status: 'leave_away',
|
||||
name: 'Demo',
|
||||
});
|
||||
pyEnv['mail.channel'].create({
|
||||
channel_member_ids: [
|
||||
[0, 0, { partner_id: pyEnv.currentPartnerId }],
|
||||
[0, 0, { partner_id: resPartnerId1 }],
|
||||
],
|
||||
channel_type: 'chat',
|
||||
});
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss();
|
||||
|
||||
assert.containsOnce(
|
||||
document.body,
|
||||
'.o_ThreadIcon_away',
|
||||
"thread icon should have away status rendering"
|
||||
);
|
||||
assert.hasClass(
|
||||
document.querySelector('.o_ThreadIcon_away'),
|
||||
'fa-plane',
|
||||
"thread icon should have leave status rendering"
|
||||
);
|
||||
});
|
||||
|
||||
QUnit.test('thread icon of a chat when correspondent is on leave & offline', async function (assert) {
|
||||
assert.expect(2);
|
||||
|
||||
const pyEnv = await startServer();
|
||||
const resPartnerId1 = pyEnv['res.partner'].create({
|
||||
im_status: 'leave_offline',
|
||||
name: 'Demo',
|
||||
});
|
||||
pyEnv['mail.channel'].create({
|
||||
channel_member_ids: [
|
||||
[0, 0, { partner_id: pyEnv.currentPartnerId }],
|
||||
[0, 0, { partner_id: resPartnerId1 }],
|
||||
],
|
||||
channel_type: 'chat',
|
||||
});
|
||||
const { openDiscuss } = await start();
|
||||
await openDiscuss();
|
||||
|
||||
assert.containsOnce(
|
||||
document.body,
|
||||
'.o_ThreadIcon_offline',
|
||||
"thread icon should have offline status rendering"
|
||||
);
|
||||
assert.hasClass(
|
||||
document.querySelector('.o_ThreadIcon_offline'),
|
||||
'fa-plane',
|
||||
"thread icon should have leave status rendering"
|
||||
);
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
/** @odoo-module **/
|
||||
|
||||
import { start, startServer } from '@mail/../tests/helpers/test_utils';
|
||||
|
||||
QUnit.module('hr_holidays', {}, function () {
|
||||
QUnit.module('components', {}, function () {
|
||||
QUnit.module('thread_view_tests.js');
|
||||
|
||||
QUnit.test('out of office message on direct chat with out of office partner', async function (assert) {
|
||||
assert.expect(2);
|
||||
|
||||
// Returning date of the out of office partner, simulates he'll be back in a month
|
||||
const returningDate = moment.utc().add(1, 'month');
|
||||
const pyEnv = await startServer();
|
||||
// Needed partner & user to allow simulation of message reception
|
||||
const resPartnerId1 = pyEnv['res.partner'].create({
|
||||
name: "Foreigner partner",
|
||||
out_of_office_date_end: returningDate.format("YYYY-MM-DD"),
|
||||
});
|
||||
const mailChannelId1 = pyEnv['mail.channel'].create({
|
||||
channel_member_ids: [
|
||||
[0, 0, { partner_id: pyEnv.currentPartnerId }],
|
||||
[0, 0, { partner_id: resPartnerId1 }],
|
||||
],
|
||||
channel_type: 'chat',
|
||||
});
|
||||
const { openDiscuss, messaging } = await start({
|
||||
discuss: {
|
||||
params: {
|
||||
default_active_id: `mail.channel_${mailChannelId1}`,
|
||||
},
|
||||
},
|
||||
});
|
||||
await openDiscuss();
|
||||
assert.containsOnce(
|
||||
document.body,
|
||||
'.o_ThreadView_outOfOffice',
|
||||
"should have an out of office alert on thread view"
|
||||
);
|
||||
const formattedDate = returningDate.toDate().toLocaleDateString(
|
||||
messaging.locale.language.replace(/_/g, '-'),
|
||||
{ day: 'numeric', month: 'short' }
|
||||
);
|
||||
assert.ok(
|
||||
document.querySelector('.o_ThreadView_outOfOffice').textContent.includes(formattedDate),
|
||||
"out of office message should mention the returning date"
|
||||
);
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
/** @odoo-module **/
|
||||
|
||||
import { click, clickSave, getFixture } from "@web/../tests/helpers/utils";
|
||||
import { makeView, setupViewRegistries } from "@web/../tests/views/helpers";
|
||||
|
||||
let serverData;
|
||||
let target;
|
||||
|
||||
QUnit.module("Fields", (hooks) => {
|
||||
hooks.beforeEach(() => {
|
||||
serverData = {
|
||||
models: {
|
||||
partner: {
|
||||
fields: {
|
||||
product_id: { string: "Product", type: "many2one", relation: "product" },
|
||||
},
|
||||
records: [{ id: 1, product_id: false }],
|
||||
},
|
||||
product: {
|
||||
fields: {
|
||||
name: { string: "Product Name", type: "char" },
|
||||
},
|
||||
records: [
|
||||
{ id: 1, display_name: "a" },
|
||||
{ id: 2, display_name: "b" },
|
||||
{ id: 3, display_name: "c" },
|
||||
],
|
||||
},
|
||||
},
|
||||
};
|
||||
target = getFixture();
|
||||
setupViewRegistries();
|
||||
});
|
||||
|
||||
QUnit.module("RadioImageField");
|
||||
|
||||
QUnit.test("field is correctly renderered", async function (assert) {
|
||||
await makeView({
|
||||
type: "form",
|
||||
resModel: "partner",
|
||||
resId: 1,
|
||||
serverData,
|
||||
arch: '<form><field name="product_id" widget="hr_holidays_radio_image"/></form>',
|
||||
});
|
||||
|
||||
assert.containsOnce(target, ".o_field_widget.o_field_hr_holidays_radio_image");
|
||||
assert.containsN(target, ".o_radio_input", 3);
|
||||
assert.containsNone(target, ".o_radio_input:checked");
|
||||
assert.containsN(target, "img", 3);
|
||||
|
||||
await click(target.querySelector("img"));
|
||||
assert.containsOnce(target, ".o_radio_input:checked");
|
||||
|
||||
await clickSave(target);
|
||||
assert.containsOnce(target, ".o_field_widget.o_field_hr_holidays_radio_image");
|
||||
assert.containsN(target, ".o_radio_input", 3);
|
||||
assert.containsN(target, "img", 3);
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,159 @@
|
|||
/** @odoo-module */
|
||||
|
||||
import { selectDropdownItem, editInput, getFixture } from '@web/../tests/helpers/utils';
|
||||
import { makeView, setupViewRegistries } from "@web/../tests/views/helpers";
|
||||
|
||||
|
||||
let serverData;
|
||||
let target;
|
||||
|
||||
QUnit.module('leave_stats_widget', (hooks) => {
|
||||
hooks.beforeEach(() => {
|
||||
setupViewRegistries();
|
||||
|
||||
target = getFixture();
|
||||
serverData = {
|
||||
models: {
|
||||
department: {
|
||||
fields: {
|
||||
name: { string: "Name", type: "char" },
|
||||
},
|
||||
records: [{id:11, name: "R&D"}],
|
||||
},
|
||||
employee: {
|
||||
fields: {
|
||||
name: { string: "Name", type: "char" },
|
||||
department_id: { string: "Department", type: "many2one", relation: 'department' },
|
||||
},
|
||||
records: [{
|
||||
id: 100,
|
||||
name: "Richard",
|
||||
department_id: 11,
|
||||
},{
|
||||
id: 200,
|
||||
name: "Jesus",
|
||||
department_id: 11,
|
||||
}],
|
||||
},
|
||||
'hr.leave.type': {
|
||||
fields: {
|
||||
name: { string: "Name", type: "char" }
|
||||
},
|
||||
records: [{
|
||||
id: 55,
|
||||
name: "Legal Leave",
|
||||
}]
|
||||
},
|
||||
'hr.leave': {
|
||||
fields: {
|
||||
employee_id: { string: "Employee", type: "many2one", relation: 'employee' },
|
||||
department_id: { string: "Department", type: "many2one", relation: 'department' },
|
||||
date_from: { string: "From", type: "datetime" },
|
||||
date_to: { string: "To", type: "datetime" },
|
||||
holiday_status_id: { string: "Leave type", type: "many2one", relation: 'hr.leave.type' },
|
||||
state: { string: "State", type: "char" },
|
||||
holiday_type: { string: "Holiday Type", type: "char" },
|
||||
number_of_days: { string: "State", type: "integer" },
|
||||
},
|
||||
records: [{
|
||||
id: 12,
|
||||
employee_id: 100,
|
||||
department_id: 11,
|
||||
date_from: "2016-10-20 09:00:00",
|
||||
date_to: "2016-10-25 18:00:00",
|
||||
holiday_status_id: 55,
|
||||
state: 'validate',
|
||||
number_of_days: 5,
|
||||
holiday_type: 'employee',
|
||||
},{
|
||||
id: 13,
|
||||
employee_id: 100,
|
||||
department_id: 11,
|
||||
date_from: "2016-10-02 09:00:00",
|
||||
date_to: "2016-10-02 18:00:00",
|
||||
holiday_status_id: 55,
|
||||
state: 'validate',
|
||||
number_of_days: 1,
|
||||
holiday_type: 'employee',
|
||||
},{
|
||||
id: 14,
|
||||
employee_id: 200,
|
||||
department_id: 11,
|
||||
date_from: "2016-10-15 09:00:00",
|
||||
date_to: "2016-10-20 18:00:00",
|
||||
holiday_status_id: 55,
|
||||
state: 'validate',
|
||||
number_of_days: 8,
|
||||
holiday_type: 'employee',
|
||||
}]
|
||||
}
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
QUnit.test('leave stats renders correctly', async (assert) => {
|
||||
assert.expect(5);
|
||||
await makeView({
|
||||
serverData,
|
||||
type: "form",
|
||||
resModel: 'hr.leave',
|
||||
arch: '<form string="Leave">' +
|
||||
'<field name="employee_id"/>' +
|
||||
'<field name="department_id"/>' +
|
||||
'<field name="date_from"/>' +
|
||||
'<widget name="hr_leave_stats"/>' +
|
||||
'</form>',
|
||||
resId: 12,
|
||||
mockRPC(route, args) {
|
||||
if (args.model === 'hr.leave' && args.method === 'search') {
|
||||
return Promise.resolve(this.data['hr.leave'].records.map(function (record) { return record.id; }));
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
const $leaveTypeBody = target.querySelector('.o_leave_stats #o_leave_stats_employee');
|
||||
const $leavesDepartmentBody = target.querySelector('.o_leave_stats #o_leave_stats_department');
|
||||
|
||||
assert.containsOnce($leaveTypeBody, 'span:contains(Legal Leave)', "it should have leave type");
|
||||
assert.containsOnce($leaveTypeBody, 'span:contains(6)', "it should have 6 days");
|
||||
|
||||
assert.containsN($leavesDepartmentBody, 'span:contains(Richard)', 2, "it should have 2 leaves for Richard");
|
||||
assert.containsOnce($leavesDepartmentBody, 'span:contains(Jesus)', "it should have 1 leaves for Jesus");
|
||||
assert.containsOnce($leavesDepartmentBody, 'div.o_horizontal_separator:contains(R&D)', "it should have R&D title");
|
||||
});
|
||||
QUnit.test('leave stats reload when employee/department changes', async (assert) => {
|
||||
assert.expect(3);
|
||||
await makeView({
|
||||
serverData,
|
||||
type: "form",
|
||||
resModel: 'hr.leave',
|
||||
mode: 'edit',
|
||||
arch: '<form string="Leave">' +
|
||||
'<field name="employee_id"/>' +
|
||||
'<field name="department_id"/>' +
|
||||
'<field name="date_from"/>' +
|
||||
'<widget name="hr_leave_stats"/>' +
|
||||
'</form>',
|
||||
mockRPC(route, args) {
|
||||
if (args.model === 'hr.leave' && args.method === 'search_read') {
|
||||
assert.ok(_.some(args.kwargs.domain, _.matcher(['department_id', '=', 11])), "It should load department's leaves data");
|
||||
}
|
||||
if (args.model === 'hr.leave' && args.method === 'read_group') {
|
||||
assert.ok(_.some(args.kwargs.domain, _.matcher(['employee_id', '=', 200])), "It should load employee's leaves data");
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
// Set date => shouldn't load data yet (no employee nor department defined)
|
||||
await editInput(
|
||||
target,
|
||||
"div[name='date_from'] .o_datepicker_input",
|
||||
"2016-10-12 09:00:00"
|
||||
);
|
||||
|
||||
// Set employee => should load employee's date
|
||||
await selectDropdownItem(target, "employee_id", "Jesus");
|
||||
// Set department => should load department's data
|
||||
await selectDropdownItem(target, "department_id", "R&D");
|
||||
});
|
||||
});
|
||||
Loading…
Add table
Add a link
Reference in a new issue