Skip to content

Commit

Permalink
Merge branch 'develop' into fix/threadEdit
Browse files Browse the repository at this point in the history
  • Loading branch information
kodiakhq[bot] authored Jul 22, 2024
2 parents 7e6a63e + d9fdf02 commit f6de7b9
Show file tree
Hide file tree
Showing 8 changed files with 171 additions and 14 deletions.
6 changes: 6 additions & 0 deletions .changeset/dry-pumas-draw.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@rocket.chat/meteor": patch
"@rocket.chat/livechat": patch
---

Fixed an issue that caused the widget to set the wrong department when using the setDepartment Livechat api endpoint in conjunction with a Livechat Trigger
5 changes: 5 additions & 0 deletions .changeset/sixty-nails-clean.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@rocket.chat/meteor': patch
---

Fixed an issue that prevented the option to start a discussion from being shown on the message actions
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ Meteor.startup(() => {
subscription,
user,
}) {
if (drid || !Number.isNaN(dcount)) {
if (drid || !Number.isNaN(Number(dcount))) {
return false;
}
if (!subscription) {
Expand Down
14 changes: 14 additions & 0 deletions apps/meteor/tests/e2e/message-actions.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,20 @@ test.describe.serial('message-actions', () => {
await expect(poHomeChannel.content.lastMessageTextAttachmentEqualsText).toHaveText(message);
});

test('expect create a discussion from message', async ({ page }) => {
const message = `Message for discussion - ${Date.now()}`;

await poHomeChannel.content.sendMessage(message);
await poHomeChannel.content.openLastMessageMenu();
await page.locator('role=menuitem[name="Start a Discussion"]').click();
await page.locator('input[name="topic"]').fill('1');
await page.getByRole('dialog').getByRole('button', { name: 'create' }).click();
// There is some condition checking if the form has been edited.
// the "Create" button should not be disabled if starting a discussion from a message
// TODO: Fix form and remove line below
await expect(page.locator('header h1')).toHaveText(message);
});

test('expect star the message', async ({ page }) => {
await poHomeChannel.content.sendMessage('Message to star');
await poHomeChannel.content.openLastMessageMenu();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,11 @@ test.describe('OC - Livechat New Chat Triggers - After Registration', () => {
triggersName = faker.string.uuid();
triggerMessage = 'This is a trigger message after guest registration';

const requests = await Promise.all([
await Promise.all([
api.post('/livechat/users/agent', { username: 'user1' }),
api.post('/livechat/users/manager', { username: 'user1' }),
]);

requests.every((e) => expect(e.status()).toBe(200));

const { page } = await createAuxContext(browser, Users.user1, '/omnichannel/triggers');
agent = { page, poHomeOmnichannel: new HomeOmnichannel(page) };
await page.emulateMedia({ reducedMotion: 'reduce' });
Expand All @@ -45,17 +43,18 @@ test.describe('OC - Livechat New Chat Triggers - After Registration', () => {

await Promise.all(ids.map((id) => api.delete(`/livechat/triggers/${id}`)));

await Promise.all([
api.delete('/livechat/users/agent/user1'),
api.delete('/livechat/users/manager/user1'),
api.post('/settings/Livechat_clear_local_storage_when_chat_ended', { value: false }),
]);
await Promise.all([api.delete('/livechat/users/agent/user1'), api.delete('/livechat/users/manager/user1')]);

await agent.page.close();
await poLiveChat.page.close();
});

test.afterAll(async ({ api }) => {
await api.post('/settings/Livechat_clear_local_storage_when_chat_ended', { value: false });
});

test.describe('OC - Livechat New Chat Triggers - After Registration', async () => {
await test('expect trigger message after registration', async () => {
test('expect trigger message after registration', async () => {
await poLiveChat.page.goto('/livechat');
await poLiveChat.sendMessageAndCloseChat(newVisitor);

Expand Down Expand Up @@ -102,7 +101,7 @@ test.describe('OC - Livechat New Chat Triggers - After Registration', () => {
await api.post('/settings/Livechat_clear_local_storage_when_chat_ended', { value: true });
});

await test('expect trigger message after registration', async () => {
test('expect trigger message after registration', async () => {
await poLiveChat.page.goto('/livechat');
await poLiveChat.sendMessageAndCloseChat(newVisitor);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
import { IS_EE } from '../config/constants';
import { createAuxContext } from '../fixtures/createAuxContext';
import { Users } from '../fixtures/userStates';
import { HomeOmnichannel, OmnichannelLiveChatEmbedded } from '../page-objects';
import { createAgent } from '../utils/omnichannel/agents';
import { addAgentToDepartment, createDepartment } from '../utils/omnichannel/departments';
import { test, expect } from '../utils/test';

declare const window: Window & {
RocketChat: { livechat: { setDepartment: (dep: string) => void; maximizeWidget: () => void } };
};

test.use({ storageState: Users.admin.state });
test.describe('OC - Livechat Triggers - SetDepartment', () => {
test.skip(!IS_EE, 'Enterprise Only');
let poLiveChat: OmnichannelLiveChatEmbedded;
let departments: Awaited<ReturnType<typeof createDepartment>>[];
let departmentA: Awaited<ReturnType<typeof createDepartment>>['data'];
let departmentB: Awaited<ReturnType<typeof createDepartment>>['data'];
let agents: Awaited<ReturnType<typeof createDepartment>>[];
let agent1: Awaited<ReturnType<typeof createAgent>>['data'];
let agent2: Awaited<ReturnType<typeof createAgent>>['data'];
let poHomeOmnichannelAgent1: HomeOmnichannel;
let poHomeOmnichannelAgent2: HomeOmnichannel;

test.beforeAll(async ({ api }) => {
// Assign agents & departments
agents = await Promise.all([createAgent(api, 'user1'), createAgent(api, 'user2')]);
[agent1, agent2] = agents.map(({ data }) => data);
departments = await Promise.all([
createDepartment(api, { showOnRegistration: true }),
createDepartment(api, { showOnRegistration: true }),
]);

[departmentA, departmentB] = departments.map(({ data }) => data);

await Promise.all([
addAgentToDepartment(api, { department: departmentA, agentId: agent1._id }),
addAgentToDepartment(api, { department: departmentB, agentId: agent2._id }),
api.post(
'/livechat/triggers',

{
name: 'open',
description: '',
enabled: true,
runOnce: false,
conditions: [
{
name: 'chat-opened-by-visitor',
value: '',
},
],
actions: [
{
name: 'send-message',
params: {
name: '',
msg: 'This is a trigger message open by visitor',
sender: 'queue',
},
},
],
},
),
]);
});

test.beforeEach(async ({ browser, page }) => {
const { page: agent1Page } = await createAuxContext(browser, Users.user1, '/', true);
poHomeOmnichannelAgent1 = new HomeOmnichannel(agent1Page);
const { page: agent2Page } = await createAuxContext(browser, Users.user2, '/', true);
poHomeOmnichannelAgent2 = new HomeOmnichannel(agent2Page);

poLiveChat = new OmnichannelLiveChatEmbedded(page);
});

test.afterEach(async ({ page }) => {
await poHomeOmnichannelAgent1.page.close();
await poHomeOmnichannelAgent2.page.close();
await poLiveChat.page.close();
await page.close();
});

test.afterAll(async ({ api }) => {
const ids = (await (await api.get('/livechat/triggers')).json()).triggers.map(
(trigger: { _id: string }) => trigger._id,
) as unknown as string[];

await Promise.all(ids.map((id) => api.delete(`/livechat/triggers/${id}`)));
expect((await api.post('/settings/Omnichannel_enable_department_removal', { value: true })).status()).toBe(200);
await Promise.all([...agents.map((agent) => agent.delete())]);
await Promise.all([...departments.map((department) => department.delete())]);
expect((await api.post('/settings/Omnichannel_enable_department_removal', { value: false })).status()).toBe(200);
await api.post('/settings/Livechat_registration_form', { value: true });
});

test('OC - Livechat Triggers - setDepartment should affect agent.next call', async () => {
await poLiveChat.page.goto('/packages/rocketchat_livechat/assets/demo.html');

const depId = departmentB._id;

await poLiveChat.page.evaluate((depId) => window.RocketChat.livechat.setDepartment(depId), depId);

await poLiveChat.openLiveChat();

await expect(poLiveChat.txtChatMessage('This is a trigger message open by visitor')).toBeVisible();

await expect(poLiveChat.headerTitle).toContainText(agent2.username);
});

test('OC - Livechat Triggers - setDepartment should affect agent.next call - Register Form Disabled', async ({ api }) => {
await api.post('/settings/Livechat_registration_form', { value: false });

await poLiveChat.page.goto('/packages/rocketchat_livechat/assets/demo.html');

const depId = departmentB._id;

await poLiveChat.page.evaluate((depId) => window.RocketChat.livechat.setDepartment(depId), depId);

await poLiveChat.openLiveChat();

await expect(poLiveChat.txtChatMessage('This is a trigger message open by visitor')).toBeVisible();

await expect(poLiveChat.headerTitle).toContainText(agent2.username);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ export class OmnichannelLiveChatEmbedded {
return this.page.frameLocator('#rocketchat-iframe').locator('div >> text="Chat Finished"');
}

get headerTitle(): Locator {
return this.page.frameLocator('#rocketchat-iframe').locator('[data-qa="header-title"]');
}

get btnChatNow(): Locator {
return this.page.frameLocator('#rocketchat-iframe').locator('[type="button"] >> text="Chat now"');
}
Expand Down
8 changes: 5 additions & 3 deletions packages/livechat/src/lib/triggerUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,18 @@ const isAgentWithInfo = (agent: any): agent is Serialized<ILivechatAgent> => !ag
const getNextAgentFromQueue = async () => {
const {
defaultAgent,
iframe: { guest: { department } = {} },
iframe: { defaultDepartment, guest: { department } = {} },
} = store.state;

if (defaultAgent?.ts && Date.now() - defaultAgent.ts < agentCacheExpiry) {
return defaultAgent; // cache valid for 1 hour
}

const dep = department || defaultDepartment;

let agent = null;
try {
const tempAgent = await Livechat.nextAgent({ department });
const tempAgent = await Livechat.nextAgent({ department: dep });

if (isAgentWithInfo(tempAgent?.agent)) {
agent = tempAgent.agent;
Expand All @@ -35,7 +37,7 @@ const getNextAgentFromQueue = async () => {
return Promise.reject(error);
}

store.setState({ defaultAgent: { ...agent, department, ts: Date.now() } as Agent });
store.setState({ defaultAgent: { ...agent, department: dep, ts: Date.now() } as Agent });

return agent;
};
Expand Down

0 comments on commit f6de7b9

Please sign in to comment.