test: Omnichannel Users & Departments (#30820)

pull/30281/head^2
Kevin Aleman 2 years ago committed by GitHub
parent 542a6fef8a
commit ea8f99c082
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 4
      apps/meteor/tests/data/livechat/units.ts
  2. 21
      apps/meteor/tests/end-to-end/api/livechat/01-agents.ts
  3. 232
      apps/meteor/tests/end-to-end/api/livechat/10-departments.ts
  4. 167
      apps/meteor/tests/end-to-end/api/livechat/14-units.ts
  5. 167
      apps/meteor/tests/end-to-end/api/livechat/22-monitors.ts

@ -25,7 +25,7 @@ export const createMonitor = async (username: string): Promise<{ _id: string; us
});
};
export const createUnit = async (monitorId: string, username: string, departmentIds: string[]): Promise<IOmnichannelBusinessUnit> => {
export const createUnit = async (monitorId: string, username: string, departmentIds: string[], name?: string): Promise<IOmnichannelBusinessUnit> => {
return new Promise((resolve, reject) => {
request
.post(methodCall(`livechat:saveUnit`))
@ -33,7 +33,7 @@ export const createUnit = async (monitorId: string, username: string, department
.send({
message: JSON.stringify({
method: 'livechat:saveUnit',
params: [null, { name: faker.person.firstName(), visibility: faker.helpers.arrayElement(['public', 'private']) }, [{ monitorId, username }], departmentIds.map((departmentId) => ({ departmentId }))],
params: [null, { name: name || faker.person.firstName(), visibility: faker.helpers.arrayElement(['public', 'private']) }, [{ monitorId, username }], departmentIds.map((departmentId) => ({ departmentId }))],
id: '101',
msg: 'method',
}),

@ -258,6 +258,27 @@ describe('LIVECHAT - Agents', function () {
// cleanup
await deleteUser(user);
});
it('should properly create a manager', async () => {
const user: IUser = await createUser();
await request
.post(api('livechat/users/manager'))
.set(credentials)
.send({
username: user.username,
})
.expect('Content-Type', 'application/json')
.expect(200)
.expect((res: Response) => {
expect(res.body).to.have.property('success', true);
expect(res.body).to.have.property('user');
expect(res.body.user).to.have.property('_id');
expect(res.body.user).to.have.property('username');
});
// cleanup
await deleteUser(user);
});
});
describe('GET livechat/users/:type/:_id', () => {

@ -1,6 +1,7 @@
import { faker } from '@faker-js/faker';
import type { ILivechatDepartment } from '@rocket.chat/core-typings';
import { expect } from 'chai';
import { before, describe, it } from 'mocha';
import { before, describe, it, after } from 'mocha';
import type { Response } from 'supertest';
import { getCredentials, api, request, credentials } from '../../../data/api-data';
@ -14,10 +15,71 @@ import {
getLivechatRoomInfo,
} from '../../../data/livechat/rooms';
import { createMonitor, createUnit } from '../../../data/livechat/units';
import { updatePermission, updateSetting } from '../../../data/permissions.helper';
import { restorePermissionToRoles, updatePermission, updateSetting } from '../../../data/permissions.helper';
import { createUser, deleteUser } from '../../../data/users.helper';
import { IS_EE } from '../../../e2e/config/constants';
(IS_EE ? describe.skip : describe)('LIVECHAT - Departments[CE]', () => {
before((done) => getCredentials(done));
before(async () => {
await updateSetting('Livechat_enabled', true);
await restorePermissionToRoles('view-livechat-manager');
await createAgent();
await makeAgentAvailable();
await updateSetting('Omnichannel_enable_department_removal', true);
});
// Remove departments that may have been created before
before(async () => {
const { body } = await request.get(api('livechat/department')).set(credentials).expect('Content-Type', 'application/json').expect(200);
for await (const department of body.departments) {
await deleteDepartment(department._id);
}
});
let departmentId: string;
after(async () => {
await deleteDepartment(departmentId);
});
it('should create a new department', async () => {
const { body } = await request
.post(api('livechat/department'))
.set(credentials)
.send({ department: { name: 'Test', enabled: true, showOnOfflineForm: true, showOnRegistration: true, email: 'bla@bla' } })
.expect('Content-Type', 'application/json')
.expect(200);
expect(body).to.have.property('success', true);
expect(body).to.have.property('department');
expect(body.department).to.have.property('_id');
expect(body.department).to.have.property('name', 'Test');
expect(body.department).to.have.property('enabled', true);
expect(body.department).to.have.property('showOnOfflineForm', true);
expect(body.department).to.have.property('showOnRegistration', true);
departmentId = body.department._id;
});
it('should not create a 2nd department', () => {
return request
.post(api('livechat/department'))
.set(credentials)
.send({ department: { name: 'Test', enabled: true, showOnOfflineForm: true, showOnRegistration: true, email: 'bla@bla' } })
.expect('Content-Type', 'application/json')
.expect(400);
});
it('should return a list of 1 department', async () => {
const { body } = await request.get(api('livechat/department')).set(credentials).expect('Content-Type', 'application/json').expect(200);
expect(body).to.have.property('success', true);
expect(body).to.have.property('departments');
expect(body.departments).to.be.an('array');
expect(body.departments).to.have.lengthOf(1);
});
});
(IS_EE ? describe : describe.skip)('LIVECHAT - Departments', () => {
before((done) => getCredentials(done));
@ -51,6 +113,72 @@ import { IS_EE } from '../../../e2e/config/constants';
expect(res.body.departments).to.have.length.of.at.least(0);
});
});
it('should reject invalid pagination params', async () => {
await request
.get(api('livechat/department'))
.set(credentials)
.query({ count: 'invalid' })
.expect('Content-Type', 'application/json')
.expect(400);
});
it('should return a list of paginated departments', async () => {
await request
.get(api('livechat/department'))
.set(credentials)
.query({ count: 1, offset: 0 })
.expect('Content-Type', 'application/json')
.expect(200)
.expect((res: Response) => {
expect(res.body).to.have.property('success', true);
expect(res.body).to.have.property('departments');
expect(res.body.departments).to.be.an('array');
expect(res.body.departments).to.have.lengthOf(1);
});
});
it('should sort list alphabetically following mongodb default sort (no collation)', async () => {
const department1 = await createDepartment(undefined, 'A test');
const department2 = await createDepartment(undefined, 'a test');
await request
.get(api('livechat/department'))
.set(credentials)
.query({ count: 2, offset: 0, text: 'test' })
.expect('Content-Type', 'application/json')
.expect(200)
.expect((res: Response) => {
expect(res.body).to.have.property('success', true);
expect(res.body).to.have.property('departments');
expect(res.body.departments).to.be.an('array');
expect(res.body.departments).to.have.lengthOf(2);
expect(res.body.departments[0]).to.have.property('_id', department1._id);
expect(res.body.departments[1]).to.have.property('_id', department2._id);
});
await deleteDepartment(department1._id);
await deleteDepartment(department2._id);
});
it('should return a list of departments matching name', async () => {
const department1 = await createDepartment(undefined, 'A test 123');
const department2 = await createDepartment(undefined, 'a test 456');
await request
.get(api('livechat/department'))
.set(credentials)
.query({ count: 2, offset: 0, text: 'A test 123' })
.expect('Content-Type', 'application/json')
.expect(200)
.expect((res: Response) => {
expect(res.body).to.have.property('success', true);
expect(res.body).to.have.property('departments');
expect(res.body.departments).to.be.an('array');
expect(res.body.departments).to.have.lengthOf(1);
expect(res.body.departments[0]).to.have.property('_id', department1._id);
expect(res.body.departments.find((dept: ILivechatDepartment) => dept._id === department2._id)).to.be.undefined;
});
await deleteDepartment(department1._id);
await deleteDepartment(department2._id);
});
});
describe('POST livechat/departments', () => {
@ -76,8 +204,62 @@ import { IS_EE } from '../../../e2e/config/constants';
.expect(400);
});
it('should return an error if requestTagsBeforeClosing is true but no tags are provided', async () => {
await request
.post(api('livechat/department'))
.set(credentials)
.send({
department: {
name: 'Test',
enabled: true,
showOnOfflineForm: true,
showOnRegistration: true,
email: 'bla@bla',
requestTagBeforeClosingChat: true,
},
})
.expect('Content-Type', 'application/json')
.expect(400);
});
it('should return an error if requestTagsBeforeClosing is true but tags are not an array', async () => {
await request
.post(api('livechat/department'))
.set(credentials)
.send({
department: {
name: 'Test',
enabled: true,
showOnOfflineForm: true,
showOnRegistration: true,
email: 'bla@bla',
requestTagBeforeClosingChat: true,
chatClosingTags: 'not an array',
},
})
.expect('Content-Type', 'application/json')
.expect(400);
});
it('should return an error if fallbackForwardDepartment is present but is not a department id', async () => {
await request
.post(api('livechat/department'))
.set(credentials)
.send({
department: {
name: 'Test',
enabled: true,
showOnOfflineForm: true,
showOnRegistration: true,
email: 'bla@bla',
fallbackForwardDepartment: 'not a department id',
},
})
.expect('Content-Type', 'application/json')
.expect(400);
});
it('should create a new department', async () => {
await updatePermission('manage-livechat-departments', ['admin']);
const { body } = await request
.post(api('livechat/department'))
.set(credentials)
@ -93,6 +275,28 @@ import { IS_EE } from '../../../e2e/config/constants';
expect(body.department).to.have.property('showOnRegistration', true);
await deleteDepartment(body.department._id);
});
it('should create a new disabled department', async () => {
const { body } = await request
.post(api('livechat/department'))
.set(credentials)
.send({
department: {
name: faker.hacker.adjective(),
enabled: false,
showOnOfflineForm: true,
showOnRegistration: true,
email: faker.internet.email(),
},
})
.expect('Content-Type', 'application/json')
.expect(200);
expect(body).to.have.property('success', true);
expect(body).to.have.property('department');
expect(body.department).to.have.property('_id');
expect(body.department).to.have.property('enabled', false);
await deleteDepartment(body.department._id);
});
});
describe('GET livechat/department/:_id', () => {
@ -139,6 +343,28 @@ import { IS_EE } from '../../../e2e/config/constants';
});
});
describe('PUT livechat/departments/:_id', () => {
it('should return an error if fallbackForwardDepartment points to same department', async () => {
const department = await createDepartment();
await request
.put(api(`livechat/department/${department._id}`))
.set(credentials)
.send({
department: {
name: faker.hacker.adjective(),
enabled: true,
showOnOfflineForm: true,
showOnRegistration: true,
email: faker.internet.email(),
fallbackForwardDepartment: department._id,
},
})
.expect('Content-Type', 'application/json')
.expect(400);
await deleteDepartment(department._id);
});
});
describe('DELETE livechat/department/:_id', () => {
it('should return unauthorized error when the user does not have the necessary permission', async () => {
await updatePermission('manage-livechat-departments', []);

@ -53,6 +53,57 @@ import { IS_EE } from '../../../e2e/config/constants';
// cleanup
await deleteUser(user);
});
it('should return a list of units matching the provided filter', async () => {
const user = await createUser();
await createMonitor(user.username);
const department = await createDepartment();
const unit = await createUnit(user._id, user.username, [department._id]);
const { body } = await request.get(api('livechat/units')).query({ text: unit.name }).set(credentials).expect(200);
expect(body.units).to.be.an('array').with.lengthOf(1);
const unitFound = body.units.find((u: IOmnichannelBusinessUnit) => u._id === unit._id);
expect(unitFound).to.have.property('_id', unit._id);
expect(unitFound).to.have.property('name', unit.name);
expect(unitFound).to.have.property('numMonitors', 1);
expect(unitFound).to.have.property('numDepartments', 1);
expect(unitFound).to.have.property('type', 'u');
// cleanup
await deleteUser(user);
});
it('should properly paginate the result set', async () => {
const { body } = await request.get(api('livechat/units')).query({ count: 1 }).set(credentials).expect(200);
expect(body).to.have.property('units').and.to.be.an('array').with.lengthOf(1);
expect(body).to.have.property('count').and.to.be.equal(1);
const unit = body.units[0];
const { body: body2 } = await request.get(api('livechat/units')).query({ count: 1, offset: 1 }).set(credentials).expect(200);
expect(body2).to.have.property('units').and.to.be.an('array').with.lengthOf(1);
const unit2 = body2.units[0];
expect(unit._id).to.not.be.equal(unit2._id);
});
it('should sort the result set based on provided fields', async () => {
const user = await createUser();
await createMonitor(user.username);
const department = await createDepartment();
const unit = await createUnit(user._id, user.username, [department._id], 'A test 1234');
const unit2 = await createUnit(user._id, user.username, [department._id], 'a test 1234');
const { body } = await request
.get(api('livechat/units'))
.query({ sort: JSON.stringify({ name: 1 }), text: 'test', count: 2 })
.set(credentials)
.expect(200);
expect(body).to.have.property('units').and.to.be.an('array').with.lengthOf(2);
expect(body.units[0]._id).to.be.equal(unit._id);
expect(body.units[1]._id).to.be.equal(unit2._id);
await deleteUser(user);
});
});
describe('[POST] livechat/units', () => {
@ -131,11 +182,30 @@ import { IS_EE } from '../../../e2e/config/constants';
await updatePermission('manage-livechat-units', []);
return request.post(api('livechat/units/123')).set(credentials).expect(403);
});
it('should return a updated unit', async () => {
it('should fail if unit does not exist', async () => {
await updatePermission('manage-livechat-units', ['admin']);
const user = await createUser();
await createMonitor(user.username);
const department = await createDepartment();
const { body } = await request
.post(api('livechat/units/123'))
.set(credentials)
.send({
unitData: { name: 'test', visibility: 'public', enabled: true, description: 'test' },
unitMonitors: [{ monitorId: user._id, username: user.username }],
unitDepartments: [{ departmentId: department._id }],
})
.expect(400);
expect(body).to.have.property('success', false);
// cleanup
await deleteUser(user);
});
it('should return a updated unit', async () => {
const user = await createUser();
await createMonitor(user.username);
const department = await createDepartment();
const unit = await createUnit(user._id, user.username, [department._id]);
const { body } = await request
@ -158,6 +228,60 @@ import { IS_EE } from '../../../e2e/config/constants';
// cleanup
await deleteUser(user);
});
it('should move the department to the latest unit that attempted to assign it', async () => {
const user = await createUser();
await createMonitor(user.username);
const department = await createDepartment();
const unit1 = await createUnit(user._id, user.username, [department._id]);
const unit2 = await createUnit(user._id, user.username, [department._id]);
const { body } = await request
.get(api(`livechat/units/${unit1._id}/departments`))
.set(credentials)
.expect(200);
expect(body).to.have.property('departments');
expect(body.departments).to.have.lengthOf(0);
expect(unit2.numDepartments).to.be.equal(1);
});
it('should remove the department from the unit if it is not passed in the request', async () => {
const user = await createUser();
await createMonitor(user.username);
const department = await createDepartment();
const unit1 = await createUnit(user._id, user.username, [department._id]);
const { body } = await request
.post(api(`livechat/units/${unit1._id}`))
.set(credentials)
.send({
unitData: { name: unit1.name, visibility: unit1.visibility },
unitMonitors: [{ monitorId: user._id, username: user.username }],
unitDepartments: [],
})
.expect(200);
expect(body).to.have.property('_id', unit1._id);
expect(body).to.have.property('numDepartments', 0);
});
it('should remove the monitor from the unit if it is not passed in the request', async () => {
const user = await createUser();
await createMonitor(user.username);
const department = await createDepartment();
const unit1 = await createUnit(user._id, user.username, [department._id]);
const { body } = await request
.post(api(`livechat/units/${unit1._id}`))
.set(credentials)
.send({
unitData: { name: unit1.name, visibility: unit1.visibility },
unitMonitors: [],
unitDepartments: [{ departmentId: department._id }],
})
.expect(200);
expect(body).to.have.property('_id', unit1._id);
expect(body).to.have.property('numMonitors', 0);
});
});
describe('[DELETE] livechat/units/:id', () => {
@ -265,45 +389,4 @@ import { IS_EE } from '../../../e2e/config/constants';
await deleteUser(user);
});
});
describe('livechat/monitors', () => {
it('should fail if manage-livechat-monitors permission is missing', async () => {
await updatePermission('manage-livechat-monitors', []);
return request.get(api('livechat/monitors')).set(credentials).expect(403);
});
it('should return all monitors', async () => {
await updatePermission('manage-livechat-monitors', ['admin']);
const user = await createUser();
await createMonitor(user.username);
const { body } = await request.get(api('livechat/monitors')).set(credentials).query({ text: user.username }).expect(200);
expect(body).to.have.property('monitors');
expect(body.monitors).to.have.lengthOf(1);
expect(body.monitors[0]).to.have.property('username', user.username);
// cleanup
await deleteUser(user);
});
});
describe('livechat/monitors/:username', () => {
it('should fail if manage-livechat-monitors permission is missing', async () => {
await updatePermission('manage-livechat-monitors', []);
return request.get(api('livechat/monitors/123')).set(credentials).expect(403);
});
it('should return a monitor', async () => {
await updatePermission('manage-livechat-monitors', ['admin']);
const user = await createUser();
await createMonitor(user.username);
const { body } = await request
.get(api(`livechat/monitors/${user.username}`))
.set(credentials)
.expect(200);
expect(body).to.have.property('username', user.username);
// cleanup
await deleteUser(user);
});
});
});

