Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Waiting Queue feature not queueing rooms #33772

Merged
merged 10 commits into from
Nov 7, 2024
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/stale-actors-enjoy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@rocket.chat/meteor": patch
---

Fixes `waiting queue` feature. When `Livechat_waiting_queue` setting is enabled, incoming conversations should be sent to the queue instead of being assigned directly.
18 changes: 15 additions & 3 deletions apps/meteor/app/livechat/server/lib/QueueManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,7 @@ export class QueueManager {

const inquiryAgent = await RoutingManager.delegateAgent(defaultAgent, inquiry);
logger.debug(`Delegating inquiry with id ${inquiry._id} to agent ${defaultAgent?.username}`);
await callbacks.run('livechat.beforeRouteChat', inquiry, inquiryAgent);
const dbInquiry = await LivechatInquiry.findOneById(inquiry._id);
const dbInquiry = await callbacks.run('livechat.beforeRouteChat', inquiry, inquiryAgent);

if (!dbInquiry) {
throw new Error('inquiry-not-found');
Expand All @@ -122,6 +121,10 @@ export class QueueManager {
return LivechatInquiryStatus.QUEUED;
}

if (settings.get('Livechat_waiting_queue')) {
return LivechatInquiryStatus.QUEUED;
}

if (RoutingManager.getConfig()?.autoAssignAgent) {
return LivechatInquiryStatus.READY;
}
Expand All @@ -135,6 +138,7 @@ export class QueueManager {

static async queueInquiry(inquiry: ILivechatInquiryRecord, room: IOmnichannelRoom, defaultAgent?: SelectedAgent | null) {
if (inquiry.status === 'ready') {
logger.debug({ msg: 'Inquiry is ready. Delegating', inquiry, defaultAgent });
return RoutingManager.delegateInquiry(inquiry, defaultAgent, undefined, room);
}

Expand Down Expand Up @@ -252,7 +256,11 @@ export class QueueManager {
throw new Error('room-not-found');
}

if (!newRoom.servedBy && settings.get('Omnichannel_calculate_dispatch_service_queue_statistics')) {
if (
!newRoom.servedBy &&
settings.get('Livechat_waiting_queue') &&
settings.get('Omnichannel_calculate_dispatch_service_queue_statistics')
) {
const [inq] = await LivechatInquiry.getCurrentSortedQueueAsync({
inquiryId: inquiry._id,
department,
Expand Down Expand Up @@ -320,6 +328,10 @@ export class QueueManager {
}

private static dispatchInquiryQueued = async (inquiry: ILivechatInquiryRecord, room: IOmnichannelRoom, agent?: SelectedAgent | null) => {
if (RoutingManager.getConfig()?.autoAssignAgent) {
return;
}

logger.debug(`Notifying agents of new inquiry ${inquiry._id} queued`);

const { department, rid, v } = inquiry;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ callbacks.add(
}

await saveQueueInquiry(inquiry);

return LivechatInquiry.findOneById(inquiry._id);
},
callbacks.priority.HIGH,
'livechat-before-routing-chat',
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
import { createFakeVisitor } from '../../mocks/data';
import { IS_EE } from '../config/constants';
import { createAuxContext } from '../fixtures/createAuxContext';
import { Users } from '../fixtures/userStates';
import { HomeOmnichannel, OmnichannelLiveChat } from '../page-objects';
import { test, expect } from '../utils/test';

const firstVisitor = createFakeVisitor();

const secondVisitor = createFakeVisitor();

test.use({ storageState: Users.user1.state });

test.describe('OC - Livechat - Queue Management', () => {
test.skip(!IS_EE, 'Enterprise Only');

let poHomeOmnichannel: HomeOmnichannel;
let poLiveChat: OmnichannelLiveChat;

const waitingQueueMessage = 'This is a message from Waiting Queue';
const queuePosition1 = 'Your spot is #1';
const queuePosition2 = 'Your spot is #2';

test.beforeAll(async ({ api, browser }) => {
await Promise.all([
api.post('/settings/Livechat_Routing_Method', { value: 'Auto_Selection' }),
api.post('/settings/Livechat_accept_chats_with_no_agents', { value: true }),
api.post('/settings/Livechat_waiting_queue', { value: true }),
api.post('/settings/Livechat_waiting_queue_message', { value: waitingQueueMessage }),
api.post('/livechat/users/agent', { username: 'user1' }),
]);

const { page: omniPage } = await createAuxContext(browser, Users.user1, '/', true);
poHomeOmnichannel = new HomeOmnichannel(omniPage);

// Agent will be offline for these tests
await poHomeOmnichannel.sidenav.switchOmnichannelStatus('offline');
});

test.beforeEach(async ({ browser, api }) => {
const context = await browser.newContext();
const page2 = await context.newPage();

poLiveChat = new OmnichannelLiveChat(page2, api);
await poLiveChat.page.goto('/livechat');
});

test.afterAll(async ({ api }) => {
await Promise.all([
api.post('/settings/Livechat_waiting_queue', { value: false }),
api.post('/settings/Livechat_waiting_queue_message', { value: '' }),
MarcosSpessatto marked this conversation as resolved.
Show resolved Hide resolved
api.delete('/livechat/users/agent/user1'),
]);
await poHomeOmnichannel.page.close();
});

test.describe('OC - Queue Management - Auto Selection', () => {
let poLiveChat2: OmnichannelLiveChat;

test.beforeEach(async ({ browser, api }) => {
const context = await browser.newContext();
const page = await context.newPage();
poLiveChat2 = new OmnichannelLiveChat(page, api);
await poLiveChat2.page.goto('/livechat');
});

test.afterEach(async () => {
await poLiveChat2.closeChat();
await poLiveChat2.page.close();
await poLiveChat.closeChat();
await poLiveChat.page.close();
});

test('Update user position on Queue', async () => {
await test.step('should start livechat session', async () => {
await poLiveChat.openAnyLiveChatAndSendMessage({
liveChatUser: firstVisitor,
message: 'Test message',
isOffline: false,
});
});

await test.step('expect to receive Waiting Queue message on chat', async () => {
await expect(poLiveChat.page.locator(`div >> text=${waitingQueueMessage}`)).toBeVisible();
});

await test.step('expect to be on spot #1', async () => {
await expect(poLiveChat.page.locator(`div[role='alert'] >> text=${queuePosition1}`)).toBeVisible();
KevLehman marked this conversation as resolved.
Show resolved Hide resolved
});

await test.step('should start secondary livechat session', async () => {
await poLiveChat2.openAnyLiveChatAndSendMessage({
liveChatUser: secondVisitor,
message: 'Test message',
isOffline: false,
});
});

await test.step('should start secondary livechat on spot #2', async () => {
await expect(poLiveChat2.page.locator(`div[role='alert'] >> text=${queuePosition2}`)).toBeVisible();
});

await test.step('should start the queue by making the agent available again', async () => {
await poHomeOmnichannel.sidenav.switchOmnichannelStatus('online');
});

await test.step('user1 should get assigned to the first chat', async () => {
await expect(poLiveChat.page.locator(`div[role='alert'] >> text=${queuePosition1}`)).not.toBeVisible();
});

await test.step('secondary session should be on position #1', async () => {
await expect(poLiveChat2.page.locator(`div[role='alert'] >> text=${queuePosition1}`)).toBeVisible();
});

await test.step('secondary session should be taken by user1', async () => {
await expect(poLiveChat2.page.locator(`div[role='alert'] >> text=${queuePosition1}`)).not.toBeVisible();
});
});
});
});
Loading