From c5e323234112b0cca0dab06cfd4eb3651de1ace1 Mon Sep 17 00:00:00 2001 From: Harmeet221 Date: Tue, 17 Feb 2026 15:58:39 +0530 Subject: [PATCH 1/6] test: custom field usage --- .../omnichannel-custom-field-usage.spec.ts | 164 ++++++++++++++++++ .../fragments/edit-room-flextab.ts | 4 + .../omnichannel/omnichannel-info.ts | 8 + 3 files changed, 176 insertions(+) create mode 100644 apps/meteor/tests/e2e/omnichannel/omnichannel-custom-field-usage.spec.ts diff --git a/apps/meteor/tests/e2e/omnichannel/omnichannel-custom-field-usage.spec.ts b/apps/meteor/tests/e2e/omnichannel/omnichannel-custom-field-usage.spec.ts new file mode 100644 index 0000000000000..fd3a8c06523d5 --- /dev/null +++ b/apps/meteor/tests/e2e/omnichannel/omnichannel-custom-field-usage.spec.ts @@ -0,0 +1,164 @@ +import { faker } from '@faker-js/faker'; + +import { createFakeVisitor } from '../../mocks/data'; +import { Users } from '../fixtures/userStates'; +import { HomeOmnichannel } from '../page-objects'; +import { createCustomField } from '../utils/omnichannel/custom-field'; +import { createConversation } from '../utils/omnichannel/rooms'; +import { test, expect } from '../utils/test'; + +const visitor = createFakeVisitor(); + +test.use({ storageState: Users.user1.state }); + +test.describe('OC - Custom fields usage, scope : room and visitor', () => { + let poHomeChannel: HomeOmnichannel; + + const roomCustomFieldLabel = `room_cf_${faker.string.alpha(8)}`; + const roomCustomFieldName = roomCustomFieldLabel; + const roomCustomFieldValue = faker.lorem.words(3); + + const visitorCustomFieldLabel = `visitor_cf_${faker.string.alpha(8)}`; + const visitorCustomFieldName = visitorCustomFieldLabel; + const visitorCustomFieldValue = faker.lorem.words(3); + const visitorToken = faker.string.uuid(); + + let conversation: Awaited>; + let roomCustomField: Awaited>; + let visitorCustomField: Awaited>; + + test.beforeAll('Set up agent, manager and custom fields', async ({ api }) => { + const responses = await Promise.all([ + api.post('/livechat/users/agent', { username: 'user1' }), + api.post('/livechat/users/manager', { username: 'user1' }), + ]); + responses.forEach((res) => expect(res.status()).toBe(200)); + + roomCustomField = await createCustomField(api, { + field: roomCustomFieldLabel, + label: roomCustomFieldName, + scope: 'room', + }); + + visitorCustomField = await createCustomField(api, { + field: visitorCustomFieldName, + label: visitorCustomFieldLabel, + scope: 'visitor', + }); + + conversation = await createConversation(api, { + visitorName: visitor.name, + agentId: 'user1', + visitorToken, + }); + + const res = await api.post('/livechat/custom.field', { + token: visitorToken, + key: visitorCustomField.customField._id, + value: visitorCustomFieldValue, + overwrite: true, + }); + expect(res.status()).toBe(200); + }); + + test.beforeEach(async ({ page }) => { + poHomeChannel = new HomeOmnichannel(page); + await page.goto('/'); + await page.locator('#main-content').waitFor(); + }); + + test.afterAll('Remove agent, manager and custom fields', async ({ api }) => { + const responses = await Promise.all([api.delete('/livechat/users/agent/user1'), api.delete('/livechat/users/manager/user1')]); + responses.forEach((res) => expect(res.status()).toBe(200)); + + await roomCustomField.delete(); + await visitorCustomField.delete(); + await conversation.delete(); + }); + + test('Should be allowed to set room custom field for a conversation', async () => { + await test.step('Agent opens the conversation', async () => { + await poHomeChannel.sidebar.getSidebarItemByName(visitor.name).click(); + }); + + await test.step('Agent opens edit room', async () => { + await poHomeChannel.roomInfo.waitForDisplay(); + await poHomeChannel.roomInfo.btnEdit.click(); + await poHomeChannel.editRoomInfo.waitForDisplay(); + }); + + await test.step('Agent fills room custom field and saves', async () => { + await poHomeChannel.editRoomInfo.getRoomCustomField(roomCustomFieldLabel).fill(roomCustomFieldValue); + await poHomeChannel.editRoomInfo.btnSave.click(); + }); + + await test.step('Custom field should be updated successfully', async () => { + await poHomeChannel.roomInfo.btnEdit.click(); + await poHomeChannel.editRoomInfo.waitForDisplay(); + await expect(poHomeChannel.editRoomInfo.getRoomCustomField(roomCustomFieldLabel)).toHaveValue(roomCustomFieldValue); + }); + }); + + test('Should be allowed to update existing room custom field', async () => { + const updatedValue = faker.lorem.words(2); + + await test.step('Agent opens the conversation', async () => { + await poHomeChannel.sidebar.getSidebarItemByName(visitor.name).click(); + }); + + await test.step('Agent opens edit room and updates custom field', async () => { + // await poHomeChannel.roomToolbar.openRoomInfo(); + await poHomeChannel.roomInfo.waitForDisplay(); + await poHomeChannel.roomInfo.btnEdit.click(); + await poHomeChannel.editRoomInfo.waitForDisplay(); + await poHomeChannel.editRoomInfo.getRoomCustomField(roomCustomFieldLabel).fill(updatedValue); + await poHomeChannel.editRoomInfo.btnSave.click(); + }); + + await test.step('Room Information displays the updated custom field value', async () => { + // await poHomeChannel.roomToolbar.openRoomInfo(); + // await poHomeChannel.roomInfo.waitForDisplay(); + await poHomeChannel.roomInfo.btnEdit.click(); + await poHomeChannel.editRoomInfo.waitForDisplay(); + await expect(poHomeChannel.editRoomInfo.getRoomCustomField(roomCustomFieldLabel)).toHaveValue(updatedValue); + }); + }); + + test('Should verify that the visitor custom field is set', async () => { + await test.step('Agent opens the conversation', async () => { + await poHomeChannel.sidebar.getSidebarItemByName(visitor.name).click(); + }); + + await test.step('Agent opens Contact Information', async () => { + await poHomeChannel.roomToolbar.openContactInfo(); + await expect(poHomeChannel.contacts.contactInfo.dialogContactInfo).toBeVisible(); + }); + + await test.step('Assert custom field is set successfully', async () => { + await expect(poHomeChannel.contacts.contactInfo.dialogContactInfo).toContainText(visitorCustomFieldValue); + }); + }); + + test('Should be allowed to update existing visitor custom field', async () => { + const updatedVisitorCustomFieldValue = faker.lorem.words(2); + + await test.step('Agent opens the conversation', async () => { + await poHomeChannel.sidebar.getSidebarItemByName(visitor.name).click(); + }); + + await test.step('Agent opens Contact Information', async () => { + await poHomeChannel.roomToolbar.openContactInfo(); + await expect(poHomeChannel.contacts.contactInfo.dialogContactInfo).toBeVisible(); + }); + + await test.step('Agent clicks edit and updates visitor custom field', async () => { + await poHomeChannel.contacts.contactInfo.btnEdit.click(); + await poHomeChannel.contacts.contactInfo.getVisitorCustomField(visitorCustomFieldLabel).fill(updatedVisitorCustomFieldValue); + await poHomeChannel.contacts.contactInfo.btnSave.click(); + }); + + await test.step('Assert custom field is updated successfully', async () => { + await expect(poHomeChannel.contacts.contactInfo.dialogContactInfo).toContainText(updatedVisitorCustomFieldValue); + }); + }); +}); diff --git a/apps/meteor/tests/e2e/page-objects/fragments/edit-room-flextab.ts b/apps/meteor/tests/e2e/page-objects/fragments/edit-room-flextab.ts index bfc88661991bb..80d9d2be73d24 100644 --- a/apps/meteor/tests/e2e/page-objects/fragments/edit-room-flextab.ts +++ b/apps/meteor/tests/e2e/page-objects/fragments/edit-room-flextab.ts @@ -84,4 +84,8 @@ export class OmnichannelEditRoomFlexTab extends EditRoomFlexTab { get inputTags(): Locator { return this.root.getByRole('textbox', { name: 'Select an option' }); } + + getRoomCustomField(label: string): Locator { + return this.root.getByLabel(label); + } } diff --git a/apps/meteor/tests/e2e/page-objects/omnichannel/omnichannel-info.ts b/apps/meteor/tests/e2e/page-objects/omnichannel/omnichannel-info.ts index d911a81305d00..d22a8bfffa466 100644 --- a/apps/meteor/tests/e2e/page-objects/omnichannel/omnichannel-info.ts +++ b/apps/meteor/tests/e2e/page-objects/omnichannel/omnichannel-info.ts @@ -39,6 +39,14 @@ export class OmnichannelContactInfo extends FlexTab { return this.root.getByRole('button', { name: 'See conflicts' }); } + get dialogContactInfo(): Locator { + return this.root; + } + + getVisitorCustomField(label: string): Locator { + return this.root.getByLabel(label); + } + async solveConflict(field: string, value: string) { await this.btnSeeConflicts.click(); await this.contactReviewModal.solveConfirmation(field, value); From 2dc25343d2423568343016b988c1fe2bb8785600 Mon Sep 17 00:00:00 2001 From: Harmeet221 Date: Tue, 17 Feb 2026 16:04:32 +0530 Subject: [PATCH 2/6] remove comments --- .../e2e/omnichannel/omnichannel-custom-field-usage.spec.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/apps/meteor/tests/e2e/omnichannel/omnichannel-custom-field-usage.spec.ts b/apps/meteor/tests/e2e/omnichannel/omnichannel-custom-field-usage.spec.ts index fd3a8c06523d5..beb1f69ed48a1 100644 --- a/apps/meteor/tests/e2e/omnichannel/omnichannel-custom-field-usage.spec.ts +++ b/apps/meteor/tests/e2e/omnichannel/omnichannel-custom-field-usage.spec.ts @@ -107,7 +107,6 @@ test.describe('OC - Custom fields usage, scope : room and visitor', () => { }); await test.step('Agent opens edit room and updates custom field', async () => { - // await poHomeChannel.roomToolbar.openRoomInfo(); await poHomeChannel.roomInfo.waitForDisplay(); await poHomeChannel.roomInfo.btnEdit.click(); await poHomeChannel.editRoomInfo.waitForDisplay(); @@ -116,8 +115,6 @@ test.describe('OC - Custom fields usage, scope : room and visitor', () => { }); await test.step('Room Information displays the updated custom field value', async () => { - // await poHomeChannel.roomToolbar.openRoomInfo(); - // await poHomeChannel.roomInfo.waitForDisplay(); await poHomeChannel.roomInfo.btnEdit.click(); await poHomeChannel.editRoomInfo.waitForDisplay(); await expect(poHomeChannel.editRoomInfo.getRoomCustomField(roomCustomFieldLabel)).toHaveValue(updatedValue); From a540ac8110f5949000bdf43139443a94fb9f9836 Mon Sep 17 00:00:00 2001 From: Harmeet221 Date: Tue, 17 Feb 2026 18:17:20 +0530 Subject: [PATCH 3/6] remove comments --- .../e2e/omnichannel/omnichannel-custom-field-usage.spec.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/meteor/tests/e2e/omnichannel/omnichannel-custom-field-usage.spec.ts b/apps/meteor/tests/e2e/omnichannel/omnichannel-custom-field-usage.spec.ts index beb1f69ed48a1..6580e28267b1c 100644 --- a/apps/meteor/tests/e2e/omnichannel/omnichannel-custom-field-usage.spec.ts +++ b/apps/meteor/tests/e2e/omnichannel/omnichannel-custom-field-usage.spec.ts @@ -11,7 +11,7 @@ const visitor = createFakeVisitor(); test.use({ storageState: Users.user1.state }); -test.describe('OC - Custom fields usage, scope : room and visitor', () => { +test.describe.serial('OC - Custom fields usage, scope : room and visitor', () => { let poHomeChannel: HomeOmnichannel; const roomCustomFieldLabel = `room_cf_${faker.string.alpha(8)}`; @@ -64,7 +64,7 @@ test.describe('OC - Custom fields usage, scope : room and visitor', () => { test.beforeEach(async ({ page }) => { poHomeChannel = new HomeOmnichannel(page); await page.goto('/'); - await page.locator('#main-content').waitFor(); + await poHomeChannel.waitForHome(); }); test.afterAll('Remove agent, manager and custom fields', async ({ api }) => { From 2649557326310db212438db5c145a4fdb8fe710c Mon Sep 17 00:00:00 2001 From: Harmeet221 Date: Thu, 19 Feb 2026 12:51:52 +0530 Subject: [PATCH 4/6] added promise.all --- .../omnichannel-custom-field-usage.spec.ts | 61 ++++++++----------- .../e2e/utils/omnichannel/custom-field.ts | 16 +++++ 2 files changed, 43 insertions(+), 34 deletions(-) diff --git a/apps/meteor/tests/e2e/omnichannel/omnichannel-custom-field-usage.spec.ts b/apps/meteor/tests/e2e/omnichannel/omnichannel-custom-field-usage.spec.ts index 6580e28267b1c..2b688acb627c2 100644 --- a/apps/meteor/tests/e2e/omnichannel/omnichannel-custom-field-usage.spec.ts +++ b/apps/meteor/tests/e2e/omnichannel/omnichannel-custom-field-usage.spec.ts @@ -3,7 +3,9 @@ import { faker } from '@faker-js/faker'; import { createFakeVisitor } from '../../mocks/data'; import { Users } from '../fixtures/userStates'; import { HomeOmnichannel } from '../page-objects'; -import { createCustomField } from '../utils/omnichannel/custom-field'; +import { createAgent } from '../utils/omnichannel/agents'; +import { createCustomField, setVisitorCustomFieldValue } from '../utils/omnichannel/custom-field'; +import { createManager } from '../utils/omnichannel/managers'; import { createConversation } from '../utils/omnichannel/rooms'; import { test, expect } from '../utils/test'; @@ -23,42 +25,38 @@ test.describe.serial('OC - Custom fields usage, scope : room and visitor', () => const visitorCustomFieldValue = faker.lorem.words(3); const visitorToken = faker.string.uuid(); + let agent: Awaited>; + let manager: Awaited>; let conversation: Awaited>; let roomCustomField: Awaited>; let visitorCustomField: Awaited>; test.beforeAll('Set up agent, manager and custom fields', async ({ api }) => { - const responses = await Promise.all([ - api.post('/livechat/users/agent', { username: 'user1' }), - api.post('/livechat/users/manager', { username: 'user1' }), + [agent, manager] = await Promise.all([createAgent(api, 'user1'), createManager(api, 'user1')]); + + [roomCustomField, visitorCustomField, conversation] = await Promise.all([ + createCustomField(api, { + field: roomCustomFieldLabel, + label: roomCustomFieldName, + scope: 'room', + }), + createCustomField(api, { + field: visitorCustomFieldLabel, + label: visitorCustomFieldName, + scope: 'visitor', + }), + createConversation(api, { + visitorName: visitor.name, + agentId: 'user1', + visitorToken, + }), ]); - responses.forEach((res) => expect(res.status()).toBe(200)); - roomCustomField = await createCustomField(api, { - field: roomCustomFieldLabel, - label: roomCustomFieldName, - scope: 'room', - }); - - visitorCustomField = await createCustomField(api, { - field: visitorCustomFieldName, - label: visitorCustomFieldLabel, - scope: 'visitor', - }); - - conversation = await createConversation(api, { - visitorName: visitor.name, - agentId: 'user1', - visitorToken, - }); - - const res = await api.post('/livechat/custom.field', { + await setVisitorCustomFieldValue(api, { token: visitorToken, - key: visitorCustomField.customField._id, + customFieldId: visitorCustomField.customField._id, value: visitorCustomFieldValue, - overwrite: true, }); - expect(res.status()).toBe(200); }); test.beforeEach(async ({ page }) => { @@ -67,13 +65,8 @@ test.describe.serial('OC - Custom fields usage, scope : room and visitor', () => await poHomeChannel.waitForHome(); }); - test.afterAll('Remove agent, manager and custom fields', async ({ api }) => { - const responses = await Promise.all([api.delete('/livechat/users/agent/user1'), api.delete('/livechat/users/manager/user1')]); - responses.forEach((res) => expect(res.status()).toBe(200)); - - await roomCustomField.delete(); - await visitorCustomField.delete(); - await conversation.delete(); + test.afterAll('Remove agent, manager, custom fields and conversation', async () => { + await Promise.all([agent.delete(), manager.delete(), roomCustomField.delete(), visitorCustomField.delete(), conversation.delete()]); }); test('Should be allowed to set room custom field for a conversation', async () => { diff --git a/apps/meteor/tests/e2e/utils/omnichannel/custom-field.ts b/apps/meteor/tests/e2e/utils/omnichannel/custom-field.ts index fca092c4133a5..6d4efffcc5e91 100644 --- a/apps/meteor/tests/e2e/utils/omnichannel/custom-field.ts +++ b/apps/meteor/tests/e2e/utils/omnichannel/custom-field.ts @@ -10,6 +10,22 @@ export const removeCustomField = (api: BaseTest['api'], id: string) => { }); }; +export const setVisitorCustomFieldValue = async ( + api: BaseTest['api'], + params: { token: string; customFieldId: string; value: string; overwrite?: boolean }, +) => { + const response = await api.post('/livechat/custom.field', { + token: params.token, + key: params.customFieldId, + value: params.value, + overwrite: params.overwrite ?? true, + }); + if (!response.ok()) { + throw new Error(`Failed to set visitor custom field [http status: ${response.status()}]`); + } + return response; +}; + export const createCustomField = async (api: BaseTest['api'], overwrites: Partial) => { const response = await api.post('/livechat/custom-fields.save', { customFieldId: null, From d08b14a03ecdf22b34b12a9f1eb6045ff8d9f6e7 Mon Sep 17 00:00:00 2001 From: Harmeet221 Date: Thu, 19 Feb 2026 20:26:27 +0530 Subject: [PATCH 5/6] fixed review --- apps/meteor/tests/e2e/utils/omnichannel/custom-field.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/meteor/tests/e2e/utils/omnichannel/custom-field.ts b/apps/meteor/tests/e2e/utils/omnichannel/custom-field.ts index 6d4efffcc5e91..7aa2f914f6ef3 100644 --- a/apps/meteor/tests/e2e/utils/omnichannel/custom-field.ts +++ b/apps/meteor/tests/e2e/utils/omnichannel/custom-field.ts @@ -23,7 +23,8 @@ export const setVisitorCustomFieldValue = async ( if (!response.ok()) { throw new Error(`Failed to set visitor custom field [http status: ${response.status()}]`); } - return response; + const { field } = await response.json(); + return { response, field }; }; export const createCustomField = async (api: BaseTest['api'], overwrites: Partial) => { From 8e1e9b91c4b14acbaace5c4f69a29d1bfda20961 Mon Sep 17 00:00:00 2001 From: Harmeet221 Date: Fri, 20 Feb 2026 16:37:27 +0530 Subject: [PATCH 6/6] improved locator --- .../tests/e2e/page-objects/fragments/edit-room-flextab.ts | 4 ++-- .../tests/e2e/page-objects/omnichannel/omnichannel-info.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/meteor/tests/e2e/page-objects/fragments/edit-room-flextab.ts b/apps/meteor/tests/e2e/page-objects/fragments/edit-room-flextab.ts index 80d9d2be73d24..94fc7ec652074 100644 --- a/apps/meteor/tests/e2e/page-objects/fragments/edit-room-flextab.ts +++ b/apps/meteor/tests/e2e/page-objects/fragments/edit-room-flextab.ts @@ -85,7 +85,7 @@ export class OmnichannelEditRoomFlexTab extends EditRoomFlexTab { return this.root.getByRole('textbox', { name: 'Select an option' }); } - getRoomCustomField(label: string): Locator { - return this.root.getByLabel(label); + getRoomCustomField(customFieldId: string): Locator { + return this.root.locator(`[name="livechatData.${customFieldId}"]`); } } diff --git a/apps/meteor/tests/e2e/page-objects/omnichannel/omnichannel-info.ts b/apps/meteor/tests/e2e/page-objects/omnichannel/omnichannel-info.ts index d22a8bfffa466..64be806a086be 100644 --- a/apps/meteor/tests/e2e/page-objects/omnichannel/omnichannel-info.ts +++ b/apps/meteor/tests/e2e/page-objects/omnichannel/omnichannel-info.ts @@ -43,8 +43,8 @@ export class OmnichannelContactInfo extends FlexTab { return this.root; } - getVisitorCustomField(label: string): Locator { - return this.root.getByLabel(label); + getVisitorCustomField(customFieldId: string): Locator { + return this.root.locator(`[name="customFields.${customFieldId}"]`); } async solveConflict(field: string, value: string) {