@ -1,9 +1,9 @@
/* eslint-disable @typescript-eslint/no-non-null-assertion */
import type { ILivechatDepartment, IUser } from '@rocket.chat/core-typings';
import { expect } from 'chai';
import { before, it, describe } from 'mocha';
import { before, it, describe, after } from 'mocha';
import { getCredentials, api, request } from '../../../data/api-data';
import { getCredentials, api, request, methodCall, credentials } from '../../../data/api-data';
import { addOrRemoveAgentFromDepartment, createDepartment } from '../../../data/livechat/department';
import {
createAgent,
@ -14,9 +14,9 @@ import {
makeAgentAvailable,
} from '../../../data/livechat/rooms';
import { createMonitor, createUnit } from '../../../data/livechat/units';
import { updateSetting, updatePermission } from '../../../data/permissions.helper';
import { updateSetting, updatePermission, restorePermissionToRoles, removePermissionFromAllRoles } from '../../../data/permissions.helper';
import { password } from '../../../data/user';
import { createUser, login, setUserActiveStatus } from '../../../data/users.helper';
import { createUser, deleteUser, login, setUserActiveStatus } from '../../../data/users.helper';
import { IS_EE } from '../../../e2e/config/constants';
type TestUser = { user: IUser; credentials: { 'X-Auth-Token': string; 'X-User-Id': string } };
@ -70,6 +70,165 @@ type TestUser = { user: IUser; credentials: { 'X-Auth-Token': string; 'X-User-Id
await updatePermission('transfer-livechat-guest', ['admin', 'livechat-manager', 'livechat-agent', 'livechat-monitor']);
});
describe('Monitors', () => {
let user: IUser;
before(async () => {
user = await createUser();
});
after(async () => {
await deleteUser(user);
});
it('should properly create a new monitor', async () => {
const { body } = await request
.post(methodCall(`livechat:addMonitor`))
.set(credentials)
.send({
message: JSON.stringify({
method: 'livechat:addMonitor',
params: [user.username],
id: '101',
msg: 'method',
}),
})
.expect(200);
expect(body.success).to.be.true;
});
it('should not fail when trying to create a monitor that already exists', async () => {
const { body } = await request
.post(methodCall(`livechat:addMonitor`))
.set(credentials)
.send({
message: JSON.stringify({
method: 'livechat:addMonitor',
params: [user.username],
id: '101',
msg: 'method',
}),
})
.expect(200);
expect(body.success).to.be.true;
});
it('should fail when trying to create a monitor with an invalid username', async () => {
const { body } = await request
.post(methodCall(`livechat:addMonitor`))
.set(credentials)
.send({
message: JSON.stringify({
method: 'livechat:addMonitor',
params: ['invalid-username'],
id: '101',
msg: 'method',
}),
})
.expect(200);
expect(body.success).to.be.true;
const parsedBody = JSON.parse(body.message);
expect(parsedBody.error).to.have.property('error').to.be.equal('error-invalid-user');
});
it('should fail when trying to create a monitor with an empty username', async () => {
const { body } = await request
.post(methodCall(`livechat:addMonitor`))
.set(credentials)
.send({
message: JSON.stringify({
method: 'livechat:addMonitor',
params: [''],
id: '101',
msg: 'method',
}),
})
.expect(200);
expect(body.success).to.be.true;
const parsedBody = JSON.parse(body.message);
expect(parsedBody.error).to.have.property('error').to.be.equal('error-invalid-user');
});
it('should remove a monitor', async () => {
const { body } = await request
.post(methodCall(`livechat:removeMonitor`))
.set(credentials)
.send({
message: JSON.stringify({
method: 'livechat:removeMonitor',
params: [user.username],
id: '101',
msg: 'method',
}),
})
.expect(200);
expect(body.success).to.be.true;
});
it('should not fail when trying to remove a monitor that does not exist', async () => {
const { body } = await request
.post(methodCall(`livechat:removeMonitor`))
.set(credentials)
.send({
message: JSON.stringify({
method: 'livechat:removeMonitor',
params: [user.username],
id: '101',
msg: 'method',
}),
})
.expect(200);
expect(body.success).to.be.true;
});
});
describe('[GET] livechat/monitors', () => {
it('should fail if manage-livechat-monitors permission is missing', async () => {
await removePermissionFromAllRoles('manage-livechat-monitors');
return request.get(api('livechat/monitors')).set(credentials).expect(403);
});
it('should return all monitors', async () => {
await restorePermissionToRoles('manage-livechat-monitors');
const user = await createUser();
await createMonitor(user.username);
const { body } = await request.get(api('livechat/monitors')).set(credentials).query({ text: user.username }).expect(200);
expect(body).to.have.property('monitors');
expect(body.monitors).to.have.lengthOf(1);
expect(body.monitors[0]).to.have.property('username', user.username);
// cleanup
await deleteUser(user);
});
});
describe('livechat/monitors/:username', () => {
it('should fail if manage-livechat-monitors permission is missing', async () => {
await removePermissionFromAllRoles('manage-livechat-monitors');
return request.get(api('livechat/monitors/123')).set(credentials).expect(403);
});
it('should return a monitor', async () => {
await restorePermissionToRoles('manage-livechat-monitors');
const user = await createUser();
await createMonitor(user.username);
const { body } = await request
.get(api(`livechat/monitors/${user.username}`))
.set(credentials)
.expect(200);
expect(body).to.have.property('username', user.username);
// cleanup
await deleteUser(user);
});
});
describe('Monitors & Rooms', () => {
it('should not return a room of a department that the monitor is not assigned to', async () => {
const visitor = await createVisitor(noUnitDepartment._id);

Loading…
Cancel
Save