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..2b688acb627c2 --- /dev/null +++ b/apps/meteor/tests/e2e/omnichannel/omnichannel-custom-field-usage.spec.ts @@ -0,0 +1,154 @@ +import { faker } from '@faker-js/faker'; + +import { createFakeVisitor } from '../../mocks/data'; +import { Users } from '../fixtures/userStates'; +import { HomeOmnichannel } from '../page-objects'; +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'; + +const visitor = createFakeVisitor(); + +test.use({ storageState: Users.user1.state }); + +test.describe.serial('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 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 }) => { + [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, + }), + ]); + + await setVisitorCustomFieldValue(api, { + token: visitorToken, + customFieldId: visitorCustomField.customField._id, + value: visitorCustomFieldValue, + }); + }); + + test.beforeEach(async ({ page }) => { + poHomeChannel = new HomeOmnichannel(page); + await page.goto('/'); + await poHomeChannel.waitForHome(); + }); + + 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 () => { + 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.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.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..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 @@ -84,4 +84,8 @@ export class OmnichannelEditRoomFlexTab extends EditRoomFlexTab { get inputTags(): Locator { return this.root.getByRole('textbox', { name: 'Select an option' }); } + + 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 d911a81305d00..64be806a086be 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(customFieldId: string): Locator { + return this.root.locator(`[name="customFields.${customFieldId}"]`); + } + async solveConflict(field: string, value: string) { await this.btnSeeConflicts.click(); await this.contactReviewModal.solveConfirmation(field, value); diff --git a/apps/meteor/tests/e2e/utils/omnichannel/custom-field.ts b/apps/meteor/tests/e2e/utils/omnichannel/custom-field.ts index fca092c4133a5..7aa2f914f6ef3 100644 --- a/apps/meteor/tests/e2e/utils/omnichannel/custom-field.ts +++ b/apps/meteor/tests/e2e/utils/omnichannel/custom-field.ts @@ -10,6 +10,23 @@ 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()}]`); + } + const { field } = await response.json(); + return { response, field }; +}; + export const createCustomField = async (api: BaseTest['api'], overwrites: Partial) => { const response = await api.post('/livechat/custom-fields.save', { customFieldId: null,