snapshot of https://github.com/RocketChat/Rocket.Chat.git (develop, 2026-09-16; blobs > 131072B omitted)
Some checks failed
Create issues from TODOs / todos (push) Failing after 3s
Close inactive issues / close-issues (push) Has been cancelled
Deploy GitHub Pages / deploy-preview (push) Has been cancelled
CI / ⚙️ Variables Setup (push) Has been cancelled
CI / ⚙️ Test Guard (push) Has been cancelled
CI / 🚀 Notify external services - draft (push) Has been cancelled
CI / 📦 Build Packages (push) Has been cancelled
CI / 📦 Meteor Build (coverage) (push) Has been cancelled
CI / 📦 Meteor Build (production) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [account-service presence-service omnichannel-transcript-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [account-service presence-service omnichannel-transcript-service], fips) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [authorization-service queue-worker-service ddp-streamer-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [authorization-service queue-worker-service ddp-streamer-service], fips) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], coverage) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], fips) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [account-service presence-service omnichannel-transcript-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [authorization-service queue-worker-service ddp-streamer-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [rocketchat], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [rocketchat], coverage) (push) Has been cancelled
CI / 🚢 Publish Docker Images (ghcr.io) (push) Has been cancelled
CI / 📦 Track Image Sizes (push) Has been cancelled
CI / 🔎 Code Check - Action Lint (push) Has been cancelled
CI / 🔎 Code Check (push) Has been cancelled
CI / 🔨 Test Storybook (push) Has been cancelled
CI / 🔨 Test Unit (push) Has been cancelled
CI / 🔨 Test API (CE) (push) Has been cancelled
CI / 🔨 Test API Livechat (CE) (push) Has been cancelled
CI / 🔨 Test UI (CE) (push) Has been cancelled
CI / 🔨 Test API (EE) (push) Has been cancelled
CI / 🔨 Test API Livechat (EE) (push) Has been cancelled
CI / 🔨 Test API Apps (deno-runtime - EE) (push) Has been cancelled
CI / 🔨 Test UI (EE) (push) Has been cancelled
CI / 🔨 Test API (FIPS) (push) Has been cancelled
CI / 🔨 Test API Livechat (FIPS) (push) Has been cancelled
CI / 🔨 Test UI (FIPS) (push) Has been cancelled
CI / 🔨 Test Federation Matrix (push) Has been cancelled
CI / 📊 Report Coverage (push) Has been cancelled
CI / ✅ Tests Done (push) Has been cancelled
CI / 🚀 Publish build assets (push) Has been cancelled
CI / 🚀 Publish Docker Images (DockerHub) (push) Has been cancelled
CI / 🚀 Notify external services (push) Has been cancelled
CI / Update Version Durability (push) Has been cancelled
Release / Release (push) Has been cancelled
Auto-close duplicate issues / auto-close-duplicates (push) Failing after 1s
Code scanning - action / CodeQL-Build (push) Failing after 1s
Some checks failed
Create issues from TODOs / todos (push) Failing after 3s
Close inactive issues / close-issues (push) Has been cancelled
Deploy GitHub Pages / deploy-preview (push) Has been cancelled
CI / ⚙️ Variables Setup (push) Has been cancelled
CI / ⚙️ Test Guard (push) Has been cancelled
CI / 🚀 Notify external services - draft (push) Has been cancelled
CI / 📦 Build Packages (push) Has been cancelled
CI / 📦 Meteor Build (coverage) (push) Has been cancelled
CI / 📦 Meteor Build (production) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [account-service presence-service omnichannel-transcript-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [account-service presence-service omnichannel-transcript-service], fips) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [authorization-service queue-worker-service ddp-streamer-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [authorization-service queue-worker-service ddp-streamer-service], fips) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], coverage) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], fips) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [account-service presence-service omnichannel-transcript-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [authorization-service queue-worker-service ddp-streamer-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [rocketchat], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [rocketchat], coverage) (push) Has been cancelled
CI / 🚢 Publish Docker Images (ghcr.io) (push) Has been cancelled
CI / 📦 Track Image Sizes (push) Has been cancelled
CI / 🔎 Code Check - Action Lint (push) Has been cancelled
CI / 🔎 Code Check (push) Has been cancelled
CI / 🔨 Test Storybook (push) Has been cancelled
CI / 🔨 Test Unit (push) Has been cancelled
CI / 🔨 Test API (CE) (push) Has been cancelled
CI / 🔨 Test API Livechat (CE) (push) Has been cancelled
CI / 🔨 Test UI (CE) (push) Has been cancelled
CI / 🔨 Test API (EE) (push) Has been cancelled
CI / 🔨 Test API Livechat (EE) (push) Has been cancelled
CI / 🔨 Test API Apps (deno-runtime - EE) (push) Has been cancelled
CI / 🔨 Test UI (EE) (push) Has been cancelled
CI / 🔨 Test API (FIPS) (push) Has been cancelled
CI / 🔨 Test API Livechat (FIPS) (push) Has been cancelled
CI / 🔨 Test UI (FIPS) (push) Has been cancelled
CI / 🔨 Test Federation Matrix (push) Has been cancelled
CI / 📊 Report Coverage (push) Has been cancelled
CI / ✅ Tests Done (push) Has been cancelled
CI / 🚀 Publish build assets (push) Has been cancelled
CI / 🚀 Publish Docker Images (DockerHub) (push) Has been cancelled
CI / 🚀 Notify external services (push) Has been cancelled
CI / Update Version Durability (push) Has been cancelled
Release / Release (push) Has been cancelled
Auto-close duplicate issues / auto-close-duplicates (push) Failing after 1s
Code scanning - action / CodeQL-Build (push) Failing after 1s
This commit is contained in:
191
apps/meteor/tests/e2e/omnichannel/omnichannel-agents.spec.ts
Normal file
191
apps/meteor/tests/e2e/omnichannel/omnichannel-agents.spec.ts
Normal file
@@ -0,0 +1,191 @@
|
||||
import { createFakeDepartment } from '../../mocks/data';
|
||||
import { IS_EE } from '../config/constants';
|
||||
import { Users } from '../fixtures/userStates';
|
||||
import { OmnichannelAgents } from '../page-objects/omnichannel';
|
||||
import { setSettingValueById } from '../utils';
|
||||
import { createDepartment } from '../utils/omnichannel/departments';
|
||||
import { test, expect } from '../utils/test';
|
||||
|
||||
test.use({ storageState: Users.admin.state });
|
||||
|
||||
test.describe.serial('OC - Manage Agents', () => {
|
||||
let poOmnichannelAgents: OmnichannelAgents;
|
||||
let department: Awaited<ReturnType<typeof createDepartment>>;
|
||||
|
||||
// Create agent and department
|
||||
test.beforeEach(async ({ api }) => {
|
||||
department = await createDepartment(api);
|
||||
});
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
poOmnichannelAgents = new OmnichannelAgents(page);
|
||||
await poOmnichannelAgents.goto();
|
||||
});
|
||||
|
||||
test.beforeAll(async ({ api }) => {
|
||||
expect((await setSettingValueById(api, 'Omnichannel_enable_department_removal', true)).status()).toBe(200);
|
||||
});
|
||||
|
||||
test.afterAll(async ({ api }) => {
|
||||
expect((await setSettingValueById(api, 'Omnichannel_enable_department_removal', false)).status()).toBe(200);
|
||||
});
|
||||
|
||||
// Ensure that there is no leftover data even if test fails
|
||||
test.afterEach(async ({ api }) => {
|
||||
await api.delete('/livechat/users/agent/user1');
|
||||
await department.delete();
|
||||
});
|
||||
|
||||
test('OC - Manage Agents - Add, search and remove using table', async ({ page }) => {
|
||||
await test.step('expect "user1" be first ', async () => {
|
||||
await poOmnichannelAgents.inputUsername.type('user');
|
||||
await expect(page.locator('role=option[name="user1"]')).toContainText('user1');
|
||||
|
||||
await poOmnichannelAgents.inputUsername.fill('');
|
||||
});
|
||||
|
||||
await test.step('expect add "user1" as agent', async () => {
|
||||
await poOmnichannelAgents.selectUsername('user1');
|
||||
await poOmnichannelAgents.btnAddAgent.click();
|
||||
|
||||
await poOmnichannelAgents.search('user1');
|
||||
await expect(poOmnichannelAgents.table.findRowByName('user1')).toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('expect remove "user1" as agent', async () => {
|
||||
await poOmnichannelAgents.search('user1');
|
||||
await poOmnichannelAgents.deleteAgent('user1');
|
||||
|
||||
await poOmnichannelAgents.search('user1');
|
||||
await expect(poOmnichannelAgents.table.findRowByName('user1')).not.toBeVisible();
|
||||
});
|
||||
});
|
||||
|
||||
test('OC - Manage Agents [CE]- Edit and Remove', async () => {
|
||||
test.skip(IS_EE, 'Community Edition Only');
|
||||
|
||||
await poOmnichannelAgents.selectUsername('user1');
|
||||
await poOmnichannelAgents.btnAddAgent.click();
|
||||
|
||||
await poOmnichannelAgents.search('user1');
|
||||
await poOmnichannelAgents.table.findRowByName('user1').click();
|
||||
await poOmnichannelAgents.agentInfo.btnEdit.click();
|
||||
|
||||
await test.step('expect max chats fields to be hidden', async () => {
|
||||
await expect(poOmnichannelAgents.editAgent.inputMaxChats).toBeHidden();
|
||||
});
|
||||
|
||||
await test.step('expect update "user1" information', async () => {
|
||||
await poOmnichannelAgents.editAgent.selectStatus('Not Available');
|
||||
await poOmnichannelAgents.editAgent.selectDepartment(department.data.name);
|
||||
await poOmnichannelAgents.editAgent.save();
|
||||
});
|
||||
|
||||
await test.step('expect removing "user1" via sidebar', async () => {
|
||||
await poOmnichannelAgents.search('user1');
|
||||
await poOmnichannelAgents.table.findRowByName('user1').click();
|
||||
await poOmnichannelAgents.agentInfo.btnRemove.click();
|
||||
});
|
||||
});
|
||||
|
||||
test('OC - Manage Agents [EE] - Edit ', async () => {
|
||||
test.skip(!IS_EE, 'Enterprise Only');
|
||||
|
||||
await poOmnichannelAgents.selectUsername('user1');
|
||||
await poOmnichannelAgents.btnAddAgent.click();
|
||||
|
||||
await poOmnichannelAgents.search('user1');
|
||||
await poOmnichannelAgents.table.findRowByName('user1').click();
|
||||
await poOmnichannelAgents.agentInfo.btnEdit.click();
|
||||
|
||||
await test.step('expect max chats field to be visible', async () => {
|
||||
await expect(poOmnichannelAgents.editAgent.inputMaxChats).toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('expect update "user1" information', async () => {
|
||||
await poOmnichannelAgents.editAgent.inputMaxChats.click();
|
||||
await poOmnichannelAgents.editAgent.inputMaxChats.fill('2');
|
||||
await poOmnichannelAgents.editAgent.btnSave.click();
|
||||
});
|
||||
});
|
||||
|
||||
test('OC - Edit agent - Manage departments', async ({ page }) => {
|
||||
await poOmnichannelAgents.selectUsername('user1');
|
||||
await poOmnichannelAgents.btnAddAgent.click();
|
||||
await poOmnichannelAgents.search('user1');
|
||||
await poOmnichannelAgents.table.findRowByName('user1').click();
|
||||
|
||||
await poOmnichannelAgents.agentInfo.btnEdit.click();
|
||||
await poOmnichannelAgents.editAgent.selectDepartment(department.data.name);
|
||||
const response = page.waitForResponse('**/api/v1/livechat/agents.saveInfo');
|
||||
await poOmnichannelAgents.editAgent.btnSave.click();
|
||||
|
||||
/**
|
||||
* between saving and opening the agent info again it is necessary to
|
||||
* wait for the agent to be saved, since after successfully saving
|
||||
* the contextual bar is closed
|
||||
* otherwise content will be closed even if the current one is not the editing one
|
||||
*/
|
||||
|
||||
await response;
|
||||
|
||||
await expect(poOmnichannelAgents.editAgent.root).not.toBeVisible();
|
||||
|
||||
await test.step('expect the selected department is visible', async () => {
|
||||
await poOmnichannelAgents.table.findRowByName('user1').click();
|
||||
|
||||
// mock the endpoint to use the one without pagination
|
||||
await page.route('/api/v1/livechat/department?showArchived=true', async (route) => {
|
||||
await route.fulfill({ json: { departments: [] } });
|
||||
});
|
||||
|
||||
await poOmnichannelAgents.agentInfo.btnEdit.click();
|
||||
await expect(poOmnichannelAgents.editAgent.findSelectedDepartment(department.data.name)).toBeVisible();
|
||||
});
|
||||
});
|
||||
|
||||
test('OC - Edit agent - Departments pagination', async ({ page }) => {
|
||||
const data = Array.from({ length: 100 }, (_, i) => createFakeDepartment({ name: `Department ${i}` }));
|
||||
await page.route('**/v1/livechat/department*', async (route, request) => {
|
||||
const url = new URL(request.url());
|
||||
const offset = parseInt(url.searchParams.get('offset') || '0', 10);
|
||||
const count = parseInt(url.searchParams.get('count') || '50', 10);
|
||||
const departments = data.slice(offset, offset + count);
|
||||
|
||||
await route.fulfill({
|
||||
status: 200,
|
||||
contentType: 'application/json',
|
||||
body: JSON.stringify({ departments, offset, count, total: data.length }),
|
||||
});
|
||||
});
|
||||
|
||||
await test.step('expect to add agent', async () => {
|
||||
await poOmnichannelAgents.selectUsername('user1');
|
||||
await poOmnichannelAgents.btnAddAgent.click();
|
||||
});
|
||||
|
||||
await test.step('expect to edit agent', async () => {
|
||||
await poOmnichannelAgents.search('user1');
|
||||
await poOmnichannelAgents.table.findRowByName('user1').click();
|
||||
await poOmnichannelAgents.agentInfo.btnEdit.click();
|
||||
});
|
||||
|
||||
await test.step('expect department field to be paginated', async () => {
|
||||
await poOmnichannelAgents.editAgent.inputDepartment.click();
|
||||
await expect(poOmnichannelAgents.editAgent.getDepartmentOption('Department 0')).toBeVisible();
|
||||
await poOmnichannelAgents.scrollToListBottom();
|
||||
await expect(poOmnichannelAgents.editAgent.getDepartmentOption('Department 49')).toBeVisible();
|
||||
await poOmnichannelAgents.scrollToListBottom();
|
||||
await expect(poOmnichannelAgents.editAgent.getDepartmentOption('Department 99')).toBeVisible();
|
||||
await poOmnichannelAgents.editAgent.close();
|
||||
});
|
||||
|
||||
await test.step('expect remove "user1" as agent', async () => {
|
||||
await poOmnichannelAgents.search('user1');
|
||||
await poOmnichannelAgents.deleteAgent('user1');
|
||||
|
||||
await poOmnichannelAgents.search('user1');
|
||||
await expect(poOmnichannelAgents.table.findRowByName('user1')).not.toBeVisible();
|
||||
});
|
||||
});
|
||||
});
|
||||
102
apps/meteor/tests/e2e/omnichannel/omnichannel-appearance.spec.ts
Normal file
102
apps/meteor/tests/e2e/omnichannel/omnichannel-appearance.spec.ts
Normal file
@@ -0,0 +1,102 @@
|
||||
import { IS_EE } from '../config/constants';
|
||||
import { Users } from '../fixtures/userStates';
|
||||
import { OmnichannelLivechatAppearance } from '../page-objects/omnichannel';
|
||||
import { test, expect } from '../utils/test';
|
||||
|
||||
test.use({ storageState: Users.admin.state });
|
||||
|
||||
test.describe.serial('OC - Livechat Appearance - EE', () => {
|
||||
let poLivechatAppearance: OmnichannelLivechatAppearance;
|
||||
test.skip(!IS_EE, 'Enterprise Only');
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
poLivechatAppearance = new OmnichannelLivechatAppearance(page);
|
||||
await poLivechatAppearance.goto();
|
||||
});
|
||||
|
||||
test.afterAll(async ({ api }) => {
|
||||
const res = await Promise.all([
|
||||
api.post('/settings/Livechat_hide_system_messages', { value: ['uj', 'ul', 'livechat-close'] }),
|
||||
api.post('/settings/Livechat_background', { value: '' }),
|
||||
]);
|
||||
|
||||
if (res.some((r) => r.status() !== 200)) {
|
||||
throw new Error('Failed to reset settings');
|
||||
}
|
||||
});
|
||||
|
||||
test('OC - Livechat Appearance - Hide system messages', async ({ page }) => {
|
||||
await test.step('expect to have default values', async () => {
|
||||
await poLivechatAppearance.inputHideSystemMessages.click();
|
||||
await expect(poLivechatAppearance.findHideSystemMessageOption('uj')).toHaveAttribute('aria-selected', 'true');
|
||||
await expect(poLivechatAppearance.findHideSystemMessageOption('ul')).toHaveAttribute('aria-selected', 'true');
|
||||
await expect(poLivechatAppearance.findHideSystemMessageOption('livechat-close')).toHaveAttribute('aria-selected', 'true');
|
||||
await poLivechatAppearance.inputHideSystemMessages.click();
|
||||
});
|
||||
|
||||
await test.step('expect to change values', async () => {
|
||||
await poLivechatAppearance.inputHideSystemMessages.click();
|
||||
await poLivechatAppearance.findHideSystemMessageOption('livechat_transfer_history').click();
|
||||
await poLivechatAppearance.findHideSystemMessageOption('livechat-close').click();
|
||||
await poLivechatAppearance.btnSaveChanges.click();
|
||||
});
|
||||
|
||||
await test.step('expect to have saved changes', async () => {
|
||||
await page.reload();
|
||||
await poLivechatAppearance.inputHideSystemMessages.click();
|
||||
await expect(poLivechatAppearance.findHideSystemMessageOption('uj')).toHaveAttribute('aria-selected', 'true');
|
||||
await expect(poLivechatAppearance.findHideSystemMessageOption('ul')).toHaveAttribute('aria-selected', 'true');
|
||||
await expect(poLivechatAppearance.findHideSystemMessageOption('livechat_transfer_history')).toHaveAttribute('aria-selected', 'true');
|
||||
await expect(poLivechatAppearance.findHideSystemMessageOption('livechat-close')).toHaveAttribute('aria-selected', 'false');
|
||||
});
|
||||
});
|
||||
|
||||
test('OC - Livechat Appearance - Change Livechat background', async ({ page }) => {
|
||||
await test.step('expect to have default value', async () => {
|
||||
await expect(await poLivechatAppearance.inputLivechatBackground).toHaveValue('');
|
||||
});
|
||||
|
||||
await test.step('expect to change value', async () => {
|
||||
await poLivechatAppearance.inputLivechatBackground.fill('rgb(186, 1, 85)');
|
||||
await poLivechatAppearance.btnSaveChanges.click();
|
||||
});
|
||||
|
||||
await test.step('expect to have saved changes', async () => {
|
||||
await page.reload();
|
||||
await expect(poLivechatAppearance.inputLivechatBackground).toHaveValue('rgb(186, 1, 85)');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('OC - Livechat Appearance - CE', () => {
|
||||
let poLivechatAppearance: OmnichannelLivechatAppearance;
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
poLivechatAppearance = new OmnichannelLivechatAppearance(page);
|
||||
await poLivechatAppearance.goto();
|
||||
});
|
||||
|
||||
test.afterAll(async ({ api }) => {
|
||||
const res = await api.post('/settings/Livechat_title', { value: 'Rocket.Chat' });
|
||||
|
||||
if (res.status() !== 200) {
|
||||
throw new Error('Failed to reset settings');
|
||||
}
|
||||
});
|
||||
|
||||
test('OC - Livechat Appearance - Change Livechat Title', async ({ page }) => {
|
||||
await test.step('expect to have default value', async () => {
|
||||
await expect(poLivechatAppearance.inputLivechatTitle).toHaveValue('Rocket.Chat');
|
||||
});
|
||||
|
||||
await test.step('expect to change value', async () => {
|
||||
await poLivechatAppearance.inputLivechatTitle.fill('Test Title');
|
||||
await poLivechatAppearance.btnSaveChanges.click();
|
||||
});
|
||||
|
||||
await test.step('expect to have saved changes', async () => {
|
||||
await page.reload();
|
||||
await expect(poLivechatAppearance.inputLivechatTitle).toHaveValue('Test Title');
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,147 @@
|
||||
import { createFakeVisitor } from '../../mocks/data';
|
||||
import { IS_EE } from '../config/constants';
|
||||
import { Users } from '../fixtures/userStates';
|
||||
import { HomeOmnichannel } from '../page-objects';
|
||||
import { setSettingValueById } from '../utils';
|
||||
import { createAgent } from '../utils/omnichannel/agents';
|
||||
import { addAgentToDepartment, createDepartment } from '../utils/omnichannel/departments';
|
||||
import { createConversation } from '../utils/omnichannel/rooms';
|
||||
import { createTag } from '../utils/omnichannel/tags';
|
||||
import { test, expect } from '../utils/test';
|
||||
|
||||
const visitorA = createFakeVisitor();
|
||||
const visitorB = createFakeVisitor();
|
||||
|
||||
test.use({ storageState: Users.user1.state });
|
||||
|
||||
test.describe('OC - Tags Visibility', () => {
|
||||
test.skip(!IS_EE, 'OC - Tags Visibility > Enterprise Edition Only');
|
||||
|
||||
let poOmnichannel: HomeOmnichannel;
|
||||
let conversations: Awaited<ReturnType<typeof createConversation>>[] = [];
|
||||
let departmentA: Awaited<ReturnType<typeof createDepartment>>;
|
||||
let departmentB: Awaited<ReturnType<typeof createDepartment>>;
|
||||
let agent: Awaited<ReturnType<typeof createAgent>>;
|
||||
let tagA: Awaited<ReturnType<typeof createTag>>;
|
||||
let tagB: Awaited<ReturnType<typeof createTag>>;
|
||||
let globalTag: Awaited<ReturnType<typeof createTag>>;
|
||||
let sharedTag: Awaited<ReturnType<typeof createTag>>;
|
||||
|
||||
test.beforeAll('Create departments', async ({ api }) => {
|
||||
expect((await setSettingValueById(api, 'Omnichannel_enable_department_removal', true)).status()).toBe(200);
|
||||
departmentA = await createDepartment(api, { name: 'Department A' });
|
||||
departmentB = await createDepartment(api, { name: 'Department B' });
|
||||
});
|
||||
|
||||
test.beforeAll('Create agent', async ({ api }) => {
|
||||
agent = await createAgent(api, 'user1');
|
||||
});
|
||||
|
||||
test.beforeAll('Add agents to departments', async ({ api }) => {
|
||||
await Promise.all([
|
||||
addAgentToDepartment(api, { department: departmentA.data, agentId: 'user1' }),
|
||||
addAgentToDepartment(api, { department: departmentB.data, agentId: 'user1' }),
|
||||
]);
|
||||
});
|
||||
|
||||
test.beforeAll('Create tags', async ({ api }) => {
|
||||
tagA = await createTag(api, { departments: [departmentA.data._id] });
|
||||
tagB = await createTag(api, { departments: [departmentB.data._id] });
|
||||
globalTag = await createTag(api, { departments: [] });
|
||||
sharedTag = await createTag(api, {
|
||||
departments: [departmentA.data._id, departmentB.data._id],
|
||||
});
|
||||
});
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
poOmnichannel = new HomeOmnichannel(page);
|
||||
await poOmnichannel.goto();
|
||||
});
|
||||
|
||||
test.beforeEach(async ({ api }) => {
|
||||
if (conversations.length === 0) {
|
||||
conversations = await Promise.all([
|
||||
createConversation(api, {
|
||||
visitorName: visitorA.name,
|
||||
agentId: 'user1',
|
||||
departmentId: departmentA.data._id,
|
||||
}),
|
||||
createConversation(api, {
|
||||
visitorName: visitorB.name,
|
||||
agentId: 'user1',
|
||||
departmentId: departmentB.data._id,
|
||||
}),
|
||||
]);
|
||||
}
|
||||
});
|
||||
|
||||
test.afterAll(async ({ api }) => {
|
||||
await Promise.all(conversations.map((conversation) => conversation.delete()));
|
||||
await Promise.all([tagA, tagB, globalTag, sharedTag].map((tag) => tag.delete()));
|
||||
await agent.delete();
|
||||
await departmentA.delete();
|
||||
await departmentB.delete();
|
||||
expect((await setSettingValueById(api, 'Omnichannel_enable_department_removal', false)).status()).toBe(200);
|
||||
});
|
||||
|
||||
test('Verify agent should see correct tags based on department association', async () => {
|
||||
await test.step('Agent opens room', async () => {
|
||||
await poOmnichannel.navbar.openChat(visitorA.name);
|
||||
});
|
||||
|
||||
await test.step('should not be able to see tags field', async () => {
|
||||
await expect(poOmnichannel.roomInfo.getLabel('Tags')).not.toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('check available tags', async () => {
|
||||
await poOmnichannel.roomInfo.btnEdit.click();
|
||||
await expect(poOmnichannel.editRoomInfo.root).toBeVisible();
|
||||
await poOmnichannel.editRoomInfo.inputTags.click();
|
||||
});
|
||||
|
||||
await test.step('Should see TagA (department A specific)', async () => {
|
||||
await expect(poOmnichannel.editRoomInfo.optionTag(tagA.data.name)).toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('Should see SharedTag (both departments)', async () => {
|
||||
await expect(poOmnichannel.editRoomInfo.optionTag(sharedTag.data.name)).toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('Should see Public Tags for all chats (no department restriction)', async () => {
|
||||
await expect(poOmnichannel.editRoomInfo.optionTag(globalTag.data.name)).toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('Should not see TagB (department B specific)', async () => {
|
||||
await expect(poOmnichannel.editRoomInfo.optionTag(tagB.data.name)).not.toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('add tags and save', async () => {
|
||||
await poOmnichannel.editRoomInfo.selectTag(tagA.data.name);
|
||||
await poOmnichannel.editRoomInfo.selectTag(globalTag.data.name);
|
||||
await poOmnichannel.editRoomInfo.btnSave.click();
|
||||
});
|
||||
|
||||
await test.step('verify selected tags are displayed under room information', async () => {
|
||||
await expect(poOmnichannel.roomInfo.getLabel('Tags')).toBeVisible();
|
||||
await expect(poOmnichannel.roomInfo.getTagInfoByLabel(tagA.data.name)).toBeVisible();
|
||||
await expect(poOmnichannel.roomInfo.getTagInfoByLabel(globalTag.data.name)).toBeVisible();
|
||||
});
|
||||
});
|
||||
|
||||
test('Verify tags visibility for agent associated with multiple departments', async () => {
|
||||
await test.step('Open room info', async () => {
|
||||
await poOmnichannel.navbar.openChat(visitorB.name);
|
||||
await poOmnichannel.roomInfo.btnEdit.click();
|
||||
await expect(poOmnichannel.editRoomInfo.root).toBeVisible();
|
||||
await poOmnichannel.editRoomInfo.inputTags.click();
|
||||
});
|
||||
|
||||
await test.step('Agent associated with DepartmentB should be able to see tags for Department B', async () => {
|
||||
await expect(poOmnichannel.editRoomInfo.optionTag(tagB.data.name)).toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('Agent associated with DepartmentB should not be able to see tags for DepartmentA', async () => {
|
||||
await expect(poOmnichannel.editRoomInfo.optionTag(tagA.data.name)).not.toBeVisible();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,83 @@
|
||||
import type { Page } from '@playwright/test';
|
||||
|
||||
import { createFakeVisitor } from '../../mocks/data';
|
||||
import { IS_EE } from '../config/constants';
|
||||
import { createAuxContext } from '../fixtures/createAuxContext';
|
||||
import { Users } from '../fixtures/userStates';
|
||||
import { HomeOmnichannel } from '../page-objects';
|
||||
import { OmnichannelLiveChat } from '../page-objects/omnichannel';
|
||||
import { test, expect } from '../utils/test';
|
||||
|
||||
test.describe('omnichannel-auto-onhold-chat-closing', () => {
|
||||
test.skip(!IS_EE, 'Enterprise Only');
|
||||
|
||||
let poLiveChat: OmnichannelLiveChat;
|
||||
let newVisitor: { email: string; name: string };
|
||||
|
||||
let agent: { page: Page; poHomeChannel: HomeOmnichannel };
|
||||
|
||||
test.beforeAll(async ({ api, browser }) => {
|
||||
await Promise.all([
|
||||
api.post('/livechat/users/agent', { username: 'user1' }).then((res) => expect(res.status()).toBe(200)),
|
||||
api.post('/settings/Livechat_Routing_Method', { value: 'Auto_Selection' }).then((res) => expect(res.status()).toBe(200)),
|
||||
api.post('/settings/Livechat_auto_close_on_hold_chats_timeout', { value: 5 }).then((res) => expect(res.status()).toBe(200)),
|
||||
api.post('/settings/Livechat_allow_manual_on_hold', { value: true }).then((res) => expect(res.status()).toBe(200)),
|
||||
]);
|
||||
|
||||
const { page } = await createAuxContext(browser, Users.user1);
|
||||
agent = { page, poHomeChannel: new HomeOmnichannel(page) };
|
||||
});
|
||||
test.afterAll(async ({ api }) => {
|
||||
await agent.page.close();
|
||||
|
||||
await Promise.all([
|
||||
api.delete('/livechat/users/agent/user1').then((res) => expect(res.status()).toBe(200)),
|
||||
api.post('/settings/Livechat_auto_close_on_hold_chats_timeout', { value: 3600 }).then((res) => expect(res.status()).toBe(200)),
|
||||
api.post('/settings/Livechat_allow_manual_on_hold', { value: false }).then((res) => expect(res.status()).toBe(200)),
|
||||
]);
|
||||
});
|
||||
|
||||
test.beforeEach(async ({ page, api }) => {
|
||||
// make "user-1" online
|
||||
await agent.poHomeChannel.navbar.changeUserStatus('online');
|
||||
|
||||
// start a new chat for each test
|
||||
newVisitor = createFakeVisitor();
|
||||
poLiveChat = new OmnichannelLiveChat(page, api);
|
||||
await poLiveChat.goto();
|
||||
await poLiveChat.openLiveChat();
|
||||
await poLiveChat.sendMessage(newVisitor, false);
|
||||
await poLiveChat.onlineAgentMessage.type('this_a_test_message_from_user');
|
||||
await poLiveChat.btnSendMessageToOnlineAgent.click();
|
||||
});
|
||||
|
||||
// Note: Skipping this test as the scheduler is gonna take 1 minute to process now
|
||||
// And waiting for 1 minute in a test is horrible
|
||||
test.skip('expect on-hold chat to be closed automatically in 5 seconds', async () => {
|
||||
await agent.poHomeChannel.navbar.openChat(newVisitor.name);
|
||||
await agent.poHomeChannel.content.sendMessage('this_is_a_test_message_from_agent');
|
||||
|
||||
await agent.poHomeChannel.quickActionsRoomToolbar.placeChatOnHold();
|
||||
|
||||
await agent.poHomeChannel.content.btnModalConfirm.click();
|
||||
|
||||
// expect to see a system message saying the chat was on-hold
|
||||
await expect(agent.poHomeChannel.content.lastSystemMessageBody).toHaveText(
|
||||
`Chat On Hold: The chat was manually placed On Hold by user1`,
|
||||
);
|
||||
await expect(agent.poHomeChannel.composer.inputMessage).not.toBeVisible();
|
||||
await expect(agent.poHomeChannel.content.resumeOnHoldOmnichannelChatButton).toBeVisible();
|
||||
|
||||
// current url
|
||||
const chatRoomUrl = agent.page.url();
|
||||
|
||||
// wait for the chat to be closed automatically for 5 seconds
|
||||
await agent.page.waitForTimeout(7000);
|
||||
|
||||
// expect to see a system message saying the chat was closed automatically in the closed chat room
|
||||
await agent.page.goto(chatRoomUrl);
|
||||
expect(await agent.poHomeChannel.content.lastSystemMessageBody.innerText()).toBe(
|
||||
'Conversation closed: Closed automatically because chat was On Hold for 5 seconds.',
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,71 @@
|
||||
import type { Page } from '@playwright/test';
|
||||
|
||||
import { createFakeVisitor } from '../../mocks/data';
|
||||
import { IS_EE } from '../config/constants';
|
||||
import { createAuxContext } from '../fixtures/createAuxContext';
|
||||
import { Users } from '../fixtures/userStates';
|
||||
import { HomeChannel } from '../page-objects';
|
||||
import { OmnichannelLiveChat } from '../page-objects/omnichannel';
|
||||
import { test, expect } from '../utils/test';
|
||||
|
||||
test.describe('omnichannel-auto-transfer-unanswered-chat', () => {
|
||||
test.skip(!IS_EE, 'Enterprise Only');
|
||||
|
||||
let poLiveChat: OmnichannelLiveChat;
|
||||
let newVisitor: { email: string; name: string };
|
||||
|
||||
let agent1: { page: Page; poHomeChannel: HomeChannel };
|
||||
let agent2: { page: Page; poHomeChannel: HomeChannel };
|
||||
|
||||
test.beforeAll(async ({ api, browser }) => {
|
||||
await Promise.all([
|
||||
api.post('/livechat/users/agent', { username: 'user1' }).then((res) => expect(res.status()).toBe(200)),
|
||||
api.post('/livechat/users/agent', { username: 'user2' }).then((res) => expect(res.status()).toBe(200)),
|
||||
api.post('/settings/Livechat_Routing_Method', { value: 'Auto_Selection' }).then((res) => expect(res.status()).toBe(200)),
|
||||
api.post('/settings/Livechat_auto_transfer_chat_timeout', { value: 5 }).then((res) => expect(res.status()).toBe(200)),
|
||||
]);
|
||||
|
||||
const { page } = await createAuxContext(browser, Users.user1);
|
||||
agent1 = { page, poHomeChannel: new HomeChannel(page) };
|
||||
|
||||
const { page: page2 } = await createAuxContext(browser, Users.user2);
|
||||
agent2 = { page: page2, poHomeChannel: new HomeChannel(page2) };
|
||||
});
|
||||
|
||||
test.afterAll(async ({ api }) => {
|
||||
await agent1.page.close();
|
||||
await agent2.page.close();
|
||||
|
||||
await Promise.all([
|
||||
api.delete('/livechat/users/agent/user1').then((res) => expect(res.status()).toBe(200)),
|
||||
api.delete('/livechat/users/agent/user2').then((res) => expect(res.status()).toBe(200)),
|
||||
api.post('/settings/Livechat_auto_transfer_chat_timeout', { value: 0 }).then((res) => expect(res.status()).toBe(200)),
|
||||
]);
|
||||
});
|
||||
|
||||
test.beforeEach(async ({ page, api }) => {
|
||||
// make "user-1" online
|
||||
await agent1.poHomeChannel.navbar.switchOmnichannelStatus('online');
|
||||
await agent2.poHomeChannel.navbar.switchOmnichannelStatus('offline');
|
||||
|
||||
// start a new chat for each test
|
||||
newVisitor = createFakeVisitor();
|
||||
poLiveChat = new OmnichannelLiveChat(page, api);
|
||||
await poLiveChat.goto();
|
||||
await poLiveChat.openLiveChat();
|
||||
await poLiveChat.sendMessage(newVisitor, false);
|
||||
await poLiveChat.onlineAgentMessage.type('this_a_test_message_from_user');
|
||||
await poLiveChat.btnSendMessageToOnlineAgent.click();
|
||||
});
|
||||
|
||||
test('expect chat to be auto transferred to next agent within 5 seconds of no reply from first agent', async () => {
|
||||
await agent1.poHomeChannel.navbar.openChat(newVisitor.name);
|
||||
|
||||
await agent2.poHomeChannel.navbar.switchOmnichannelStatus('online');
|
||||
|
||||
// wait for the chat to be closed automatically for 5 seconds
|
||||
await agent1.page.waitForTimeout(7000);
|
||||
|
||||
await agent2.poHomeChannel.navbar.openChat(newVisitor.name);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,163 @@
|
||||
import type { Page } from '@playwright/test';
|
||||
|
||||
import { IS_EE } from '../config/constants';
|
||||
import { Users } from '../fixtures/userStates';
|
||||
import { OmnichannelBusinessHours } from '../page-objects/omnichannel';
|
||||
import { setSettingValueById } from '../utils';
|
||||
import { createAgent } from '../utils/omnichannel/agents';
|
||||
import { createBusinessHour } from '../utils/omnichannel/businessHours';
|
||||
import { createDepartment } from '../utils/omnichannel/departments';
|
||||
import { test, expect } from '../utils/test';
|
||||
|
||||
test.use({ storageState: Users.admin.state });
|
||||
|
||||
// TODO: These tests needs to be refactored to be independent from each other
|
||||
test.describe('OC - Business Hours', () => {
|
||||
test.skip(!IS_EE, 'OC - Manage Business Hours > Enterprise Edition Only');
|
||||
|
||||
let poOmnichannelBusinessHours: OmnichannelBusinessHours;
|
||||
let department: Awaited<ReturnType<typeof createDepartment>>;
|
||||
let department2: Awaited<ReturnType<typeof createDepartment>>;
|
||||
let agent: Awaited<ReturnType<typeof createAgent>>;
|
||||
|
||||
const BHName = 'TEST Business Hours';
|
||||
|
||||
test.beforeAll(async ({ api }) => {
|
||||
department = await createDepartment(api);
|
||||
department2 = await createDepartment(api);
|
||||
agent = await createAgent(api, 'user2');
|
||||
expect((await setSettingValueById(api, 'Omnichannel_enable_department_removal', true)).status()).toBe(200);
|
||||
await api.post('/settings/Livechat_enable_business_hours', { value: true }).then((res) => expect(res.status()).toBe(200));
|
||||
await api.post('/settings/Livechat_business_hour_type', { value: 'Multiple' }).then((res) => expect(res.status()).toBe(200));
|
||||
});
|
||||
|
||||
test.afterAll(async ({ api }) => {
|
||||
await department.delete();
|
||||
await department2.delete();
|
||||
await agent.delete();
|
||||
expect((await setSettingValueById(api, 'Omnichannel_enable_department_removal', false)).status()).toBe(200);
|
||||
await api.post('/settings/Livechat_enable_business_hours', { value: false }).then((res) => expect(res.status()).toBe(200));
|
||||
await api.post('/settings/Livechat_business_hour_type', { value: 'Single' }).then((res) => expect(res.status()).toBe(200));
|
||||
});
|
||||
|
||||
test.beforeEach(async ({ page }: { page: Page }) => {
|
||||
poOmnichannelBusinessHours = new OmnichannelBusinessHours(page);
|
||||
});
|
||||
|
||||
test('OC - Manage Business Hours - Create Business Hours', async () => {
|
||||
await poOmnichannelBusinessHours.goto();
|
||||
|
||||
await test.step('expect correct form default state', async () => {
|
||||
await poOmnichannelBusinessHours.btnCreateBusinessHour.click();
|
||||
await poOmnichannelBusinessHours.btnBack.click();
|
||||
await expect(poOmnichannelBusinessHours.inputSearch).toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('expect to create a new business hours', async () => {
|
||||
await poOmnichannelBusinessHours.btnCreateBusinessHour.click();
|
||||
await poOmnichannelBusinessHours.inputName.fill(BHName);
|
||||
await poOmnichannelBusinessHours.selectDepartment(department.data.name);
|
||||
await poOmnichannelBusinessHours.btnSave.click();
|
||||
|
||||
await test.step('expect business hours to have been created', async () => {
|
||||
await poOmnichannelBusinessHours.search(BHName);
|
||||
await expect(poOmnichannelBusinessHours.table.findRowByName(BHName)).toBeVisible();
|
||||
});
|
||||
});
|
||||
|
||||
await test.step('expect to be able to delete business hours', async () => {
|
||||
await poOmnichannelBusinessHours.deleteBusinessHour(BHName);
|
||||
});
|
||||
|
||||
await test.step('expect business hours to have been deleted', async () => {
|
||||
await poOmnichannelBusinessHours.search(BHName);
|
||||
await expect(poOmnichannelBusinessHours.table.findRowByName(BHName)).not.toBeVisible();
|
||||
});
|
||||
});
|
||||
|
||||
test('OC - Business hours - Edit BH departments', async ({ api }) => {
|
||||
await test.step('expect to create new businessHours', async () => {
|
||||
const createBH = await createBusinessHour(api, {
|
||||
name: BHName,
|
||||
departments: [department.data._id],
|
||||
});
|
||||
|
||||
expect(createBH.status()).toBe(200);
|
||||
});
|
||||
|
||||
await poOmnichannelBusinessHours.goto();
|
||||
|
||||
await test.step('expect to add business hours departments', async () => {
|
||||
await poOmnichannelBusinessHours.search(BHName);
|
||||
await poOmnichannelBusinessHours.table.findRowByName(BHName).click();
|
||||
await poOmnichannelBusinessHours.selectDepartment(department2.data.name);
|
||||
await poOmnichannelBusinessHours.btnSave.click();
|
||||
await expect(poOmnichannelBusinessHours.btnSave).not.toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('expect department to be in the chosen departments list', async () => {
|
||||
await poOmnichannelBusinessHours.search(BHName);
|
||||
await poOmnichannelBusinessHours.table.findRowByName(BHName).click();
|
||||
await expect(poOmnichannelBusinessHours.findDepartmentsChipOption(department2.data.name)).toBeVisible();
|
||||
await poOmnichannelBusinessHours.btnBack.click();
|
||||
});
|
||||
|
||||
await test.step('expect to remove business hours departments', async () => {
|
||||
await poOmnichannelBusinessHours.search(BHName);
|
||||
await poOmnichannelBusinessHours.table.findRowByName(BHName).click();
|
||||
await poOmnichannelBusinessHours.selectDepartment(department2.data.name);
|
||||
await poOmnichannelBusinessHours.btnSave.click();
|
||||
await expect(poOmnichannelBusinessHours.btnSave).not.toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('expect department to not be in the chosen departments list', async () => {
|
||||
await poOmnichannelBusinessHours.search(BHName);
|
||||
await poOmnichannelBusinessHours.table.findRowByName(BHName).click();
|
||||
await expect(poOmnichannelBusinessHours.findDepartmentsChipOption(department2.data.name)).toBeHidden();
|
||||
await poOmnichannelBusinessHours.btnBack.click();
|
||||
});
|
||||
|
||||
await test.step('expect delete business hours', async () => {
|
||||
await poOmnichannelBusinessHours.deleteBusinessHour(BHName);
|
||||
});
|
||||
});
|
||||
|
||||
test('OC - Business hours - Toggle BH active status', async ({ api }) => {
|
||||
await test.step('expect to create new businessHours', async () => {
|
||||
const createBH = await createBusinessHour(api, {
|
||||
name: BHName,
|
||||
departments: [department.data._id],
|
||||
});
|
||||
|
||||
expect(createBH.status()).toBe(200);
|
||||
});
|
||||
|
||||
await poOmnichannelBusinessHours.goto();
|
||||
|
||||
await test.step('expect to disable business hours', async () => {
|
||||
await poOmnichannelBusinessHours.search(BHName);
|
||||
await poOmnichannelBusinessHours.table.findRowByName(BHName).click();
|
||||
|
||||
await poOmnichannelBusinessHours.getCheckboxByLabel('Enabled').click();
|
||||
await expect(poOmnichannelBusinessHours.getCheckboxByLabel('Enabled')).not.toBeChecked();
|
||||
|
||||
await poOmnichannelBusinessHours.btnSave.click();
|
||||
await expect(poOmnichannelBusinessHours.btnSave).not.toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('expect to enable business hours', async () => {
|
||||
await poOmnichannelBusinessHours.search(BHName);
|
||||
await poOmnichannelBusinessHours.table.findRowByName(BHName).click();
|
||||
|
||||
await poOmnichannelBusinessHours.getCheckboxByLabel('Enabled').click();
|
||||
await expect(poOmnichannelBusinessHours.getCheckboxByLabel('Enabled')).toBeChecked();
|
||||
|
||||
await poOmnichannelBusinessHours.btnSave.click();
|
||||
await expect(poOmnichannelBusinessHours.btnSave).not.toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('expect delete business hours', async () => {
|
||||
await poOmnichannelBusinessHours.deleteBusinessHour(BHName);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,93 @@
|
||||
import { faker } from '@faker-js/faker';
|
||||
import type { Page } from '@playwright/test';
|
||||
|
||||
import { createFakeVisitor } from '../../mocks/data';
|
||||
import { IS_EE } from '../config/constants';
|
||||
import { createAuxContext } from '../fixtures/createAuxContext';
|
||||
import { Users } from '../fixtures/userStates';
|
||||
import { HomeOmnichannel } from '../page-objects';
|
||||
import { OmnichannelLiveChat } from '../page-objects/omnichannel';
|
||||
import { test } from '../utils/test';
|
||||
|
||||
test.describe.serial('OC - Canned Responses Sidebar', () => {
|
||||
test.skip(!IS_EE, 'Enterprise Only');
|
||||
|
||||
let poLiveChat: OmnichannelLiveChat;
|
||||
let newVisitor: { email: string; name: string };
|
||||
|
||||
let agent: { page: Page; poHomeChannel: HomeOmnichannel };
|
||||
|
||||
const cannedResponseName = faker.string.uuid();
|
||||
|
||||
test.beforeAll(async ({ api, browser }) => {
|
||||
newVisitor = createFakeVisitor();
|
||||
|
||||
// Set user user 1 as manager and agent
|
||||
await api.post('/livechat/users/agent', { username: 'user1' });
|
||||
await api.post('/livechat/users/manager', { username: 'user1' });
|
||||
|
||||
const { page } = await createAuxContext(browser, Users.user1);
|
||||
agent = { page, poHomeChannel: new HomeOmnichannel(page) };
|
||||
});
|
||||
|
||||
test.beforeEach(async ({ page, api }) => {
|
||||
poLiveChat = new OmnichannelLiveChat(page, api);
|
||||
});
|
||||
|
||||
test.afterAll('close livechat conversation', async () => {
|
||||
await agent.poHomeChannel.quickActionsRoomToolbar.closeChat();
|
||||
});
|
||||
|
||||
test.afterAll(async ({ api }) => {
|
||||
await Promise.all([
|
||||
api.delete('/livechat/users/agent/user1'),
|
||||
api.delete('/livechat/users/manager/user1'),
|
||||
poLiveChat.page.close(),
|
||||
agent.page.close(),
|
||||
]);
|
||||
});
|
||||
|
||||
test('OC - Canned Responses Sidebar - Create', async () => {
|
||||
await test.step('expect send a message as a visitor', async () => {
|
||||
await poLiveChat.goto();
|
||||
await poLiveChat.openLiveChat();
|
||||
await poLiveChat.sendMessage(newVisitor, false);
|
||||
await poLiveChat.onlineAgentMessage.fill('this_a_test_message_from_visitor');
|
||||
await poLiveChat.btnSendMessageToOnlineAgent.click();
|
||||
});
|
||||
|
||||
await test.step('expect to have 1 omnichannel assigned to agent 1', async () => {
|
||||
await agent.poHomeChannel.navbar.openChat(newVisitor.name);
|
||||
});
|
||||
|
||||
await test.step('expect to be able to open canned responses sidebar and creation', async () => {
|
||||
await agent.poHomeChannel.roomToolbar.openCannedResponses();
|
||||
});
|
||||
|
||||
await test.step('expect to create new canned response', async () => {
|
||||
await agent.poHomeChannel.content.btnNewCannedResponse.click();
|
||||
await agent.poHomeChannel.cannedResponses.inputShortcut.fill(cannedResponseName);
|
||||
await agent.poHomeChannel.cannedResponses.inputMessage.fill(faker.lorem.paragraph());
|
||||
await agent.poHomeChannel.cannedResponses.addTag(faker.commerce.department());
|
||||
await agent.poHomeChannel.cannedResponses.radioPublic.click();
|
||||
await agent.poHomeChannel.cannedResponses.btnSave.click();
|
||||
});
|
||||
});
|
||||
|
||||
test('OC - Canned Responses Sidebar - Edit', async () => {
|
||||
await test.step('expect to have 1 omnichannel assigned to agent 1', async () => {
|
||||
await agent.poHomeChannel.navbar.openChat(newVisitor.name);
|
||||
});
|
||||
|
||||
await test.step('expect to be able to open canned responses sidebar and creation', async () => {
|
||||
await agent.poHomeChannel.roomToolbar.openCannedResponses();
|
||||
});
|
||||
|
||||
await test.step('expect to edit canned response', async () => {
|
||||
await agent.poHomeChannel.cannedResponses.listItem(cannedResponseName).click();
|
||||
await agent.poHomeChannel.cannedResponses.btnEdit.click();
|
||||
await agent.poHomeChannel.cannedResponses.radioPrivate.click();
|
||||
await agent.poHomeChannel.cannedResponses.btnSave.click();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,212 @@
|
||||
import { faker } from '@faker-js/faker';
|
||||
import type { Page } from '@playwright/test';
|
||||
|
||||
import { createFakeVisitor } from '../../mocks/data';
|
||||
import { IS_EE } from '../config/constants';
|
||||
import { createAuxContext } from '../fixtures/createAuxContext';
|
||||
import { Users } from '../fixtures/userStates';
|
||||
import { HomeOmnichannel } from '../page-objects';
|
||||
import { OmnichannelLiveChat } from '../page-objects/omnichannel';
|
||||
import { test, expect } from '../utils/test';
|
||||
|
||||
test.describe('OC - Canned Responses Usage', () => {
|
||||
test.skip(!IS_EE, 'Enterprise Only');
|
||||
|
||||
let poLiveChat: OmnichannelLiveChat;
|
||||
let newVisitor: { email: string; name: string };
|
||||
let agent: { page: Page; poHomeChannel: HomeOmnichannel };
|
||||
let cannedResponseId: string;
|
||||
let placeholderResponseId: string;
|
||||
let secondResponseId: string;
|
||||
|
||||
const cannedResponseName = `test-${faker.string.uuid()}`;
|
||||
const cannedResponseText = 'Hello! Welcome to our support chat. How can I assist you today?';
|
||||
const cannedResponseWithPlaceholder = `Hello {{contact.name}}, thank you for contacting us!`;
|
||||
const placeholderResponseName = `placeholder-${faker.string.uuid()}`;
|
||||
const secondResponseName = `followup-${faker.string.uuid()}`;
|
||||
const secondResponseText = 'Is there anything else I can help you with today?';
|
||||
|
||||
test.beforeAll(async ({ api, browser }) => {
|
||||
await Promise.all([
|
||||
api.post('/livechat/users/agent', { username: 'user1' }),
|
||||
api.post('/livechat/users/manager', { username: 'user1' }),
|
||||
api.post('/canned-responses', {
|
||||
shortcut: cannedResponseName,
|
||||
text: cannedResponseText,
|
||||
scope: 'global',
|
||||
tags: ['tag'],
|
||||
}),
|
||||
api.post('/canned-responses', {
|
||||
shortcut: placeholderResponseName,
|
||||
text: cannedResponseWithPlaceholder,
|
||||
scope: 'global',
|
||||
tags: ['tag'],
|
||||
}),
|
||||
api.post('/canned-responses', {
|
||||
shortcut: secondResponseName,
|
||||
text: secondResponseText,
|
||||
scope: 'global',
|
||||
tags: ['tag'],
|
||||
}),
|
||||
]);
|
||||
|
||||
const { page } = await createAuxContext(browser, Users.user1);
|
||||
agent = { page, poHomeChannel: new HomeOmnichannel(page) };
|
||||
|
||||
const [mainResponse, placeholderResponse, secondResponse] = await Promise.all([
|
||||
api.get('/canned-responses', { shortcut: cannedResponseName }),
|
||||
api.get('/canned-responses', { shortcut: placeholderResponseName }),
|
||||
api.get('/canned-responses', { shortcut: secondResponseName }),
|
||||
]);
|
||||
|
||||
const [mainData, placeholderData, secondData] = await Promise.all([
|
||||
mainResponse.json(),
|
||||
placeholderResponse.json(),
|
||||
secondResponse.json(),
|
||||
]);
|
||||
|
||||
cannedResponseId = mainData.cannedResponses[0]._id;
|
||||
placeholderResponseId = placeholderData.cannedResponses[0]._id;
|
||||
secondResponseId = secondData.cannedResponses[0]._id;
|
||||
});
|
||||
|
||||
test.beforeEach(async ({ page, api }) => {
|
||||
newVisitor = createFakeVisitor();
|
||||
poLiveChat = new OmnichannelLiveChat(page, api);
|
||||
});
|
||||
|
||||
test.afterEach('close livechat conversation', async () => {
|
||||
await poLiveChat.closeChat();
|
||||
});
|
||||
|
||||
test.afterAll(async ({ api }) => {
|
||||
await Promise.all([
|
||||
api.delete('/livechat/users/agent/user1'),
|
||||
api.delete('/livechat/users/manager/user1'),
|
||||
api.delete('/canned-responses', { _id: cannedResponseId }),
|
||||
api.delete('/canned-responses', { _id: placeholderResponseId }),
|
||||
api.delete('/canned-responses', { _id: secondResponseId }),
|
||||
agent.poHomeChannel.page.close(),
|
||||
]);
|
||||
});
|
||||
|
||||
test('OC - Canned Responses Usage - Create response and use in chat', async () => {
|
||||
await test.step('expect to start a visitor conversation', async () => {
|
||||
await poLiveChat.goto();
|
||||
await poLiveChat.openLiveChat();
|
||||
await poLiveChat.sendMessage(newVisitor, false);
|
||||
await poLiveChat.onlineAgentMessage.fill('this_a_test_message_from_visitor');
|
||||
await poLiveChat.btnSendMessageToOnlineAgent.click();
|
||||
});
|
||||
|
||||
await test.step('expect agent to receive and open the chat', async () => {
|
||||
await agent.poHomeChannel.navbar.openChat(newVisitor.name);
|
||||
});
|
||||
|
||||
await test.step('expect to use the canned response in the chat', async () => {
|
||||
await agent.poHomeChannel.content.selectCannedResponse(cannedResponseName);
|
||||
});
|
||||
|
||||
await test.step('expect canned response text to appear in message composer', async () => {
|
||||
await expect(agent.poHomeChannel.composer.inputMessage).toHaveValue(`${cannedResponseText} `);
|
||||
});
|
||||
|
||||
await test.step('expect agent to be able to send the canned response message', async () => {
|
||||
await agent.poHomeChannel.content.sendMessage(cannedResponseText);
|
||||
});
|
||||
|
||||
await test.step('expect visitor to receive the canned response message', async () => {
|
||||
await expect(poLiveChat.txtChatMessage(cannedResponseText)).toBeVisible();
|
||||
});
|
||||
});
|
||||
|
||||
test('OC - Canned Responses Usage - Use response with placeholder replacement', async () => {
|
||||
await test.step('expect to start a new visitor conversation', async () => {
|
||||
await poLiveChat.goto();
|
||||
await poLiveChat.openLiveChat();
|
||||
await poLiveChat.sendMessage(newVisitor, false);
|
||||
await poLiveChat.onlineAgentMessage.fill('test_message_for_placeholder');
|
||||
await poLiveChat.btnSendMessageToOnlineAgent.click();
|
||||
});
|
||||
|
||||
await test.step('expect agent to receive and open the chat', async () => {
|
||||
await agent.poHomeChannel.navbar.openChat(newVisitor.name);
|
||||
});
|
||||
|
||||
await test.step('expect to use the canned response with placeholder', async () => {
|
||||
await agent.poHomeChannel.content.selectCannedResponse(placeholderResponseName);
|
||||
});
|
||||
|
||||
await test.step('expect placeholder to be replaced with actual visitor name', async () => {
|
||||
await agent.poHomeChannel.content.sendMessage(cannedResponseWithPlaceholder);
|
||||
await expect(poLiveChat.txtChatMessage('{{contact.name}}')).not.toBeVisible();
|
||||
});
|
||||
});
|
||||
|
||||
test('OC - Canned Responses Usage - Modify response before sending', async () => {
|
||||
const modifiedText = `Additionally, I'll be happy to help you with any specific questions.`;
|
||||
|
||||
await test.step('expect to start a visitor conversation', async () => {
|
||||
await poLiveChat.goto();
|
||||
await poLiveChat.openLiveChat();
|
||||
await poLiveChat.sendMessage(newVisitor, false);
|
||||
await poLiveChat.onlineAgentMessage.fill('test_message_for_modification');
|
||||
await poLiveChat.btnSendMessageToOnlineAgent.click();
|
||||
});
|
||||
|
||||
await test.step('expect agent to open the chat', async () => {
|
||||
await agent.poHomeChannel.navbar.openChat(newVisitor.name);
|
||||
});
|
||||
|
||||
await test.step('expect to use existing canned response and modify it', async () => {
|
||||
await agent.poHomeChannel.content.selectCannedResponse(cannedResponseName);
|
||||
});
|
||||
|
||||
await test.step('expect to modify the canned response text before sending', async () => {
|
||||
await agent.poHomeChannel.composer.inputMessage.click();
|
||||
await agent.page.keyboard.press('End');
|
||||
await agent.poHomeChannel.composer.inputMessage.pressSequentially(modifiedText);
|
||||
|
||||
await expect(agent.poHomeChannel.composer.inputMessage).toHaveValue(`${cannedResponseText} ${modifiedText}`);
|
||||
});
|
||||
|
||||
await test.step('expect to send the modified message', async () => {
|
||||
await agent.page.keyboard.press('Enter');
|
||||
});
|
||||
|
||||
await test.step('expect visitor to receive the modified message', async () => {
|
||||
await expect(poLiveChat.txtChatMessage(`${cannedResponseText} ${modifiedText}`)).toBeVisible();
|
||||
});
|
||||
});
|
||||
|
||||
test('OC - Canned Responses Usage - Use multiple responses in sequence', async () => {
|
||||
await test.step('expect to start a visitor conversation', async () => {
|
||||
await poLiveChat.goto();
|
||||
await poLiveChat.openLiveChat();
|
||||
await poLiveChat.sendMessage(newVisitor, false);
|
||||
await poLiveChat.onlineAgentMessage.fill('test_message_for_sequence');
|
||||
await poLiveChat.btnSendMessageToOnlineAgent.click();
|
||||
});
|
||||
|
||||
await test.step('expect agent to open the chat', async () => {
|
||||
await agent.poHomeChannel.navbar.openChat(newVisitor.name);
|
||||
});
|
||||
|
||||
await test.step('expect to use first canned response', async () => {
|
||||
await agent.poHomeChannel.content.selectCannedResponse(cannedResponseName);
|
||||
await expect(agent.poHomeChannel.composer.inputMessage).toHaveValue(`${cannedResponseText} `);
|
||||
await agent.page.keyboard.press('Enter');
|
||||
});
|
||||
|
||||
await test.step('expect to use second canned response', async () => {
|
||||
await agent.poHomeChannel.content.selectCannedResponse(secondResponseName);
|
||||
await expect(agent.poHomeChannel.composer.inputMessage).toHaveValue(`${secondResponseText} `);
|
||||
await agent.page.keyboard.press('Enter');
|
||||
});
|
||||
|
||||
await test.step('expect visitor to receive both messages in correct order', async () => {
|
||||
await expect(poLiveChat.txtChatMessage(cannedResponseText)).toBeVisible();
|
||||
await expect(poLiveChat.txtChatMessage(secondResponseText)).toBeVisible();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,106 @@
|
||||
import type { Page } from '@playwright/test';
|
||||
|
||||
import { createFakeVisitor } from '../../mocks/data';
|
||||
import { ADMIN_CREDENTIALS, IS_EE } from '../config/constants';
|
||||
import { createAuxContext } from '../fixtures/createAuxContext';
|
||||
import { Users } from '../fixtures/userStates';
|
||||
import { HomeChannel } from '../page-objects';
|
||||
import { OmnichannelLiveChat } from '../page-objects/omnichannel';
|
||||
import { getPriorityByi18nLabel } from '../utils/omnichannel/priority';
|
||||
import { createSLA } from '../utils/omnichannel/sla';
|
||||
import { test, expect } from '../utils/test';
|
||||
|
||||
const getRoomId = (page: Page): string => {
|
||||
// url is of the form: http://localhost:3000/live/:rid/room-info
|
||||
const url = page?.url();
|
||||
// rid comes after /live/ and before /room-info (or /)
|
||||
const rid = url?.split('/live/')[1].split('/')[0];
|
||||
if (!rid) {
|
||||
throw new Error(`Could not get room id from url: ${page.url()}`);
|
||||
}
|
||||
return rid;
|
||||
};
|
||||
|
||||
test.describe.serial('omnichannel-changing-room-priority-and-sla', () => {
|
||||
test.skip(!IS_EE, 'Enterprise Only');
|
||||
|
||||
let poLiveChat: OmnichannelLiveChat;
|
||||
let newVisitor: { email: string; name: string };
|
||||
|
||||
let agent: { page: Page; poHomeChannel: HomeChannel };
|
||||
|
||||
test.beforeAll(async ({ api, browser }) => {
|
||||
let statusCode = (await api.post('/livechat/users/agent', { username: ADMIN_CREDENTIALS.username })).status();
|
||||
expect(statusCode).toBe(200);
|
||||
|
||||
statusCode = (await api.post('/livechat/users/manager', { username: ADMIN_CREDENTIALS.username })).status();
|
||||
expect(statusCode).toBe(200);
|
||||
|
||||
statusCode = (await api.post('/livechat/agent.status', { status: 'available' })).status();
|
||||
expect(statusCode).toBe(200);
|
||||
|
||||
statusCode = (await api.post('/settings/Livechat_Routing_Method', { value: 'Manual_Selection' })).status();
|
||||
expect(statusCode).toBe(200);
|
||||
|
||||
const { page } = await createAuxContext(browser, Users.admin);
|
||||
agent = { page, poHomeChannel: new HomeChannel(page) };
|
||||
|
||||
await agent.poHomeChannel.navbar.changeUserStatus('online');
|
||||
});
|
||||
|
||||
test.afterAll(async ({ api }) => {
|
||||
await agent.page.close();
|
||||
|
||||
await Promise.all([
|
||||
api.delete(`/livechat/users/agent/${ADMIN_CREDENTIALS.username}`),
|
||||
api.delete(`/livechat/users/manager/${ADMIN_CREDENTIALS.username}`),
|
||||
api.post('/settings/Livechat_Routing_Method', { value: 'Auto_Selection' }),
|
||||
]);
|
||||
});
|
||||
|
||||
test('expect to initiate a new livechat conversation', async ({ page, api }) => {
|
||||
newVisitor = createFakeVisitor();
|
||||
poLiveChat = new OmnichannelLiveChat(page, api);
|
||||
await poLiveChat.goto();
|
||||
await poLiveChat.openLiveChat();
|
||||
await poLiveChat.sendMessage(newVisitor, false);
|
||||
await poLiveChat.onlineAgentMessage.type('this_a_test_message_from_user');
|
||||
await poLiveChat.btnSendMessageToOnlineAgent.click();
|
||||
|
||||
await agent.poHomeChannel.sidebar.getSidebarItemByName(newVisitor.name).click();
|
||||
});
|
||||
|
||||
test('expect to change priority of room and corresponding system message should be displayed', async ({ api }) => {
|
||||
const priority = await getPriorityByi18nLabel(api, 'High');
|
||||
|
||||
await test.step('change priority of room to the new priority', async () => {
|
||||
const status = (await api.post(`/livechat/room/${getRoomId(agent.page)}/priority`, { priorityId: priority._id })).status();
|
||||
await expect(status).toBe(200);
|
||||
|
||||
await agent.page.waitForTimeout(1000);
|
||||
});
|
||||
|
||||
await expect(agent.poHomeChannel.content.lastSystemMessageBody).toHaveText(
|
||||
`Priority changed: ${ADMIN_CREDENTIALS.username} changed the priority to ${priority.name || priority.i18n}`,
|
||||
);
|
||||
});
|
||||
|
||||
test('expect to change SLA of room and corresponding system message should be displayed', async ({ api }) => {
|
||||
const sla = await createSLA(api);
|
||||
|
||||
await test.step('change SLA of room to the new SLA', async () => {
|
||||
const status = (await api.put(`/livechat/inquiry.setSLA`, { sla: sla.name, roomId: getRoomId(agent.page) })).status();
|
||||
expect(status).toBe(200);
|
||||
await agent.page.waitForTimeout(1000);
|
||||
});
|
||||
|
||||
await expect(agent.poHomeChannel.content.lastSystemMessageBody).toHaveText(
|
||||
`SLA Policy changed: ${ADMIN_CREDENTIALS.username} changed the SLA Policy to ${sla.name}`,
|
||||
);
|
||||
|
||||
await test.step('cleanup SLA', async () => {
|
||||
const status = (await api.delete(`/livechat/sla/${sla._id}`)).status();
|
||||
expect(status).toBe(200);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,98 @@
|
||||
import type { Page } from '@playwright/test';
|
||||
|
||||
import { createFakeVisitor } from '../../mocks/data';
|
||||
import { createAuxContext } from '../fixtures/createAuxContext';
|
||||
import { Users } from '../fixtures/userStates';
|
||||
import { HomeOmnichannel } from '../page-objects';
|
||||
import { OmnichannelLiveChat } from '../page-objects/omnichannel';
|
||||
import { test, expect } from '../utils/test';
|
||||
|
||||
test.describe('Omnichannel chat history', () => {
|
||||
let poLiveChat: OmnichannelLiveChat;
|
||||
let newVisitor: { email: string; name: string };
|
||||
|
||||
let agent: { page: Page; poHomeOmnichannel: HomeOmnichannel };
|
||||
|
||||
test.beforeAll(async ({ api, browser }) => {
|
||||
newVisitor = createFakeVisitor();
|
||||
|
||||
// Set user user 1 as manager and agent
|
||||
await api.post('/livechat/users/agent', { username: 'user1' });
|
||||
await api.post('/livechat/users/manager', { username: 'user1' });
|
||||
|
||||
const { page } = await createAuxContext(browser, Users.user1);
|
||||
agent = { page, poHomeOmnichannel: new HomeOmnichannel(page) };
|
||||
});
|
||||
|
||||
test.beforeEach(async ({ page, api }) => {
|
||||
poLiveChat = new OmnichannelLiveChat(page, api);
|
||||
});
|
||||
|
||||
test.afterAll(async ({ api }) => {
|
||||
await api.delete('/livechat/users/agent/user1');
|
||||
await api.delete('/livechat/users/manager/user1');
|
||||
await agent.page.close();
|
||||
|
||||
await api.post('/permissions.update', { permissions: [{ _id: 'preview-c-room', roles: ['admin', 'owner', 'moderator', 'user'] }] });
|
||||
});
|
||||
|
||||
test('Receiving a message from visitor', async ({ api }) => {
|
||||
await test.step('Expect send a message as a visitor', async () => {
|
||||
await poLiveChat.goto();
|
||||
await poLiveChat.openLiveChat();
|
||||
await poLiveChat.sendMessage(newVisitor, false);
|
||||
await poLiveChat.onlineAgentMessage.type('this_a_test_message_from_visitor');
|
||||
await poLiveChat.btnSendMessageToOnlineAgent.click();
|
||||
});
|
||||
|
||||
await test.step('Expect to have 1 omnichannel assigned to agent 1', async () => {
|
||||
await agent.poHomeOmnichannel.navbar.openChat(newVisitor.name);
|
||||
});
|
||||
|
||||
await test.step('expect to be able to edit room info', async () => {
|
||||
await agent.poHomeOmnichannel.roomInfo.btnEdit.click();
|
||||
await agent.poHomeOmnichannel.editRoomInfo.inputTopic.fill('any_topic');
|
||||
await agent.poHomeOmnichannel.editRoomInfo.btnSave.click();
|
||||
|
||||
await expect(agent.poHomeOmnichannel.roomInfo.root).toContainText('any_topic');
|
||||
});
|
||||
|
||||
await test.step('Expect to be able to close an omnichannel to conversation', async () => {
|
||||
await agent.poHomeOmnichannel.quickActionsRoomToolbar.closeChat();
|
||||
});
|
||||
|
||||
await test.step('Expect send a message as a visitor again to reopen chat', async () => {
|
||||
await poLiveChat.goto();
|
||||
await poLiveChat.openLiveChat();
|
||||
await poLiveChat.onlineAgentMessage.type('this_a_test_message_from_visitor');
|
||||
await poLiveChat.btnSendMessageToOnlineAgent.click();
|
||||
});
|
||||
|
||||
await test.step('Expect to have 1 omnichannel assigned to agent 1', async () => {
|
||||
await agent.poHomeOmnichannel.navbar.openChat(newVisitor.name);
|
||||
});
|
||||
|
||||
await test.step('Expect to be able to see conversation history', async () => {
|
||||
await agent.poHomeOmnichannel.btnContactInfo.click();
|
||||
await agent.poHomeOmnichannel.contacts.contactInfo.tabHistory.click();
|
||||
await expect(agent.poHomeOmnichannel.contacts.contactInfo.historyItem).toBeVisible();
|
||||
|
||||
await agent.poHomeOmnichannel.contacts.contactInfo.historyItem.click();
|
||||
await expect(agent.poHomeOmnichannel.contacts.contactInfo.historyMessage).toBeVisible();
|
||||
});
|
||||
|
||||
await api.post('/permissions.update', { permissions: [{ _id: 'preview-c-room', roles: [] }] });
|
||||
|
||||
await test.step('Expect agent to see conversation history, but not join room', async () => {
|
||||
await agent.page.reload();
|
||||
|
||||
await agent.poHomeOmnichannel.contacts.contactInfo.historyItem.click();
|
||||
await agent.poHomeOmnichannel.contacts.contactInfo.historyMessage.click();
|
||||
await agent.poHomeOmnichannel.contacts.contactInfo.btnOpenChat.click();
|
||||
|
||||
// Should not show the NoSubscribedRoom.tsx component on livechat rooms
|
||||
await expect(agent.page.locator('div >> text=This conversation is already closed.')).toBeVisible();
|
||||
await expect(agent.page.locator('div >> text="this_a_test_message_from_visitor"')).toBeVisible();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,512 @@
|
||||
import type { Page } from '@playwright/test';
|
||||
|
||||
import { IS_EE } from '../config/constants';
|
||||
import { createAuxContext } from '../fixtures/createAuxContext';
|
||||
import { Users } from '../fixtures/userStates';
|
||||
import { HomeOmnichannel } from '../page-objects';
|
||||
import { setSettingValueById } from '../utils';
|
||||
import { createAgent, makeAgentAvailable } from '../utils/omnichannel/agents';
|
||||
import { addAgentToDepartment, createDepartment } from '../utils/omnichannel/departments';
|
||||
import { createManager } from '../utils/omnichannel/managers';
|
||||
import { createMonitor } from '../utils/omnichannel/monitors';
|
||||
import { createConversation } from '../utils/omnichannel/rooms';
|
||||
import { createOrUpdateUnit } from '../utils/omnichannel/units';
|
||||
import { expect, test } from '../utils/test';
|
||||
|
||||
const wrapSession = async ({ page }: { page: Page }) => ({ page, poHomeOmnichannel: new HomeOmnichannel(page) });
|
||||
|
||||
test.use({ storageState: Users.user3.state });
|
||||
|
||||
test.skip(!IS_EE, 'Enterprise Edition Only');
|
||||
|
||||
test.describe('OC - Chat transfers [Monitor role]', () => {
|
||||
let departments: Awaited<ReturnType<typeof createDepartment>>[];
|
||||
let conversations: Awaited<ReturnType<typeof createConversation>>[];
|
||||
let agents: Awaited<ReturnType<typeof createAgent>>[];
|
||||
let monitors: Awaited<ReturnType<typeof createMonitor>>[];
|
||||
let units: Awaited<ReturnType<typeof createOrUpdateUnit>>[];
|
||||
let sessions: { page: Page; poHomeOmnichannel: HomeOmnichannel }[] = [];
|
||||
|
||||
let poOmnichannel: HomeOmnichannel;
|
||||
|
||||
// Create agents
|
||||
test.beforeAll(async ({ api }) => {
|
||||
agents = await Promise.all([createAgent(api, 'user1'), createAgent(api, 'user2'), createAgent(api, 'rocketchat.internal.admin.test')]);
|
||||
|
||||
(await Promise.all(agents.map(({ data: agent }) => makeAgentAvailable(api, agent._id)))).forEach((res) => {
|
||||
expect(res.status()).toBe(200);
|
||||
});
|
||||
});
|
||||
|
||||
// Create departments
|
||||
test.beforeAll(async ({ api }) => {
|
||||
departments = await Promise.all([createDepartment(api), createDepartment(api)]);
|
||||
});
|
||||
|
||||
// Add agents to departments
|
||||
test.beforeAll(async ({ api }) => {
|
||||
const [departmentA, departmentB] = departments.map(({ data }) => data);
|
||||
|
||||
const promises = await Promise.all([
|
||||
addAgentToDepartment(api, { department: departmentA, agentId: 'user1' }),
|
||||
addAgentToDepartment(api, { department: departmentA, agentId: 'rocketchat.internal.admin.test' }),
|
||||
addAgentToDepartment(api, { department: departmentB, agentId: 'user2' }),
|
||||
]);
|
||||
|
||||
promises.forEach((res) => expect(res.status()).toBe(200));
|
||||
});
|
||||
|
||||
// Create conversations
|
||||
test.beforeAll(async ({ api }) => {
|
||||
const [departmentA] = departments.map(({ data }) => data);
|
||||
|
||||
conversations = await Promise.all([
|
||||
createConversation(api, {
|
||||
agentId: `user1`,
|
||||
departmentId: departmentA._id,
|
||||
}),
|
||||
createConversation(api, {
|
||||
agentId: `user1`,
|
||||
departmentId: departmentA._id,
|
||||
}),
|
||||
createConversation(api, {
|
||||
agentId: `user1`,
|
||||
departmentId: departmentA._id,
|
||||
}),
|
||||
]);
|
||||
});
|
||||
|
||||
// Create monitors
|
||||
test.beforeAll(async ({ api }) => {
|
||||
monitors = await Promise.all([createMonitor(api, 'user3')]);
|
||||
});
|
||||
|
||||
// Create units
|
||||
test.beforeAll(async ({ api }) => {
|
||||
const [departmentA, departmentB] = departments.map(({ data }) => data);
|
||||
|
||||
units = await Promise.all([
|
||||
createOrUpdateUnit(api, {
|
||||
monitors: [{ monitorId: 'user3', username: 'user3' }],
|
||||
departments: [{ departmentId: departmentA._id }],
|
||||
}),
|
||||
createOrUpdateUnit(api, {
|
||||
monitors: [{ monitorId: 'rocketchat.internal.admin.test', username: 'rocketchat.internal.admin.test' }],
|
||||
departments: [{ departmentId: departmentB._id }],
|
||||
}),
|
||||
]);
|
||||
expect((await setSettingValueById(api, 'Omnichannel_enable_department_removal', true)).status()).toBe(200);
|
||||
});
|
||||
|
||||
// Create sessions
|
||||
test.beforeEach(async ({ browser }) => {
|
||||
sessions = [];
|
||||
for (const user of [Users.user1, Users.user2, Users.admin]) {
|
||||
sessions.push(await createAuxContext(browser, user).then(wrapSession));
|
||||
}
|
||||
});
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
poOmnichannel = new HomeOmnichannel(page);
|
||||
|
||||
await poOmnichannel.chats.goto();
|
||||
});
|
||||
|
||||
// Close sessions
|
||||
test.afterEach(async () => {
|
||||
await Promise.all(sessions.map(({ page }) => page.close()));
|
||||
sessions = [];
|
||||
});
|
||||
|
||||
test.afterAll(async ({ api }) => {
|
||||
await Promise.all([
|
||||
...conversations.map((conversation) => conversation.delete()),
|
||||
...monitors.map((monitor) => monitor.delete()),
|
||||
...agents.map((agent) => agent.delete()),
|
||||
...units.map((unit) => unit.delete()),
|
||||
...departments.map((department) => department.delete()),
|
||||
]);
|
||||
await setSettingValueById(api, 'Omnichannel_enable_department_removal', false);
|
||||
});
|
||||
|
||||
test(`OC - Chat transfers [Monitor role] - Transfer to department with no online agents should fail`, async ({ api }) => {
|
||||
const [roomA] = conversations.map(({ data }) => data.room);
|
||||
const [, agentB] = sessions;
|
||||
|
||||
const emptyDepartment = await createDepartment(api);
|
||||
|
||||
await test.step('expect to open forward chat modal', async () => {
|
||||
await poOmnichannel.chats.openChat(roomA.fname);
|
||||
await poOmnichannel.quickActionsRoomToolbar.forwardChat();
|
||||
});
|
||||
|
||||
await test.step('expect transfer to department with no online agents to fail', async () => {
|
||||
await poOmnichannel.content.forwardChatModal.selectDepartment(emptyDepartment.data.name);
|
||||
await poOmnichannel.content.forwardChatModal.inputComment.type('transfer_attempt');
|
||||
await expect(poOmnichannel.content.forwardChatModal.btnForward).toBeEnabled();
|
||||
await poOmnichannel.content.forwardChatModal.btnForward.click();
|
||||
await poOmnichannel.toastMessage.waitForDisplay({ type: 'error' });
|
||||
});
|
||||
|
||||
await test.step('expect conversation to remain with original agent', async () => {
|
||||
await expect(agentB.poHomeOmnichannel.sidebar.getSidebarItemByName(roomA.fname)).not.toBeVisible();
|
||||
});
|
||||
|
||||
await emptyDepartment.delete();
|
||||
});
|
||||
|
||||
test(`OC - Chat transfers [Monitor role] - Transfer to another department`, async () => {
|
||||
const [, departmentB] = departments.map(({ data }) => data);
|
||||
const [roomA] = conversations.map(({ data }) => data.room);
|
||||
const [agentA, agentB] = sessions;
|
||||
|
||||
await test.step('expect room a to bot be visible for user2', async () => {
|
||||
await expect(agentB.poHomeOmnichannel.sidebar.getSidebarItemByName(roomA.fname)).not.toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('expect to be able to join chats from same unit', async () => {
|
||||
await poOmnichannel.chats.openChat(roomA.fname);
|
||||
await poOmnichannel.quickActionsRoomToolbar.forwardChat();
|
||||
});
|
||||
|
||||
await test.step('expect agent and department fields to be visible and enabled', async () => {
|
||||
await expect(poOmnichannel.content.forwardChatModal.inputForwardUser).toBeEnabled();
|
||||
await expect(poOmnichannel.content.forwardChatModal.inputForwardDepartment).toBeEnabled();
|
||||
await expect(poOmnichannel.content.forwardChatModal.btnForward).toBeDisabled();
|
||||
});
|
||||
|
||||
await test.step('expect to transfer from dep a to dep b', async () => {
|
||||
await poOmnichannel.content.forwardChatModal.selectDepartment(departmentB.name);
|
||||
await poOmnichannel.content.forwardChatModal.inputComment.type('any_comment');
|
||||
await expect(poOmnichannel.content.forwardChatModal.btnForward).toBeEnabled();
|
||||
await poOmnichannel.content.forwardChatModal.btnForward.click();
|
||||
await poOmnichannel.content.forwardChatModal.waitForDismissal();
|
||||
// await expect(agentA.poHomeOmnichannel.toastSuccess).toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('expect conversation to have been assigned to user 2', async () => {
|
||||
await expect(agentA.page).toHaveURL(`/home`);
|
||||
await expect(agentA.poHomeOmnichannel.sidebar.getSidebarItemByName(roomA.fname)).not.toBeVisible();
|
||||
await expect(agentB.poHomeOmnichannel.sidebar.getSidebarItemByName(roomA.fname)).toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('expect user 1 to have left the conversation', async () => {
|
||||
await agentB.poHomeOmnichannel.sidebar.getSidebarItemByName(roomA.fname).click();
|
||||
await agentB.poHomeOmnichannel.content.findSystemMessage(
|
||||
`Transfer: user3 transferred the chat to the department ${departmentB.name}}`,
|
||||
);
|
||||
await agentB.poHomeOmnichannel.content.findSystemMessage('left the channel');
|
||||
});
|
||||
});
|
||||
|
||||
test(`OC - Chat transfers [Monitor role] - Transfer to another agent, different department`, async () => {
|
||||
const [, roomB] = conversations.map(({ data }) => data.room);
|
||||
const [agentA, agentB] = sessions;
|
||||
|
||||
await test.step('expect room a to bot be visible for user2', async () => {
|
||||
await expect(agentB.poHomeOmnichannel.sidebar.getSidebarItemByName(roomB.fname)).not.toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('expect to be able to join chats from same unit', async () => {
|
||||
await poOmnichannel.chats.openChat(roomB.fname);
|
||||
await poOmnichannel.quickActionsRoomToolbar.forwardChat();
|
||||
});
|
||||
|
||||
await test.step('expect agent and department fields to be visible and enabled', async () => {
|
||||
await expect(poOmnichannel.content.forwardChatModal.inputForwardUser).toBeEnabled();
|
||||
await expect(poOmnichannel.content.forwardChatModal.inputForwardDepartment).toBeEnabled();
|
||||
await expect(poOmnichannel.content.forwardChatModal.btnForward).toBeDisabled();
|
||||
});
|
||||
|
||||
await test.step('expect to transfer from user1 to user2', async () => {
|
||||
await poOmnichannel.content.forwardChatModal.selectUser(`user2`);
|
||||
await poOmnichannel.content.forwardChatModal.inputComment.type('any_comment');
|
||||
await expect(poOmnichannel.content.forwardChatModal.btnForward).toBeEnabled();
|
||||
await poOmnichannel.content.forwardChatModal.btnForward.click();
|
||||
// await expect(agentA.poHomeOmnichannel.toastSuccess).toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('expect conversation to have been assigned to user 2', async () => {
|
||||
await expect(agentA.page).toHaveURL(`/home`);
|
||||
await expect(agentA.poHomeOmnichannel.sidebar.getSidebarItemByName(roomB.fname)).not.toBeVisible();
|
||||
await expect(agentB.poHomeOmnichannel.sidebar.getSidebarItemByName(roomB.fname)).toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('expect user 1 to have left the conversation', async () => {
|
||||
await agentB.poHomeOmnichannel.sidebar.getSidebarItemByName(roomB.fname).click();
|
||||
await expect(
|
||||
agentB.poHomeOmnichannel.content.findSystemMessage(
|
||||
`New Chat Transfer: user3 transferred the chat to user2 with a comment: any_comment`,
|
||||
),
|
||||
).toBeVisible();
|
||||
await expect(agentB.poHomeOmnichannel.content.findSystemMessage('left the channel')).toBeVisible();
|
||||
});
|
||||
});
|
||||
|
||||
test(`OC - Chat transfers [Monitor role] - Transfer to another agent, same department`, async () => {
|
||||
const [, , roomC] = conversations.map(({ data }) => data.room);
|
||||
const [agentA, , agentC] = sessions;
|
||||
|
||||
await test.step('expect room a to bot be visible for user2', async () => {
|
||||
await expect(agentC.poHomeOmnichannel.sidebar.getSidebarItemByName(roomC.fname)).not.toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('expect to be able to join chats from same unit', async () => {
|
||||
await poOmnichannel.chats.openChat(roomC.fname);
|
||||
await poOmnichannel.quickActionsRoomToolbar.forwardChat();
|
||||
});
|
||||
|
||||
await test.step('expect agent and department fields to be visible and enabled', async () => {
|
||||
await expect(poOmnichannel.content.forwardChatModal.inputForwardUser).toBeEnabled();
|
||||
await expect(poOmnichannel.content.forwardChatModal.inputForwardDepartment).toBeEnabled();
|
||||
await expect(poOmnichannel.content.forwardChatModal.btnForward).toBeDisabled();
|
||||
});
|
||||
|
||||
await test.step('expect to transfer from dep a to dep b', async () => {
|
||||
await poOmnichannel.content.forwardChatModal.selectUser('rocketchat.internal.admin.test');
|
||||
await poOmnichannel.content.forwardChatModal.inputComment.type('any_comment');
|
||||
await expect(poOmnichannel.content.forwardChatModal.btnForward).toBeEnabled();
|
||||
await poOmnichannel.content.forwardChatModal.btnForward.click();
|
||||
// await expect(agentA.poHomeOmnichannel.toastSuccess).toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('expect conversation to have been assigned to user 2', async () => {
|
||||
await expect(agentA.page).toHaveURL(`/home`);
|
||||
await expect(agentA.poHomeOmnichannel.sidebar.getSidebarItemByName(roomC.fname)).not.toBeVisible();
|
||||
await expect(agentC.poHomeOmnichannel.sidebar.getSidebarItemByName(roomC.fname)).toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('expect user 1 to have left the conversation', async () => {
|
||||
await agentC.poHomeOmnichannel.sidebar.getSidebarItemByName(roomC.fname).click();
|
||||
await expect(
|
||||
agentC.poHomeOmnichannel.content.findSystemMessage(
|
||||
`New Chat Transfer: user3 transferred the chat to RocketChat Internal Admin Test with a comment: any_comment`,
|
||||
),
|
||||
).toBeVisible();
|
||||
await expect(agentC.poHomeOmnichannel.content.findSystemMessage('left the channel')).toBeVisible();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('OC - Chat transfers [Manager role]', () => {
|
||||
let departments: Awaited<ReturnType<typeof createDepartment>>[];
|
||||
let conversations: Awaited<ReturnType<typeof createConversation>>[];
|
||||
let agents: Awaited<ReturnType<typeof createAgent>>[];
|
||||
let managers: Awaited<ReturnType<typeof createManager>>[];
|
||||
let sessions: { page: Page; poHomeOmnichannel: HomeOmnichannel }[];
|
||||
|
||||
let poOmnichannel: HomeOmnichannel;
|
||||
|
||||
// Create agents
|
||||
test.beforeAll(async ({ api }) => {
|
||||
agents = await Promise.all([createAgent(api, 'user1'), createAgent(api, 'user2'), createAgent(api, 'rocketchat.internal.admin.test')]);
|
||||
|
||||
(await Promise.all(agents.map(({ data: agent }) => makeAgentAvailable(api, agent._id)))).forEach((res) => {
|
||||
expect(res.status()).toBe(200);
|
||||
});
|
||||
});
|
||||
|
||||
// Create managers
|
||||
test.beforeAll(async ({ api }) => {
|
||||
managers = await Promise.all([createManager(api, 'user3')]);
|
||||
});
|
||||
|
||||
// Create departments
|
||||
test.beforeAll(async ({ api }) => {
|
||||
departments = await Promise.all([createDepartment(api), createDepartment(api)]);
|
||||
});
|
||||
|
||||
// Add agents to departments
|
||||
test.beforeAll(async ({ api }) => {
|
||||
const [departmentA, departmentB] = departments.map(({ data }) => data);
|
||||
|
||||
const promises = await Promise.all([
|
||||
addAgentToDepartment(api, { department: departmentA, agentId: 'user1' }),
|
||||
addAgentToDepartment(api, { department: departmentA, agentId: 'rocketchat.internal.admin.test' }),
|
||||
addAgentToDepartment(api, { department: departmentB, agentId: 'user2' }),
|
||||
]);
|
||||
|
||||
promises.forEach((res) => expect(res.status()).toBe(200));
|
||||
});
|
||||
|
||||
// Create conversations
|
||||
test.beforeAll(async ({ api }) => {
|
||||
const [departmentA] = departments.map(({ data }) => data);
|
||||
|
||||
conversations = await Promise.all([
|
||||
createConversation(api, {
|
||||
agentId: `user1`,
|
||||
departmentId: departmentA._id,
|
||||
}),
|
||||
createConversation(api, {
|
||||
agentId: `user1`,
|
||||
departmentId: departmentA._id,
|
||||
}),
|
||||
createConversation(api, {
|
||||
agentId: `user1`,
|
||||
departmentId: departmentA._id,
|
||||
}),
|
||||
]);
|
||||
});
|
||||
|
||||
// Create sessions
|
||||
test.beforeEach(async ({ browser }) => {
|
||||
sessions = await Promise.all([
|
||||
createAuxContext(browser, Users.user1).then(wrapSession),
|
||||
createAuxContext(browser, Users.user2).then(wrapSession),
|
||||
createAuxContext(browser, Users.admin).then(wrapSession),
|
||||
]);
|
||||
});
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
poOmnichannel = new HomeOmnichannel(page);
|
||||
|
||||
await poOmnichannel.chats.goto();
|
||||
});
|
||||
|
||||
// Close sessions
|
||||
test.afterEach(async () => {
|
||||
await Promise.all(sessions.map(({ page }) => page.close()));
|
||||
});
|
||||
|
||||
test.afterAll(async () => {
|
||||
await Promise.all([
|
||||
...conversations.map((conversation) => conversation.delete()),
|
||||
...managers.map((manager) => manager.delete()),
|
||||
...agents.map((agent) => agent.delete()),
|
||||
...departments.map((department) => department.delete()),
|
||||
]);
|
||||
});
|
||||
|
||||
test(`OC - Chat transfers [Manager role] - Transfer to another department`, async () => {
|
||||
const [, departmentB] = departments.map(({ data }) => data);
|
||||
const [roomA] = conversations.map(({ data }) => data.room);
|
||||
const [agentA, agentB] = sessions;
|
||||
|
||||
await test.step('expect room a to bot be visible for user2', async () => {
|
||||
await expect(agentB.poHomeOmnichannel.sidebar.getSidebarItemByName(roomA.fname)).not.toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('expect to be able to join chats from same unit', async () => {
|
||||
await poOmnichannel.chats.openChat(roomA.fname);
|
||||
await poOmnichannel.quickActionsRoomToolbar.forwardChat();
|
||||
});
|
||||
|
||||
await test.step('expect agent and department fields to be visible and enabled', async () => {
|
||||
await expect(poOmnichannel.content.forwardChatModal.inputForwardUser).toBeEnabled();
|
||||
await expect(poOmnichannel.content.forwardChatModal.inputForwardDepartment).toBeEnabled();
|
||||
await expect(poOmnichannel.content.forwardChatModal.btnForward).toBeDisabled();
|
||||
});
|
||||
|
||||
await test.step('expect to transfer from dep a to dep b', async () => {
|
||||
await poOmnichannel.content.forwardChatModal.selectDepartment(departmentB.name);
|
||||
await poOmnichannel.content.forwardChatModal.inputComment.type('any_comment');
|
||||
await expect(poOmnichannel.content.forwardChatModal.btnForward).toBeEnabled();
|
||||
await poOmnichannel.content.forwardChatModal.btnForward.click();
|
||||
await poOmnichannel.content.forwardChatModal.waitForDismissal();
|
||||
// await expect(agentA.poHomeOmnichannel.toastSuccess).toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('expect conversation to have been assigned to user 2', async () => {
|
||||
await expect(agentA.page).toHaveURL(`/home`);
|
||||
await expect(agentA.poHomeOmnichannel.sidebar.getSidebarItemByName(roomA.fname)).not.toBeVisible();
|
||||
await expect(agentB.poHomeOmnichannel.sidebar.getSidebarItemByName(roomA.fname)).toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('expect user 1 to have left the conversation', async () => {
|
||||
await agentB.poHomeOmnichannel.sidebar.getSidebarItemByName(roomA.fname).click();
|
||||
await agentB.poHomeOmnichannel.content.findSystemMessage(
|
||||
`Transfer: user3 transferred the chat to the department ${departmentB.name}}`,
|
||||
);
|
||||
await agentB.poHomeOmnichannel.content.findSystemMessage('left the channel');
|
||||
});
|
||||
});
|
||||
|
||||
test(`OC - Chat transfers [Manager role] - Transfer to another agent, different department`, async () => {
|
||||
const [, roomB] = conversations.map(({ data }) => data.room);
|
||||
const [agentA, agentB] = sessions;
|
||||
|
||||
await test.step('expect room a to bot be visible for user2', async () => {
|
||||
await expect(agentB.poHomeOmnichannel.sidebar.getSidebarItemByName(roomB.fname)).not.toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('expect to be able to join chats from same unit', async () => {
|
||||
await poOmnichannel.chats.openChat(roomB.fname);
|
||||
await poOmnichannel.quickActionsRoomToolbar.forwardChat();
|
||||
});
|
||||
|
||||
await test.step('expect agent and department fields to be visible and enabled', async () => {
|
||||
await expect(poOmnichannel.content.forwardChatModal.inputForwardUser).toBeEnabled();
|
||||
await expect(poOmnichannel.content.forwardChatModal.inputForwardDepartment).toBeEnabled();
|
||||
await expect(poOmnichannel.content.forwardChatModal.btnForward).toBeDisabled();
|
||||
});
|
||||
|
||||
await test.step('expect to transfer from user1 to user2', async () => {
|
||||
await poOmnichannel.content.forwardChatModal.selectUser(`user2`);
|
||||
await poOmnichannel.content.forwardChatModal.inputComment.type('any_comment');
|
||||
await expect(poOmnichannel.content.forwardChatModal.btnForward).toBeEnabled();
|
||||
await poOmnichannel.content.forwardChatModal.btnForward.click();
|
||||
// await expect(agentA.poHomeOmnichannel.toastSuccess).toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('expect conversation to have been assigned to user 2', async () => {
|
||||
await expect(agentA.page).toHaveURL(`/home`);
|
||||
await expect(agentA.poHomeOmnichannel.sidebar.getSidebarItemByName(roomB.fname)).not.toBeVisible();
|
||||
await expect(agentB.poHomeOmnichannel.sidebar.getSidebarItemByName(roomB.fname)).toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('expect user 1 to have left the conversation', async () => {
|
||||
await agentB.poHomeOmnichannel.sidebar.getSidebarItemByName(roomB.fname).click();
|
||||
await expect(
|
||||
agentB.poHomeOmnichannel.content.findSystemMessage(
|
||||
`New Chat Transfer: user3 transferred the chat to user2 with a comment: any_comment`,
|
||||
),
|
||||
).toBeVisible();
|
||||
await expect(agentB.poHomeOmnichannel.content.findSystemMessage('left the channel')).toBeVisible();
|
||||
});
|
||||
});
|
||||
|
||||
test(`OC - Chat transfers [Manager role] - Transfer to another agent, same department`, async () => {
|
||||
const [, , roomC] = conversations.map(({ data }) => data.room);
|
||||
const [agentA, , agentC] = sessions;
|
||||
|
||||
await test.step('expect room a to bot be visible for user2', async () => {
|
||||
await expect(agentC.poHomeOmnichannel.sidebar.getSidebarItemByName(roomC.fname)).not.toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('expect to be able to join chats from same unit', async () => {
|
||||
await poOmnichannel.chats.openChat(roomC.fname);
|
||||
await poOmnichannel.quickActionsRoomToolbar.forwardChat();
|
||||
});
|
||||
|
||||
await test.step('expect agent and department fields to be visible and enabled', async () => {
|
||||
await expect(poOmnichannel.content.forwardChatModal.inputForwardUser).toBeEnabled();
|
||||
await expect(poOmnichannel.content.forwardChatModal.inputForwardDepartment).toBeEnabled();
|
||||
await expect(poOmnichannel.content.forwardChatModal.btnForward).toBeDisabled();
|
||||
});
|
||||
|
||||
await test.step('expect to transfer from dep a to dep b', async () => {
|
||||
await poOmnichannel.content.forwardChatModal.selectUser('rocketchat.internal.admin.test');
|
||||
await poOmnichannel.content.forwardChatModal.inputComment.type('any_comment');
|
||||
await expect(poOmnichannel.content.forwardChatModal.btnForward).toBeEnabled();
|
||||
await poOmnichannel.content.forwardChatModal.btnForward.click();
|
||||
// await expect(agentA.poHomeOmnichannel.toastSuccess).toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('expect conversation to have been assigned to user 2', async () => {
|
||||
await expect(agentA.page).toHaveURL(`/home`);
|
||||
await expect(agentA.poHomeOmnichannel.sidebar.getSidebarItemByName(roomC.fname)).not.toBeVisible();
|
||||
await expect(agentC.poHomeOmnichannel.sidebar.getSidebarItemByName(roomC.fname)).toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('expect user 1 to have left the conversation', async () => {
|
||||
await agentC.poHomeOmnichannel.sidebar.getSidebarItemByName(roomC.fname).click();
|
||||
await expect(
|
||||
agentC.poHomeOmnichannel.content.findSystemMessage(
|
||||
`New Chat Transfer: user3 transferred the chat to RocketChat Internal Admin Test with a comment: any_comment`,
|
||||
),
|
||||
).toBeVisible();
|
||||
await expect(agentC.poHomeOmnichannel.content.findSystemMessage('left the channel')).toBeVisible();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,53 @@
|
||||
import type { Page } from '@playwright/test';
|
||||
|
||||
import { createFakeVisitor } from '../../mocks/data';
|
||||
import { createAuxContext } from '../fixtures/createAuxContext';
|
||||
import { Users } from '../fixtures/userStates';
|
||||
import { HomeOmnichannel } from '../page-objects';
|
||||
import { OmnichannelLiveChat } from '../page-objects/omnichannel';
|
||||
import { test } from '../utils/test';
|
||||
|
||||
test.describe('Omnichannel close chat', () => {
|
||||
let poLiveChat: OmnichannelLiveChat;
|
||||
let newVisitor: { email: string; name: string };
|
||||
|
||||
let agent: { page: Page; poHomeOmnichannel: HomeOmnichannel };
|
||||
|
||||
test.beforeAll(async ({ api, browser }) => {
|
||||
newVisitor = createFakeVisitor();
|
||||
|
||||
// Set user user 1 as manager and agent
|
||||
await api.post('/livechat/users/agent', { username: 'user1' });
|
||||
await api.post('/livechat/users/manager', { username: 'user1' });
|
||||
|
||||
const { page } = await createAuxContext(browser, Users.user1);
|
||||
agent = { page, poHomeOmnichannel: new HomeOmnichannel(page) };
|
||||
});
|
||||
test.beforeEach(async ({ page, api }) => {
|
||||
poLiveChat = new OmnichannelLiveChat(page, api);
|
||||
});
|
||||
|
||||
test.afterAll(async ({ api }) => {
|
||||
await api.delete('/livechat/users/agent/user1');
|
||||
await api.delete('/livechat/users/manager/user1');
|
||||
await agent.page.close();
|
||||
});
|
||||
|
||||
test('Receiving a message from visitor', async () => {
|
||||
await test.step('Expect send a message as a visitor', async () => {
|
||||
await poLiveChat.goto();
|
||||
await poLiveChat.openLiveChat();
|
||||
await poLiveChat.sendMessage(newVisitor, false);
|
||||
await poLiveChat.onlineAgentMessage.type('this_a_test_message_from_visitor');
|
||||
await poLiveChat.btnSendMessageToOnlineAgent.click();
|
||||
});
|
||||
|
||||
await test.step('Expect to have 1 omnichannel assigned to agent 1', async () => {
|
||||
await agent.poHomeOmnichannel.navbar.openChat(newVisitor.name);
|
||||
});
|
||||
|
||||
await test.step('Expect to be able to close an omnichannel to conversation', async () => {
|
||||
await agent.poHomeOmnichannel.quickActionsRoomToolbar.closeChat();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,67 @@
|
||||
import type { Page } from '@playwright/test';
|
||||
|
||||
import { createFakeVisitor } from '../../mocks/data';
|
||||
import { createAuxContext } from '../fixtures/createAuxContext';
|
||||
import { Users } from '../fixtures/userStates';
|
||||
import { HomeOmnichannel } from '../page-objects';
|
||||
import { OmnichannelLiveChat } from '../page-objects/omnichannel';
|
||||
import { test, expect } from '../utils/test';
|
||||
|
||||
test.describe('Omnichannel close inquiry', () => {
|
||||
let poLiveChat: OmnichannelLiveChat;
|
||||
let newVisitor: { email: string; name: string };
|
||||
|
||||
let agent: { page: Page; poHomeOmnichannel: HomeOmnichannel };
|
||||
|
||||
test.beforeAll(async ({ api }) => {
|
||||
newVisitor = createFakeVisitor();
|
||||
|
||||
await api.post('/settings/Livechat_Routing_Method', { value: 'Manual_Selection' }).then((res) => expect(res.status()).toBe(200));
|
||||
await api.post('/livechat/users/manager', { username: 'user1' });
|
||||
await api.post('/livechat/users/agent', { username: 'user1' });
|
||||
});
|
||||
|
||||
test.beforeEach(async ({ page, api, browser }) => {
|
||||
poLiveChat = new OmnichannelLiveChat(page, api);
|
||||
|
||||
const { page: auxPage } = await createAuxContext(browser, Users.user1);
|
||||
agent = { page: auxPage, poHomeOmnichannel: new HomeOmnichannel(auxPage) };
|
||||
});
|
||||
|
||||
test.afterEach(async () => {
|
||||
await agent.page.close();
|
||||
});
|
||||
|
||||
test.afterAll(async ({ api }) => {
|
||||
await Promise.all([
|
||||
await api.post('/settings/Livechat_Routing_Method', { value: 'Auto_Selection' }).then((res) => expect(res.status()).toBe(200)),
|
||||
await api.delete('/livechat/users/agent/user1'),
|
||||
await api.delete('/livechat/users/manager/user1'),
|
||||
]);
|
||||
});
|
||||
|
||||
test('Receiving a message from visitor', async () => {
|
||||
await test.step('Expect send a message as a visitor', async () => {
|
||||
await poLiveChat.goto();
|
||||
await poLiveChat.openLiveChat();
|
||||
await poLiveChat.sendMessage(newVisitor, false);
|
||||
await poLiveChat.onlineAgentMessage.type('this_a_test_message_from_visitor');
|
||||
await poLiveChat.btnSendMessageToOnlineAgent.click();
|
||||
});
|
||||
|
||||
await test.step('Expect to have 1 omnichannel assigned to agent 1', async () => {
|
||||
await agent.poHomeOmnichannel.sidebar.getSidebarItemByName(newVisitor.name).click();
|
||||
await expect(agent.poHomeOmnichannel.content.btnTakeChat).toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('Expect to be able to close an inquiry conversation', async () => {
|
||||
await agent.poHomeOmnichannel.quickActionsRoomToolbar.closeChat();
|
||||
});
|
||||
|
||||
await test.step('Expect to inquiry be closed when navigate back', async () => {
|
||||
await agent.poHomeOmnichannel.chats.goto();
|
||||
await agent.poHomeOmnichannel.chats.openChat(newVisitor.name);
|
||||
await expect(agent.poHomeOmnichannel.content.btnTakeChat).not.toBeVisible();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,77 @@
|
||||
import { faker } from '@faker-js/faker/locale/af_ZA';
|
||||
|
||||
import { Users } from '../fixtures/userStates';
|
||||
import { OmnichannelContactCenterChats } from '../page-objects/omnichannel';
|
||||
import { setSettingValueById } from '../utils';
|
||||
import { createAgent, makeAgentAvailable } from '../utils/omnichannel/agents';
|
||||
import { createConversation } from '../utils/omnichannel/rooms';
|
||||
import { test, expect } from '../utils/test';
|
||||
|
||||
test.use({ storageState: Users.user1.state });
|
||||
|
||||
test.describe('OC - Contact Center - Chats', () => {
|
||||
let conversations: Awaited<ReturnType<typeof createConversation>>[];
|
||||
let agent: Awaited<ReturnType<typeof createAgent>>;
|
||||
|
||||
let poOmniChats: OmnichannelContactCenterChats;
|
||||
|
||||
const uuid = faker.string.uuid();
|
||||
const visitorA = `visitorA_${uuid}`;
|
||||
const visitorB = `visitorB_${uuid}`;
|
||||
|
||||
test.beforeAll(async ({ api }) => {
|
||||
expect((await setSettingValueById(api, 'Livechat_Routing_Method', 'Auto_Selection')).status()).toBe(200);
|
||||
});
|
||||
|
||||
test.beforeAll(async ({ api }) => {
|
||||
agent = await createAgent(api, 'user1');
|
||||
|
||||
expect((await makeAgentAvailable(api, agent.data._id)).status()).toBe(200);
|
||||
});
|
||||
|
||||
test.beforeAll(async ({ api }) => {
|
||||
conversations = await Promise.all([
|
||||
createConversation(api, { agentId: `user1`, visitorName: visitorA }),
|
||||
createConversation(api, { agentId: `user1`, visitorName: visitorB }),
|
||||
]);
|
||||
});
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
poOmniChats = new OmnichannelContactCenterChats(page);
|
||||
|
||||
await poOmniChats.goto();
|
||||
});
|
||||
|
||||
test.afterEach(async ({ page }) => {
|
||||
await page.close();
|
||||
});
|
||||
|
||||
test.afterAll(async ({ api }) => {
|
||||
await Promise.all([...conversations.map((conversation) => conversation.delete()), agent.delete()]);
|
||||
expect((await setSettingValueById(api, 'Livechat_Routing_Method', 'Auto_Selection')).status()).toBe(200);
|
||||
});
|
||||
|
||||
test(`OC - Contact Center - Chats - Filter from and to same date`, async ({ page }) => {
|
||||
await test.step('expect conversations to be visible', async () => {
|
||||
await poOmniChats.inputSearch.fill(uuid);
|
||||
await expect(poOmniChats.table.findRowByName(visitorA)).toBeVisible();
|
||||
await expect(poOmniChats.table.findRowByName(visitorB)).toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('expect to filter [from] and [to] today', async () => {
|
||||
const [chatA] = conversations.map((c) => c.data);
|
||||
const [todayString] = new Date(chatA.room.ts).toISOString().split('T');
|
||||
await poOmniChats.btnFilters.click();
|
||||
await expect(page).toHaveURL('/omnichannel/current/chats/filters');
|
||||
await poOmniChats.filters.inputFrom.fill(todayString);
|
||||
await poOmniChats.filters.inputTo.fill(todayString);
|
||||
await poOmniChats.filters.btnApply.click();
|
||||
await page.waitForResponse('**/api/v1/livechat/rooms*');
|
||||
});
|
||||
|
||||
await test.step('expect conversations to be visible', async () => {
|
||||
await expect(poOmniChats.table.findRowByName(visitorA)).toBeVisible();
|
||||
await expect(poOmniChats.table.findRowByName(visitorB)).toBeVisible();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,227 @@
|
||||
import { faker } from '@faker-js/faker';
|
||||
import type { Page } from '@playwright/test';
|
||||
|
||||
import { IS_EE } from '../config/constants';
|
||||
import { Users } from '../fixtures/userStates';
|
||||
import { HomeOmnichannel } from '../page-objects';
|
||||
import { OmnichannelContactCenterChats } from '../page-objects/omnichannel';
|
||||
import { setSettingValueById } from '../utils';
|
||||
import { createAgent, makeAgentAvailable } from '../utils/omnichannel/agents';
|
||||
import { addAgentToDepartment, createDepartment } from '../utils/omnichannel/departments';
|
||||
import { createConversation, updateRoom } from '../utils/omnichannel/rooms';
|
||||
import { createTag } from '../utils/omnichannel/tags';
|
||||
import { test, expect } from '../utils/test';
|
||||
|
||||
const visitorA = `${faker.person.firstName()}-${faker.database.mongodbObjectId()}`;
|
||||
const visitorB = `${faker.person.firstName()}-${faker.database.mongodbObjectId()}`;
|
||||
const visitorC = `${faker.person.firstName()}-${faker.database.mongodbObjectId()}`;
|
||||
|
||||
test.skip(!IS_EE, 'OC - Contact Center Chats > Enterprise Only');
|
||||
|
||||
test.use({ storageState: Users.admin.state });
|
||||
|
||||
test.describe('OC - Contact Center Chats [Auto Selection]', async () => {
|
||||
let poContactCenterChats: OmnichannelContactCenterChats;
|
||||
let poHomeOmnichannel: HomeOmnichannel;
|
||||
let departments: Awaited<ReturnType<typeof createDepartment>>[];
|
||||
let conversations: Awaited<ReturnType<typeof createConversation>>[];
|
||||
let agents: Awaited<ReturnType<typeof createAgent>>[];
|
||||
let tagA: Awaited<ReturnType<typeof createTag>>;
|
||||
let tagB: Awaited<ReturnType<typeof createTag>>;
|
||||
|
||||
// Allow manual on hold
|
||||
test.beforeAll(async ({ api }) => {
|
||||
const responses = await Promise.all([
|
||||
api.post('/settings/Livechat_allow_manual_on_hold', { value: true }),
|
||||
api.post('/settings/Livechat_allow_manual_on_hold_upon_agent_engagement_only', { value: false }),
|
||||
]);
|
||||
responses.forEach((res) => expect(res.status()).toBe(200));
|
||||
});
|
||||
|
||||
// Create departments
|
||||
test.beforeAll(async ({ api }) => {
|
||||
departments = await Promise.all([createDepartment(api), createDepartment(api)]);
|
||||
});
|
||||
|
||||
// Create agents
|
||||
test.beforeAll(async ({ api }) => {
|
||||
agents = await Promise.all([createAgent(api, 'user1'), createAgent(api, 'user2')]);
|
||||
|
||||
const agentsStatuses = await Promise.all(agents.map(({ data: agent }) => makeAgentAvailable(api, agent._id)));
|
||||
|
||||
agentsStatuses.forEach((res) => expect(res.status()).toBe(200));
|
||||
});
|
||||
|
||||
// Add agents to departments
|
||||
test.beforeAll(async ({ api }) => {
|
||||
const [departmentA, departmentB] = departments.map(({ data }) => data);
|
||||
|
||||
const promises = await Promise.all([
|
||||
addAgentToDepartment(api, { department: departmentA, agentId: 'user1' }),
|
||||
addAgentToDepartment(api, { department: departmentB, agentId: 'user2' }),
|
||||
]);
|
||||
|
||||
promises.forEach((res) => expect(res.status()).toBe(200));
|
||||
});
|
||||
|
||||
// Create tags
|
||||
test.beforeAll(async ({ api }) => {
|
||||
tagA = await createTag(api);
|
||||
tagB = await createTag(api);
|
||||
|
||||
[tagA, tagB].forEach((res) => expect(res.response.status()).toBe(200));
|
||||
});
|
||||
|
||||
// Create rooms
|
||||
test.beforeAll(async ({ api }) => {
|
||||
const [departmentA, departmentB] = departments.map(({ data }) => data);
|
||||
|
||||
conversations = await Promise.all([
|
||||
createConversation(api, {
|
||||
visitorName: visitorA,
|
||||
visitorToken: visitorA,
|
||||
agentId: `user1`,
|
||||
departmentId: departmentA._id,
|
||||
}),
|
||||
createConversation(api, {
|
||||
visitorName: visitorB,
|
||||
visitorToken: visitorB,
|
||||
agentId: `user2`,
|
||||
departmentId: departmentB._id,
|
||||
}),
|
||||
createConversation(api, {
|
||||
visitorName: visitorC,
|
||||
visitorToken: visitorC,
|
||||
}),
|
||||
]);
|
||||
|
||||
const [conversationA, conversationB] = conversations.map(({ data }) => data);
|
||||
|
||||
await Promise.all([
|
||||
updateRoom(api, {
|
||||
roomId: conversationA.room._id,
|
||||
visitorId: conversationA.visitor._id,
|
||||
tags: [tagA.data.name],
|
||||
}),
|
||||
updateRoom(api, {
|
||||
roomId: conversationB.room._id,
|
||||
visitorId: conversationB.visitor._id,
|
||||
tags: [tagB.data.name],
|
||||
}),
|
||||
]);
|
||||
await setSettingValueById(api, 'Omnichannel_enable_department_removal', true);
|
||||
});
|
||||
|
||||
test.beforeEach(async ({ page }: { page: Page }) => {
|
||||
poContactCenterChats = new OmnichannelContactCenterChats(page);
|
||||
poHomeOmnichannel = new HomeOmnichannel(page);
|
||||
|
||||
await poContactCenterChats.goto();
|
||||
});
|
||||
|
||||
test.afterAll(async ({ api }) => {
|
||||
await Promise.all([
|
||||
// Delete conversations
|
||||
...conversations.map((conversation) => conversation.delete()),
|
||||
// Delete departments
|
||||
...departments.map((department) => department.delete()),
|
||||
// Delete agents
|
||||
...agents.map((agent) => agent.delete()),
|
||||
// Delete tags
|
||||
...[tagA, tagB].map((tag) => tag.delete()),
|
||||
// Reset setting
|
||||
api.post('/settings/Livechat_allow_manual_on_hold', { value: false }),
|
||||
api.post('/settings/Livechat_allow_manual_on_hold_upon_agent_engagement_only', { value: true }),
|
||||
]);
|
||||
await setSettingValueById(api, 'Omnichannel_enable_department_removal', false);
|
||||
});
|
||||
|
||||
// Change conversation A to on hold and close conversation B
|
||||
test.beforeAll(async ({ api }) => {
|
||||
const [conversationA, , conversationC] = conversations.map(({ data }) => data);
|
||||
|
||||
const statesPromises = await Promise.all([
|
||||
api.post('/livechat/room.onHold', { roomId: conversationA.room._id }),
|
||||
api.post('/livechat/room.close', { rid: conversationC.room._id, token: visitorC }),
|
||||
]);
|
||||
|
||||
statesPromises.forEach((res) => expect(res.status()).toBe(200));
|
||||
});
|
||||
|
||||
test('OC - Contact Center Chats - Basic navigation', async ({ page }) => {
|
||||
await test.step('expect to be return using return button', async () => {
|
||||
await poContactCenterChats.openChat(visitorA);
|
||||
await poHomeOmnichannel.content.btnReturn.click();
|
||||
expect(page.url()).toContain(`/omnichannel/current`);
|
||||
});
|
||||
});
|
||||
|
||||
test('OC - Contact Center Chats - Access in progress conversation from another agent', async () => {
|
||||
await test.step('expect to be able to join', async () => {
|
||||
const { visitor: visitorB } = conversations[1].data;
|
||||
await poContactCenterChats.openChat(visitorB.name);
|
||||
await expect(poHomeOmnichannel.composer.btnJoinRoom).toBeVisible();
|
||||
await poHomeOmnichannel.composer.btnJoinRoom.click();
|
||||
await expect(poHomeOmnichannel.composer.btnJoinRoom).not.toBeVisible();
|
||||
});
|
||||
});
|
||||
|
||||
test('OC - Contact Center Chats - Remove conversations', async () => {
|
||||
await test.step('expect to be able to remove conversation from table', async () => {
|
||||
await poContactCenterChats.removeChatByName(visitorC);
|
||||
await expect(poContactCenterChats.table.findRowByName(visitorC)).not.toBeVisible();
|
||||
});
|
||||
|
||||
// TODO: await test.step('expect to be able to close all closes conversations', async () => {});
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('OC - Contact Center [Manual Selection]', () => {
|
||||
let queuedConversation: Awaited<ReturnType<typeof createConversation>>;
|
||||
let poHomeOmnichannel: HomeOmnichannel;
|
||||
let poCurrentChats: OmnichannelContactCenterChats;
|
||||
let agent: Awaited<ReturnType<typeof createAgent>>;
|
||||
|
||||
test.beforeAll(async ({ api }) => {
|
||||
const res = await api.post('/settings/Livechat_Routing_Method', { value: 'Manual_Selection' });
|
||||
expect(res.status()).toBe(200);
|
||||
});
|
||||
|
||||
test.beforeAll(async ({ api }) => {
|
||||
agent = await createAgent(api, 'rocketchat.internal.admin.test');
|
||||
|
||||
const agentStatus = await makeAgentAvailable(api, agent.data._id);
|
||||
|
||||
expect(agentStatus.status()).toBe(200);
|
||||
});
|
||||
|
||||
test.beforeEach(async ({ page }: { page: Page }) => {
|
||||
poHomeOmnichannel = new HomeOmnichannel(page);
|
||||
poCurrentChats = new OmnichannelContactCenterChats(page);
|
||||
|
||||
await poCurrentChats.goto();
|
||||
});
|
||||
|
||||
test('OC - Contact Center Chats - Access queued conversation', async ({ api }) => {
|
||||
queuedConversation = await createConversation(api, { visitorToken: 'visitorQueued' });
|
||||
|
||||
await test.step('expect to be able to take it', async () => {
|
||||
const { visitor } = queuedConversation.data;
|
||||
await poCurrentChats.inputSearch.fill(visitor.name);
|
||||
await poCurrentChats.openChat(visitor.name);
|
||||
await expect(poHomeOmnichannel.content.btnTakeChat).toBeVisible();
|
||||
await poHomeOmnichannel.content.btnTakeChat.click();
|
||||
await expect(poHomeOmnichannel.content.btnTakeChat).not.toBeVisible();
|
||||
});
|
||||
});
|
||||
|
||||
test.afterAll(async ({ api }) => {
|
||||
const res = await api.post('/settings/Livechat_Routing_Method', { value: 'Auto_Selection' });
|
||||
expect(res.status()).toBe(200);
|
||||
});
|
||||
|
||||
test.afterAll(async () => {
|
||||
await queuedConversation.delete();
|
||||
await agent.delete();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,287 @@
|
||||
import { randomBytes } from 'crypto';
|
||||
|
||||
import { faker } from '@faker-js/faker';
|
||||
|
||||
import { Users } from '../fixtures/userStates';
|
||||
import { HomeOmnichannel } from '../page-objects';
|
||||
import { Navbar } from '../page-objects/fragments';
|
||||
import { OmnichannelContactCenterContacts } from '../page-objects/omnichannel';
|
||||
import { test, expect } from '../utils/test';
|
||||
|
||||
const createToken = (): string => {
|
||||
const array = new Uint8Array(16);
|
||||
|
||||
const buffer = randomBytes(16);
|
||||
array.set(buffer);
|
||||
|
||||
return Array.from(array)
|
||||
.map((byte) => byte.toString(16).padStart(2, '0'))
|
||||
.join('');
|
||||
};
|
||||
|
||||
const createContact = (generateToken = false) => ({
|
||||
id: null,
|
||||
name: `${faker.person.firstName()} ${faker.person.lastName()}`,
|
||||
email: faker.internet.email().toLowerCase(),
|
||||
phone: faker.phone.number('+############'),
|
||||
token: generateToken ? createToken() : null,
|
||||
customFields: {},
|
||||
});
|
||||
|
||||
const NEW_CONTACT = createContact();
|
||||
const EDIT_CONTACT = createContact();
|
||||
const EXISTING_CONTACT = {
|
||||
id: undefined,
|
||||
name: `${faker.person.firstName()} ${faker.person.lastName()}`,
|
||||
emails: [faker.internet.email().toLowerCase()],
|
||||
phones: [faker.phone.number('+############')],
|
||||
token: undefined,
|
||||
};
|
||||
const DELETE_CONTACT = {
|
||||
id: undefined,
|
||||
name: `${faker.person.firstName()} ${faker.person.lastName()}`,
|
||||
emails: [faker.internet.email().toLowerCase()],
|
||||
phones: [faker.phone.number('+############')],
|
||||
};
|
||||
|
||||
const URL = {
|
||||
contactCenter: '/omnichannel-directory/contacts',
|
||||
newContact: '/omnichannel-directory/contacts/new',
|
||||
get editContact() {
|
||||
return `${this.contactCenter}/edit/${NEW_CONTACT.id}`;
|
||||
},
|
||||
get contactInfo() {
|
||||
return `${this.contactCenter}/details/${NEW_CONTACT.id}`;
|
||||
},
|
||||
};
|
||||
|
||||
const ERROR = {
|
||||
nameRequired: 'Name required',
|
||||
invalidEmail: 'Invalid email address',
|
||||
emailRequired: 'Email required',
|
||||
emailAlreadyExists: 'Email already exists',
|
||||
phoneRequired: 'Phone required',
|
||||
phoneAlreadyExists: 'Phone already exists',
|
||||
};
|
||||
|
||||
test.use({ storageState: Users.admin.state });
|
||||
|
||||
test.describe('OC - Contact Center - Contacts', () => {
|
||||
let poContacts: OmnichannelContactCenterContacts;
|
||||
let poNavbar: Navbar;
|
||||
|
||||
test.beforeAll(async ({ api }) => {
|
||||
// Add contacts
|
||||
await Promise.all([api.post('/omnichannel/contacts', EXISTING_CONTACT), api.post('/omnichannel/contacts', DELETE_CONTACT)]);
|
||||
});
|
||||
|
||||
test.afterAll(async ({ api }) => {
|
||||
// Remove added contacts
|
||||
await Promise.all([api.delete(`/livechat/visitor/${NEW_CONTACT.token}`), api.delete(`/livechat/visitor/${EXISTING_CONTACT.token}`)]);
|
||||
});
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
poContacts = new OmnichannelContactCenterContacts(page);
|
||||
poNavbar = new Navbar(page);
|
||||
});
|
||||
|
||||
test.afterEach(async ({ api }) => {
|
||||
await api
|
||||
.get('/omnichannel/contacts.search', { searchText: NEW_CONTACT.phone })
|
||||
.then((res) => res.json())
|
||||
.then((res) => {
|
||||
NEW_CONTACT.token = res.contacts?.[0]?.token;
|
||||
NEW_CONTACT.id = res.contacts?.[0]?._id;
|
||||
});
|
||||
|
||||
await api
|
||||
.get('/omnichannel/contacts.search', { searchText: EXISTING_CONTACT.phones[0] })
|
||||
.then((res) => res.json())
|
||||
.then((res) => {
|
||||
EXISTING_CONTACT.token = res.contacts?.[0]?.token;
|
||||
EXISTING_CONTACT.id = res.contacts?.[0]?._id;
|
||||
});
|
||||
});
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await new HomeOmnichannel(page).goto();
|
||||
await poNavbar.btnContactCenter.click();
|
||||
await poContacts.tabContacts.click();
|
||||
await page.waitForURL(URL.contactCenter);
|
||||
});
|
||||
|
||||
test('Add new contact', async ({ page }) => {
|
||||
await test.step('cancel button', async () => {
|
||||
await poContacts.btnNewContact.click();
|
||||
await page.waitForURL(URL.newContact);
|
||||
await expect(poContacts.editContact.inputName).toBeVisible();
|
||||
await poContacts.editContact.btnCancel.click();
|
||||
await page.waitForURL(URL.contactCenter);
|
||||
await expect(poContacts.editContact.inputName).not.toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('open contextual bar', async () => {
|
||||
await poContacts.btnNewContact.click();
|
||||
await page.waitForURL(URL.newContact);
|
||||
await expect(poContacts.editContact.inputName).toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('input name', async () => {
|
||||
await poContacts.editContact.inputName.fill(NEW_CONTACT.name);
|
||||
});
|
||||
|
||||
await test.step('validate email format', async () => {
|
||||
await poContacts.editContact.btnAddEmail.click();
|
||||
await poContacts.editContact.inputEmail.fill('invalidemail');
|
||||
await page.keyboard.press('Enter');
|
||||
await expect(poContacts.editContact.getErrorMessage(ERROR.invalidEmail)).toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('validate email is duplicated', async () => {
|
||||
await poContacts.editContact.inputEmail.fill(EXISTING_CONTACT.emails[0]);
|
||||
await page.keyboard.press('Tab');
|
||||
await expect(poContacts.editContact.getErrorMessage(ERROR.emailAlreadyExists)).toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('validate email is required', async () => {
|
||||
await poContacts.editContact.inputEmail.clear();
|
||||
await page.keyboard.press('Tab');
|
||||
await expect(poContacts.editContact.getErrorMessage(ERROR.emailRequired)).toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('input email', async () => {
|
||||
await poContacts.editContact.inputEmail.fill(NEW_CONTACT.email);
|
||||
await page.keyboard.press('Tab');
|
||||
await expect(poContacts.editContact.getErrorMessage(ERROR.invalidEmail)).not.toBeVisible();
|
||||
await expect(poContacts.editContact.getErrorMessage(ERROR.emailRequired)).not.toBeVisible();
|
||||
await expect(poContacts.editContact.getErrorMessage(ERROR.emailAlreadyExists)).not.toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('validate phone is duplicated', async () => {
|
||||
await poContacts.editContact.btnAddPhone.click();
|
||||
await poContacts.editContact.inputPhone.fill(EXISTING_CONTACT.phones[0]);
|
||||
await page.keyboard.press('Tab');
|
||||
await expect(poContacts.editContact.getErrorMessage(ERROR.phoneAlreadyExists)).toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('input phone', async () => {
|
||||
await poContacts.editContact.inputPhone.fill(NEW_CONTACT.phone);
|
||||
await page.keyboard.press('Tab');
|
||||
await expect(poContacts.editContact.getErrorMessage(ERROR.phoneRequired)).not.toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('save new contact', async () => {
|
||||
await expect(poContacts.editContact.btnSave).toBeEnabled();
|
||||
await poContacts.editContact.btnSave.click();
|
||||
|
||||
await poContacts.inputSearch.fill(NEW_CONTACT.name);
|
||||
await expect(poContacts.table.findRowByName(NEW_CONTACT.name)).toBeVisible();
|
||||
});
|
||||
});
|
||||
|
||||
test('Edit new contact', async ({ page }) => {
|
||||
await test.step('search contact and open contextual bar', async () => {
|
||||
await poContacts.inputSearch.fill(NEW_CONTACT.name);
|
||||
const row = poContacts.table.findRowByName(NEW_CONTACT.name);
|
||||
await expect(row).toBeVisible();
|
||||
await row.click();
|
||||
await page.waitForURL(URL.contactInfo);
|
||||
});
|
||||
|
||||
await test.step('cancel button', async () => {
|
||||
await poContacts.contactInfo.btnEdit.click();
|
||||
await page.waitForURL(URL.editContact);
|
||||
await poContacts.editContact.btnCancel.click();
|
||||
await page.waitForURL(URL.contactInfo);
|
||||
});
|
||||
|
||||
await test.step('edit contact', async () => {
|
||||
await poContacts.contactInfo.btnEdit.click();
|
||||
await page.waitForURL(URL.editContact);
|
||||
});
|
||||
|
||||
await test.step('initial values', async () => {
|
||||
await expect(poContacts.editContact.inputName).toHaveValue(NEW_CONTACT.name);
|
||||
await expect(poContacts.editContact.inputEmail).toHaveValue(NEW_CONTACT.email);
|
||||
await expect(poContacts.editContact.inputPhone).toHaveValue(NEW_CONTACT.phone);
|
||||
});
|
||||
|
||||
await test.step('validate email format', async () => {
|
||||
await poContacts.editContact.inputEmail.fill('invalidemail');
|
||||
await page.keyboard.press('Enter');
|
||||
await expect(poContacts.editContact.getErrorMessage(ERROR.invalidEmail)).toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('validate email is duplicated', async () => {
|
||||
await poContacts.editContact.inputEmail.fill(EXISTING_CONTACT.emails[0]);
|
||||
await page.keyboard.press('Tab');
|
||||
await expect(poContacts.editContact.getErrorMessage(ERROR.emailAlreadyExists)).toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('validate email is required', async () => {
|
||||
await poContacts.editContact.inputEmail.clear();
|
||||
await page.keyboard.press('Tab');
|
||||
await expect(poContacts.editContact.getErrorMessage(ERROR.emailRequired)).toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('validate name is required', async () => {
|
||||
await poContacts.editContact.inputName.clear();
|
||||
await page.keyboard.press('Tab');
|
||||
await expect(poContacts.editContact.getErrorMessage(ERROR.nameRequired)).toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('edit name', async () => {
|
||||
await poContacts.editContact.inputName.fill(EDIT_CONTACT.name);
|
||||
});
|
||||
|
||||
await test.step('validate phone is duplicated', async () => {
|
||||
await poContacts.editContact.inputPhone.fill(EXISTING_CONTACT.phones[0]);
|
||||
await page.keyboard.press('Tab');
|
||||
await expect(poContacts.editContact.getErrorMessage(ERROR.phoneAlreadyExists)).toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('input phone ', async () => {
|
||||
await poContacts.editContact.inputPhone.fill(EDIT_CONTACT.phone);
|
||||
await page.keyboard.press('Tab');
|
||||
await expect(poContacts.editContact.getErrorMessage(ERROR.phoneRequired)).not.toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('input email', async () => {
|
||||
await poContacts.editContact.inputEmail.fill(EDIT_CONTACT.email);
|
||||
await page.keyboard.press('Tab');
|
||||
await expect(poContacts.editContact.getErrorMessage(ERROR.invalidEmail)).not.toBeVisible();
|
||||
await expect(poContacts.editContact.getErrorMessage(ERROR.emailRequired)).not.toBeVisible();
|
||||
await expect(poContacts.editContact.getErrorMessage(ERROR.emailAlreadyExists)).not.toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('save new contact ', async () => {
|
||||
await poContacts.editContact.btnSave.click();
|
||||
|
||||
await poContacts.inputSearch.fill(EDIT_CONTACT.name);
|
||||
await expect(poContacts.table.findRowByName(EDIT_CONTACT.name)).toBeVisible();
|
||||
});
|
||||
});
|
||||
|
||||
test('Delete a contact', async () => {
|
||||
await test.step('Find contact and open modal', async () => {
|
||||
await poContacts.inputSearch.fill(DELETE_CONTACT.name);
|
||||
await poContacts.deleteContact(DELETE_CONTACT.name);
|
||||
});
|
||||
|
||||
await test.step('Fill confirmation and delete contact', async () => {
|
||||
// Fills the input with the wrong confirmation
|
||||
await poContacts.deleteContactModal.inputConfirmation.fill('wrong');
|
||||
await expect(poContacts.deleteContactModal.btnDelete).toBeDisabled();
|
||||
|
||||
// Fills the input correctly
|
||||
await poContacts.deleteContactModal.inputConfirmation.fill('delete');
|
||||
await expect(poContacts.deleteContactModal.btnDelete).toBeEnabled();
|
||||
await poContacts.deleteContactModal.delete();
|
||||
});
|
||||
|
||||
await test.step('Confirm contact removal', async () => {
|
||||
await poContacts.inputSearch.fill(DELETE_CONTACT.name);
|
||||
await expect(poContacts.table.findRowByName(DELETE_CONTACT.name)).not.toBeVisible();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,345 @@
|
||||
import { createFakeVisitor } from '../../mocks/data';
|
||||
import { IS_EE } from '../config/constants';
|
||||
import { Users } from '../fixtures/userStates';
|
||||
import { HomeOmnichannel } from '../page-objects';
|
||||
import { Navbar } from '../page-objects/fragments';
|
||||
import { OmnichannelContactCenterChats } from '../page-objects/omnichannel';
|
||||
import { setSettingValueById } from '../utils';
|
||||
import { createAgent, makeAgentAvailable } from '../utils/omnichannel/agents';
|
||||
import { addAgentToDepartment, createDepartment } from '../utils/omnichannel/departments';
|
||||
import { createConversation, updateRoom } from '../utils/omnichannel/rooms';
|
||||
import { createTag } from '../utils/omnichannel/tags';
|
||||
import { createOrUpdateUnit } from '../utils/omnichannel/units';
|
||||
import { test, expect } from '../utils/test';
|
||||
|
||||
const URL = {
|
||||
contactCenterChats: '/omnichannel-directory/chats',
|
||||
};
|
||||
|
||||
const visitorA = createFakeVisitor().name;
|
||||
const visitorB = createFakeVisitor().name;
|
||||
const visitorC = createFakeVisitor().name;
|
||||
|
||||
test.skip(!IS_EE, 'OC - Contact center Filters > Enterprise Only');
|
||||
|
||||
test.use({ storageState: Users.admin.state });
|
||||
|
||||
test.describe('OC - Contact Center', async () => {
|
||||
let departments: Awaited<ReturnType<typeof createDepartment>>[];
|
||||
let conversations: Awaited<ReturnType<typeof createConversation>>[];
|
||||
let agents: Awaited<ReturnType<typeof createAgent>>[];
|
||||
let tagA: Awaited<ReturnType<typeof createTag>>;
|
||||
let tagB: Awaited<ReturnType<typeof createTag>>;
|
||||
let units: Awaited<ReturnType<typeof createOrUpdateUnit>>[];
|
||||
let poNavbar: Navbar;
|
||||
let poOmniChats: OmnichannelContactCenterChats;
|
||||
|
||||
// Allow manual on hold
|
||||
test.beforeAll(async ({ api }) => {
|
||||
const responses = await Promise.all([
|
||||
api.post('/settings/Livechat_allow_manual_on_hold', { value: true }),
|
||||
api.post('/settings/Livechat_allow_manual_on_hold_upon_agent_engagement_only', { value: false }),
|
||||
]);
|
||||
responses.forEach((res) => expect(res.status()).toBe(200));
|
||||
});
|
||||
|
||||
// Create departments
|
||||
test.beforeAll(async ({ api }) => {
|
||||
departments = await Promise.all([createDepartment(api), createDepartment(api)]);
|
||||
});
|
||||
|
||||
// Create agents
|
||||
test.beforeAll(async ({ api }) => {
|
||||
agents = await Promise.all([createAgent(api, 'user1'), createAgent(api, 'user2')]);
|
||||
|
||||
const agentsStatuses = await Promise.all(agents.map(({ data: agent }) => makeAgentAvailable(api, agent._id)));
|
||||
|
||||
agentsStatuses.forEach((res) => expect(res.status()).toBe(200));
|
||||
});
|
||||
|
||||
// Add agents to departments
|
||||
test.beforeAll(async ({ api }) => {
|
||||
const [departmentA, departmentB] = departments.map(({ data }) => data);
|
||||
|
||||
const promises = await Promise.all([
|
||||
addAgentToDepartment(api, { department: departmentA, agentId: 'user1' }),
|
||||
addAgentToDepartment(api, { department: departmentB, agentId: 'user2' }),
|
||||
]);
|
||||
|
||||
promises.forEach((res) => expect(res.status()).toBe(200));
|
||||
});
|
||||
|
||||
// Create tags
|
||||
test.beforeAll(async ({ api }) => {
|
||||
tagA = await createTag(api);
|
||||
tagB = await createTag(api);
|
||||
|
||||
[tagA, tagB].forEach((res) => expect(res.response.status()).toBe(200));
|
||||
});
|
||||
|
||||
// Create unit
|
||||
test.beforeAll(async ({ api }) => {
|
||||
const [departmentA, departmentB] = departments.map((dep) => dep.data);
|
||||
units = await Promise.all([
|
||||
createOrUpdateUnit(api, {
|
||||
monitors: [{ monitorId: 'user1', username: 'user1' }],
|
||||
departments: [{ departmentId: departmentA._id }],
|
||||
}),
|
||||
createOrUpdateUnit(api, {
|
||||
monitors: [{ monitorId: 'user2', username: 'user2' }],
|
||||
departments: [{ departmentId: departmentB._id }],
|
||||
}),
|
||||
]);
|
||||
units.forEach((res) => expect(res.response.status()).toBe(200));
|
||||
});
|
||||
|
||||
// Create rooms
|
||||
test.beforeAll(async ({ api }) => {
|
||||
const [departmentA, departmentB] = departments.map(({ data }) => data);
|
||||
|
||||
conversations = await Promise.all([
|
||||
createConversation(api, {
|
||||
visitorName: visitorA,
|
||||
visitorToken: visitorA,
|
||||
agentId: `user1`,
|
||||
departmentId: departmentA._id,
|
||||
}),
|
||||
createConversation(api, {
|
||||
visitorName: visitorB,
|
||||
visitorToken: visitorB,
|
||||
agentId: `user2`,
|
||||
departmentId: departmentB._id,
|
||||
}),
|
||||
createConversation(api, {
|
||||
visitorName: visitorC,
|
||||
visitorToken: visitorC,
|
||||
}),
|
||||
]);
|
||||
|
||||
const [conversationA, conversationB] = conversations.map(({ data }) => data);
|
||||
|
||||
await Promise.all([
|
||||
updateRoom(api, {
|
||||
roomId: conversationA.room._id,
|
||||
visitorId: conversationA.visitor._id,
|
||||
tags: [tagA.data.name],
|
||||
}),
|
||||
updateRoom(api, {
|
||||
roomId: conversationB.room._id,
|
||||
visitorId: conversationB.visitor._id,
|
||||
tags: [tagB.data.name],
|
||||
}),
|
||||
]);
|
||||
await setSettingValueById(api, 'Omnichannel_enable_department_removal', true);
|
||||
});
|
||||
|
||||
test.afterAll(async ({ api }) => {
|
||||
await Promise.all([
|
||||
// Delete conversations
|
||||
...conversations.map((conversation) => conversation.delete()),
|
||||
// Delete departments
|
||||
...departments.map((department) => department.delete()),
|
||||
// Delete agents
|
||||
...agents.map((agent) => agent.delete()),
|
||||
// Delete tags
|
||||
...[tagA, tagB].map((tag) => tag.delete()),
|
||||
// Delete units
|
||||
...units.map((unit) => unit.delete()),
|
||||
// Reset setting
|
||||
api.post('/settings/Livechat_allow_manual_on_hold', { value: false }),
|
||||
api.post('/settings/Livechat_allow_manual_on_hold_upon_agent_engagement_only', { value: true }),
|
||||
]);
|
||||
await setSettingValueById(api, 'Omnichannel_enable_department_removal', false);
|
||||
});
|
||||
|
||||
// Change conversation A to on hold and close conversation B
|
||||
test.beforeAll(async ({ api }) => {
|
||||
const [conversationA, , conversationC] = conversations.map(({ data }) => data);
|
||||
|
||||
const statesPromises = await Promise.all([
|
||||
api.post('/livechat/room.onHold', { roomId: conversationA.room._id }),
|
||||
api.post('/livechat/room.close', {
|
||||
rid: conversationC.room._id,
|
||||
token: visitorC,
|
||||
}),
|
||||
]);
|
||||
|
||||
statesPromises.forEach((res) => expect(res.status()).toBe(200));
|
||||
});
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
poOmniChats = new OmnichannelContactCenterChats(page);
|
||||
poNavbar = new Navbar(page);
|
||||
|
||||
await new HomeOmnichannel(page).goto();
|
||||
await poNavbar.btnContactCenter.click();
|
||||
await poOmniChats.tabChats.click();
|
||||
await page.waitForURL(URL.contactCenterChats);
|
||||
});
|
||||
|
||||
test('OC - Contact Center - Filters', async () => {
|
||||
const [departmentA, departmentB] = departments.map(({ data }) => data);
|
||||
const [unitA, unitB] = units.map((unit) => unit.data);
|
||||
|
||||
await test.step('expect to filter by guest', async () => {
|
||||
await poOmniChats.inputSearch.fill(visitorA);
|
||||
await expect(poOmniChats.table.findRowByName(visitorA)).toBeVisible();
|
||||
await expect(poOmniChats.table.findRowByName(visitorB)).not.toBeVisible();
|
||||
await expect(poOmniChats.btnSearchChip(visitorA)).toBeVisible();
|
||||
|
||||
await poOmniChats.inputSearch.fill('');
|
||||
await expect(poOmniChats.table.findRowByName(visitorA)).toBeVisible();
|
||||
await expect(poOmniChats.table.findRowByName(visitorB)).toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('expect to filter by Served By', async () => {
|
||||
await expect(poOmniChats.table.findRowByName(visitorA)).toBeVisible();
|
||||
await expect(poOmniChats.table.findRowByName(visitorB)).toBeVisible();
|
||||
|
||||
await poOmniChats.btnFilters.click();
|
||||
|
||||
// Select user1
|
||||
await poOmniChats.filters.selectServedBy('user1');
|
||||
await expect(poOmniChats.table.findRowByName(visitorA)).toBeVisible();
|
||||
await expect(poOmniChats.btnServedByChip('user1')).toBeVisible();
|
||||
await expect(poOmniChats.table.findRowByName(visitorB)).not.toBeVisible();
|
||||
|
||||
// Select user2
|
||||
await poOmniChats.btnServedByChip('user1').locator('i').click();
|
||||
await poOmniChats.filters.selectServedBy('user2');
|
||||
await expect(poOmniChats.table.findRowByName(visitorB)).toBeVisible();
|
||||
await expect(poOmniChats.table.findRowByName(visitorA)).not.toBeVisible();
|
||||
await expect(poOmniChats.btnServedByChip('user2')).toBeVisible();
|
||||
|
||||
// Select all users
|
||||
await poOmniChats.btnServedByChip('user2').locator('i').click();
|
||||
await poOmniChats.filters.selectServedBy('user1');
|
||||
await poOmniChats.filters.selectServedBy('user2');
|
||||
await expect(poOmniChats.table.findRowByName(visitorA)).toBeVisible();
|
||||
await expect(poOmniChats.table.findRowByName(visitorB)).toBeVisible();
|
||||
await poOmniChats.btnServedByChip('user1').locator('i').click();
|
||||
});
|
||||
|
||||
await test.step('expect to filter by status', async () => {
|
||||
await poOmniChats.filters.selectStatus('Closed');
|
||||
await expect(poOmniChats.table.findRowByName(visitorA)).not.toBeVisible();
|
||||
await expect(poOmniChats.table.findRowByName(visitorB)).not.toBeVisible();
|
||||
await expect(poOmniChats.table.findRowByName(visitorC)).toBeVisible();
|
||||
await expect(poOmniChats.btnStatusChip('Closed')).toBeVisible();
|
||||
|
||||
await poOmniChats.filters.selectStatus('Open');
|
||||
await expect(poOmniChats.table.findRowByName(visitorA)).not.toBeVisible();
|
||||
await expect(poOmniChats.table.findRowByName(visitorB)).toBeVisible();
|
||||
await expect(poOmniChats.table.findRowByName(visitorC)).not.toBeVisible();
|
||||
await expect(poOmniChats.btnStatusChip('Open')).toBeVisible();
|
||||
|
||||
await poOmniChats.filters.selectStatus('all');
|
||||
await expect(poOmniChats.table.findRowByName(visitorA)).toBeVisible();
|
||||
await expect(poOmniChats.table.findRowByName(visitorB)).toBeVisible();
|
||||
await expect(poOmniChats.table.findRowByName(visitorC)).toBeVisible();
|
||||
|
||||
await poOmniChats.filters.selectStatus('On hold');
|
||||
await expect(poOmniChats.table.findRowByName(visitorA)).toBeVisible();
|
||||
await expect(poOmniChats.table.findRowByName(visitorB)).not.toBeVisible();
|
||||
await expect(poOmniChats.table.findRowByName(visitorC)).not.toBeVisible();
|
||||
await expect(poOmniChats.btnStatusChip('On hold')).toBeVisible();
|
||||
await poOmniChats.btnStatusChip('On hold').locator('i').click();
|
||||
});
|
||||
|
||||
await test.step('expect to filter by department', async () => {
|
||||
// select department A
|
||||
await poOmniChats.filters.selectDepartment(departmentA.name);
|
||||
await expect(poOmniChats.table.findRowByName(visitorA)).toBeVisible();
|
||||
await expect(poOmniChats.table.findRowByName(visitorB)).not.toBeVisible();
|
||||
await expect(poOmniChats.table.findRowByName(visitorC)).not.toBeVisible();
|
||||
await expect(poOmniChats.btnDepartmentChip(departmentA.name)).toBeVisible();
|
||||
await poOmniChats.btnDepartmentChip(departmentA.name).locator('i').click();
|
||||
|
||||
// select department B
|
||||
await poOmniChats.filters.selectDepartment(departmentB.name);
|
||||
await expect(poOmniChats.table.findRowByName(visitorA)).not.toBeVisible();
|
||||
await expect(poOmniChats.table.findRowByName(visitorB)).toBeVisible();
|
||||
await expect(poOmniChats.table.findRowByName(visitorC)).not.toBeVisible();
|
||||
await expect(poOmniChats.btnDepartmentChip(departmentB.name)).toBeVisible();
|
||||
await poOmniChats.btnDepartmentChip(departmentB.name).locator('i').click();
|
||||
|
||||
// select all departments
|
||||
await poOmniChats.filters.selectDepartment(departmentA.name);
|
||||
await poOmniChats.filters.selectDepartment(departmentB.name);
|
||||
await expect(poOmniChats.table.findRowByName(visitorA)).toBeVisible();
|
||||
await expect(poOmniChats.table.findRowByName(visitorB)).toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('expect to filter by tags', async () => {
|
||||
await poOmniChats.filters.selectTag(tagA.data.name);
|
||||
await expect(poOmniChats.table.findRowByName(visitorA)).toBeVisible();
|
||||
await expect(poOmniChats.table.findRowByName(visitorB)).not.toBeVisible();
|
||||
|
||||
await poOmniChats.filters.selectTag(tagB.data.name);
|
||||
await expect(poOmniChats.table.findRowByName(visitorA)).toBeVisible();
|
||||
await expect(poOmniChats.table.findRowByName(visitorB)).toBeVisible();
|
||||
|
||||
await poOmniChats.filters.removeTag(tagA.data.name);
|
||||
await expect(poOmniChats.table.findRowByName(visitorB)).toBeVisible();
|
||||
await expect(poOmniChats.table.findRowByName(visitorA)).not.toBeVisible();
|
||||
|
||||
await poOmniChats.filters.removeTag(tagB.data.name);
|
||||
await expect(poOmniChats.table.findRowByName(visitorB)).toBeVisible();
|
||||
await expect(poOmniChats.table.findRowByName(visitorA)).toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('expect to filter by units', async () => {
|
||||
// select unitA
|
||||
await poOmniChats.filters.selectUnit(unitA.name);
|
||||
await expect(poOmniChats.table.findRowByName(visitorA)).toBeVisible();
|
||||
await expect(poOmniChats.table.findRowByName(visitorB)).not.toBeVisible();
|
||||
await expect(poOmniChats.table.findRowByName(visitorC)).not.toBeVisible();
|
||||
await poOmniChats.btnUnitsChip(unitA.name).locator('i').click();
|
||||
|
||||
// select unitB
|
||||
await poOmniChats.filters.selectUnit(unitB.name);
|
||||
await expect(poOmniChats.table.findRowByName(visitorA)).not.toBeVisible();
|
||||
await expect(poOmniChats.table.findRowByName(visitorB)).toBeVisible();
|
||||
await expect(poOmniChats.table.findRowByName(visitorC)).not.toBeVisible();
|
||||
await poOmniChats.btnUnitsChip(unitB.name).locator('i').click();
|
||||
|
||||
// no unit selected
|
||||
await expect(poOmniChats.table.findRowByName(visitorA)).toBeVisible();
|
||||
await expect(poOmniChats.table.findRowByName(visitorB)).toBeVisible();
|
||||
await expect(poOmniChats.table.findRowByName(visitorC)).not.toBeVisible();
|
||||
});
|
||||
});
|
||||
|
||||
test('OC - Contact Center - Clear all applied Filters', async () => {
|
||||
const [departmentA] = departments.map(({ data }) => data);
|
||||
const [unitA] = units.map((unit) => unit.data);
|
||||
|
||||
await test.step('expect to display result as per applied filters ', async () => {
|
||||
await poOmniChats.btnFilters.click();
|
||||
await poOmniChats.filters.selectServedBy('user1');
|
||||
await poOmniChats.filters.selectStatus('On hold');
|
||||
await poOmniChats.filters.selectDepartment(departmentA.name);
|
||||
await poOmniChats.filters.selectTag(tagA.data.name);
|
||||
await poOmniChats.filters.selectUnit(unitA.name);
|
||||
await expect(poOmniChats.table.findRowByName(visitorA)).toBeVisible();
|
||||
await expect(poOmniChats.table.findRowByName(visitorB)).not.toBeVisible();
|
||||
await expect(poOmniChats.table.findRowByName(visitorC)).not.toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('expect to clear all filters ', async () => {
|
||||
await poOmniChats.filters.btnClearFilters.click();
|
||||
await expect(poOmniChats.table.findRowByName(visitorA)).toBeVisible();
|
||||
await expect(poOmniChats.table.findRowByName(visitorB)).toBeVisible();
|
||||
await expect(poOmniChats.table.findRowByName(visitorC)).toBeVisible();
|
||||
});
|
||||
});
|
||||
|
||||
test('OC - Contact Center - Close contextual bar with filter screen', async () => {
|
||||
await test.step('expect to close filters contextual bar ', async () => {
|
||||
await poOmniChats.btnFilters.click();
|
||||
await poOmniChats.filters.close();
|
||||
await expect(poOmniChats.btnFilters).toBeVisible();
|
||||
await expect(poOmniChats.filters.btnClearFilters).not.toBeVisible();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,84 @@
|
||||
import { faker } from '@faker-js/faker';
|
||||
|
||||
import { createFakeVisitor } from '../../mocks/data';
|
||||
import { IS_EE } from '../config/constants';
|
||||
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.skip(!IS_EE, 'Omnichannel Contact Review > Enterprise Only');
|
||||
|
||||
test.use({ storageState: Users.user1.state });
|
||||
|
||||
test.describe.serial('OC - Contact Review', () => {
|
||||
let poHomeChannel: HomeOmnichannel;
|
||||
|
||||
const customFieldName = faker.string.uuid();
|
||||
const visitorToken = faker.string.uuid();
|
||||
let conversation: Awaited<ReturnType<typeof createConversation>>;
|
||||
let customField: Awaited<ReturnType<typeof createCustomField>>;
|
||||
|
||||
test.beforeAll(async ({ api }) => {
|
||||
(
|
||||
await Promise.all([
|
||||
api.post('/livechat/users/agent', { username: 'user1' }),
|
||||
api.post('/livechat/users/manager', { username: 'user1' }),
|
||||
])
|
||||
).every((res) => expect(res.status()).toBe(200));
|
||||
|
||||
customField = await createCustomField(api, { field: customFieldName });
|
||||
});
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
poHomeChannel = new HomeOmnichannel(page);
|
||||
});
|
||||
|
||||
test.beforeEach(async () => {
|
||||
await poHomeChannel.goto();
|
||||
});
|
||||
|
||||
test.beforeEach(async ({ api }) => {
|
||||
conversation = await createConversation(api, { visitorName: visitor.name, agentId: `user1`, visitorToken });
|
||||
});
|
||||
|
||||
test.beforeEach(async ({ api }) => {
|
||||
const resCustomFieldA = await api.post('/livechat/custom.field', {
|
||||
token: visitorToken,
|
||||
key: customFieldName,
|
||||
value: 'custom-field-value',
|
||||
overwrite: true,
|
||||
});
|
||||
|
||||
expect(resCustomFieldA.status()).toBe(200);
|
||||
|
||||
const resCustomFieldB = await api.post('/livechat/custom.field', {
|
||||
token: visitorToken,
|
||||
key: customFieldName,
|
||||
value: 'custom-field-value-2',
|
||||
overwrite: false,
|
||||
});
|
||||
|
||||
expect(resCustomFieldB.status()).toBe(200);
|
||||
});
|
||||
|
||||
test.afterAll(async ({ api }) => {
|
||||
(await Promise.all([api.delete('/livechat/users/agent/user1'), api.delete('/livechat/users/manager/user1')])).every((res) =>
|
||||
expect(res.status()).toBe(200),
|
||||
);
|
||||
|
||||
await conversation.delete();
|
||||
await customField.delete();
|
||||
});
|
||||
|
||||
test('OC - Contact Review - Update custom field conflicting', async () => {
|
||||
await poHomeChannel.sidebar.getSidebarItemByName(visitor.name).click();
|
||||
await poHomeChannel.roomToolbar.openContactInfo();
|
||||
await poHomeChannel.contacts.contactInfo.solveConflict(customFieldName, 'custom-field-value-2');
|
||||
|
||||
await expect(poHomeChannel.contacts.contactInfo.btnSeeConflicts).not.toBeVisible();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,61 @@
|
||||
import type { Page } from '@playwright/test';
|
||||
|
||||
import { createFakeVisitor } from '../../mocks/data';
|
||||
import { createAuxContext } from '../fixtures/createAuxContext';
|
||||
import { Users } from '../fixtures/userStates';
|
||||
import { HomeOmnichannel } from '../page-objects';
|
||||
import { OmnichannelLiveChat } from '../page-objects/omnichannel';
|
||||
import { expect, test } from '../utils/test';
|
||||
|
||||
test.describe('Omnichannel contact info', () => {
|
||||
let poLiveChat: OmnichannelLiveChat;
|
||||
let newVisitor: { email: string; name: string };
|
||||
|
||||
let agent: { page: Page; poHomeChannel: HomeOmnichannel };
|
||||
|
||||
test.beforeAll(async ({ api, browser }) => {
|
||||
newVisitor = createFakeVisitor();
|
||||
|
||||
// Set user user 1 as manager and agent
|
||||
await api.post('/livechat/users/agent', { username: 'user1' });
|
||||
await api.post('/livechat/users/manager', { username: 'user1' });
|
||||
|
||||
const { page } = await createAuxContext(browser, Users.user1);
|
||||
agent = { page, poHomeChannel: new HomeOmnichannel(page) };
|
||||
});
|
||||
test.beforeEach(async ({ page, api }) => {
|
||||
poLiveChat = new OmnichannelLiveChat(page, api);
|
||||
});
|
||||
|
||||
test.afterAll(async ({ api }) => {
|
||||
await api.delete('/livechat/users/agent/user1');
|
||||
await api.delete('/livechat/users/manager/user1');
|
||||
await agent.page.close();
|
||||
});
|
||||
|
||||
test('Receiving a message from visitor, and seeing its information', async () => {
|
||||
await test.step('Expect send a message as a visitor', async () => {
|
||||
await poLiveChat.goto();
|
||||
await poLiveChat.openLiveChat();
|
||||
await poLiveChat.sendMessage(newVisitor, false);
|
||||
await poLiveChat.onlineAgentMessage.type('this_a_test_message_from_visitor');
|
||||
await poLiveChat.btnSendMessageToOnlineAgent.click();
|
||||
});
|
||||
|
||||
await test.step('Expect to have 1 omnichannel assigned to agent 1', async () => {
|
||||
await agent.poHomeChannel.navbar.openChat(newVisitor.name);
|
||||
});
|
||||
|
||||
await test.step('Expect to be able to see contact information and edit', async () => {
|
||||
await agent.poHomeChannel.roomToolbar.openContactInfo();
|
||||
await agent.poHomeChannel.contacts.contactInfo.btnEdit.click();
|
||||
});
|
||||
|
||||
await test.step('Expect to update room name and subscription when updating contact name', async () => {
|
||||
await agent.poHomeChannel.contacts.editContact.inputName.fill('Edited Contact Name');
|
||||
await agent.poHomeChannel.contacts.editContact.btnSave.click();
|
||||
await expect(agent.poHomeChannel.sidebar.channelsList.getByText('Edited Contact Name')).toBeVisible();
|
||||
await expect(agent.poHomeChannel.content.channelHeader.getByText('Edited Contact Name')).toBeVisible();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,70 @@
|
||||
import type { Page } from '@playwright/test';
|
||||
|
||||
import { createFakeVisitor } from '../../mocks/data';
|
||||
import { IS_EE } from '../config/constants';
|
||||
import { createAuxContext } from '../fixtures/createAuxContext';
|
||||
import { Users } from '../fixtures/userStates';
|
||||
import { HomeChannel } from '../page-objects';
|
||||
import { OmnichannelLiveChat } from '../page-objects/omnichannel';
|
||||
import { expect, test } from '../utils/test';
|
||||
|
||||
test.describe('OC - Contact Unknown Callout', () => {
|
||||
test.skip(!IS_EE, 'Enterprise Only');
|
||||
|
||||
let poLiveChat: OmnichannelLiveChat;
|
||||
let newVisitor: { email: string; name: string };
|
||||
|
||||
let agent: { page: Page; poHomeChannel: HomeChannel };
|
||||
|
||||
test.beforeAll(async ({ api, browser }) => {
|
||||
newVisitor = createFakeVisitor();
|
||||
|
||||
await api.post('/livechat/users/agent', { username: 'user1' });
|
||||
await api.post('/livechat/users/manager', { username: 'user1' });
|
||||
|
||||
const { page } = await createAuxContext(browser, Users.user1);
|
||||
agent = { page, poHomeChannel: new HomeChannel(page) };
|
||||
});
|
||||
test.beforeEach(async ({ page, api }) => {
|
||||
poLiveChat = new OmnichannelLiveChat(page, api);
|
||||
});
|
||||
|
||||
test.beforeEach('create livechat conversation', async () => {
|
||||
await poLiveChat.goto();
|
||||
await poLiveChat.openLiveChat();
|
||||
await poLiveChat.sendMessage(newVisitor, false);
|
||||
await poLiveChat.onlineAgentMessage.type('this_a_test_message_from_visitor');
|
||||
await poLiveChat.btnSendMessageToOnlineAgent.click();
|
||||
});
|
||||
|
||||
test.afterEach('close livechat conversation', async () => {
|
||||
await poLiveChat.closeChat();
|
||||
});
|
||||
|
||||
test.afterAll(async ({ api }) => {
|
||||
await api.delete('/livechat/users/agent/user1');
|
||||
await api.delete('/livechat/users/manager/user1');
|
||||
await agent.page.close();
|
||||
});
|
||||
|
||||
test('OC - Contact Unknown Callout - Dismiss callout', async () => {
|
||||
await test.step('expect to open conversation', async () => {
|
||||
await agent.poHomeChannel.navbar.openChat(newVisitor.name);
|
||||
});
|
||||
|
||||
await test.step('expect contact unknown callout to be visible', async () => {
|
||||
await expect(agent.poHomeChannel.content.contactUnknownCallout).toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('expect to hide callout when dismiss is clicked', async () => {
|
||||
await agent.poHomeChannel.content.btnDismissContactUnknownCallout.click();
|
||||
await expect(agent.poHomeChannel.content.contactUnknownCallout).not.toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('expect keep callout hidden after changing pages', async () => {
|
||||
await agent.poHomeChannel.navbar.btnHome.click();
|
||||
await agent.poHomeChannel.navbar.openChat(newVisitor.name);
|
||||
await expect(agent.poHomeChannel.content.contactUnknownCallout).not.toBeVisible();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -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<ReturnType<typeof createAgent>>;
|
||||
let manager: Awaited<ReturnType<typeof createManager>>;
|
||||
let conversation: Awaited<ReturnType<typeof createConversation>>;
|
||||
let roomCustomField: Awaited<ReturnType<typeof createCustomField>>;
|
||||
let visitorCustomField: Awaited<ReturnType<typeof createCustomField>>;
|
||||
|
||||
test.beforeAll('Set up agent, manager and custom fields', async ({ api }) => {
|
||||
[agent, manager] = await Promise.all([createAgent(api, 'user1'), createManager(api, 'user1')]);
|
||||
|
||||
[roomCustomField, visitorCustomField] = await Promise.all([
|
||||
createCustomField(api, {
|
||||
field: roomCustomFieldLabel,
|
||||
label: roomCustomFieldName,
|
||||
scope: 'room',
|
||||
}),
|
||||
createCustomField(api, {
|
||||
field: visitorCustomFieldLabel,
|
||||
label: visitorCustomFieldName,
|
||||
scope: 'visitor',
|
||||
}),
|
||||
]);
|
||||
});
|
||||
|
||||
test.beforeEach(async ({ page, api }) => {
|
||||
poHomeChannel = new HomeOmnichannel(page);
|
||||
await poHomeChannel.goto();
|
||||
|
||||
conversation = await createConversation(api, {
|
||||
visitorName: visitor.name,
|
||||
agentId: 'user1',
|
||||
visitorToken,
|
||||
});
|
||||
|
||||
await setVisitorCustomFieldValue(api, {
|
||||
token: visitorToken,
|
||||
customFieldId: visitorCustomField.customField._id,
|
||||
value: visitorCustomFieldValue,
|
||||
});
|
||||
});
|
||||
|
||||
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 poHomeChannel.contacts.contactInfo.waitForDisplay();
|
||||
});
|
||||
|
||||
await test.step('Assert custom field is set successfully', async () => {
|
||||
await expect(poHomeChannel.contacts.contactInfo.getInfoByValue(visitorCustomFieldValue)).toBeVisible();
|
||||
});
|
||||
});
|
||||
|
||||
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 poHomeChannel.contacts.contactInfo.waitForDisplay();
|
||||
});
|
||||
|
||||
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.getInfoByValue(updatedVisitorCustomFieldValue)).toBeVisible();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,47 @@
|
||||
import { Users } from '../fixtures/userStates';
|
||||
import { OmnichannelCustomFields } from '../page-objects/omnichannel';
|
||||
import { test, expect } from '../utils/test';
|
||||
|
||||
test.use({ storageState: Users.admin.state });
|
||||
|
||||
test.describe('omnichannel-customFields', () => {
|
||||
let poOmnichannelCustomFields: OmnichannelCustomFields;
|
||||
const newField = 'any_field';
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
poOmnichannelCustomFields = new OmnichannelCustomFields(page);
|
||||
await poOmnichannelCustomFields.goto();
|
||||
});
|
||||
|
||||
test('expect add new "custom field"', async ({ page }) => {
|
||||
await poOmnichannelCustomFields.createNew();
|
||||
|
||||
await page.waitForURL('/omnichannel/customfields/new');
|
||||
await poOmnichannelCustomFields.manageCustomFields.inputField.fill(newField);
|
||||
await poOmnichannelCustomFields.manageCustomFields.inputLabel.fill('any_label');
|
||||
await poOmnichannelCustomFields.manageCustomFields.save();
|
||||
|
||||
await expect(poOmnichannelCustomFields.table.findRowByName(newField)).toBeVisible();
|
||||
});
|
||||
|
||||
test('expect update "newField"', async () => {
|
||||
const newLabel = 'new_any_label';
|
||||
await poOmnichannelCustomFields.inputSearch.fill(newField);
|
||||
await poOmnichannelCustomFields.table.findRowByName(newField).click();
|
||||
|
||||
await poOmnichannelCustomFields.manageCustomFields.inputLabel.fill('new_any_label');
|
||||
await poOmnichannelCustomFields.manageCustomFields.labelVisible.click();
|
||||
await poOmnichannelCustomFields.manageCustomFields.save();
|
||||
|
||||
await expect(poOmnichannelCustomFields.table.findRowByName(newField)).toContainText(newLabel);
|
||||
});
|
||||
|
||||
test('expect remove "new_field"', async () => {
|
||||
await poOmnichannelCustomFields.inputSearch.fill(newField);
|
||||
await poOmnichannelCustomFields.table.findRowByName(newField).click();
|
||||
await poOmnichannelCustomFields.deleteCustomField(newField);
|
||||
|
||||
await poOmnichannelCustomFields.inputSearch.fill(newField);
|
||||
await expect(poOmnichannelCustomFields.table.findRowByName(newField)).toBeHidden();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,39 @@
|
||||
import { faker } from '@faker-js/faker';
|
||||
|
||||
import { IS_EE } from '../config/constants';
|
||||
import { Users } from '../fixtures/userStates';
|
||||
import { OmnichannelDepartments } from '../page-objects/omnichannel';
|
||||
import { test, expect } from '../utils/test';
|
||||
|
||||
test.use({ storageState: Users.admin.state });
|
||||
|
||||
test.describe.serial('OC - Manage Departments (CE)', () => {
|
||||
test.skip(IS_EE, 'Community Edition Only');
|
||||
let poOmnichannelDepartments: OmnichannelDepartments;
|
||||
let departmentName: string;
|
||||
|
||||
test.beforeAll(async () => {
|
||||
departmentName = faker.string.uuid();
|
||||
});
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
poOmnichannelDepartments = new OmnichannelDepartments(page);
|
||||
await poOmnichannelDepartments.goto();
|
||||
});
|
||||
|
||||
test('OC - Manage Departments (CE) - Create department', async () => {
|
||||
await test.step('expect create new department', async () => {
|
||||
await poOmnichannelDepartments.createNew();
|
||||
await poOmnichannelDepartments.createDepartment(departmentName, faker.internet.email());
|
||||
|
||||
await poOmnichannelDepartments.inputSearch.fill(departmentName);
|
||||
await expect(poOmnichannelDepartments.table.findRowByName(departmentName)).toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('expect to not be possible adding a second department ', async () => {
|
||||
await poOmnichannelDepartments.createNew();
|
||||
await poOmnichannelDepartments.upsellDepartmentsModal.waitForDisplay();
|
||||
await poOmnichannelDepartments.upsellDepartmentsModal.close();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,256 @@
|
||||
import { faker } from '@faker-js/faker';
|
||||
import type { Page } from '@playwright/test';
|
||||
|
||||
import { IS_EE } from '../config/constants';
|
||||
import { Users } from '../fixtures/userStates';
|
||||
import { OmnichannelDepartments } from '../page-objects/omnichannel';
|
||||
import { createAgent } from '../utils/omnichannel/agents';
|
||||
import { createDepartment, deleteDepartment } from '../utils/omnichannel/departments';
|
||||
import { test, expect } from '../utils/test';
|
||||
|
||||
const ERROR = {
|
||||
requiredName: 'Name required',
|
||||
requiredEmail: 'Email required',
|
||||
invalidEmail: 'Invalid email address',
|
||||
};
|
||||
|
||||
test.use({ storageState: Users.admin.state });
|
||||
|
||||
test.describe('OC - Manage Departments', () => {
|
||||
test.skip(!IS_EE, 'Enterprise Edition Only');
|
||||
|
||||
let poOmnichannelDepartments: OmnichannelDepartments;
|
||||
let agent: Awaited<ReturnType<typeof createAgent>>;
|
||||
|
||||
test.beforeAll(async ({ api }) => {
|
||||
// turn on department removal
|
||||
await api.post('/settings/Omnichannel_enable_department_removal', { value: true });
|
||||
agent = await createAgent(api, 'user1');
|
||||
});
|
||||
|
||||
test.afterAll(async ({ api }) => {
|
||||
// turn off department removal
|
||||
await api.post('/settings/Omnichannel_enable_department_removal', { value: false });
|
||||
await agent.delete();
|
||||
});
|
||||
|
||||
test.describe('Create first department', async () => {
|
||||
test.beforeEach(async ({ page }: { page: Page }) => {
|
||||
poOmnichannelDepartments = new OmnichannelDepartments(page);
|
||||
await poOmnichannelDepartments.goto();
|
||||
});
|
||||
|
||||
test('Create department', async ({ page }) => {
|
||||
const departmentName = faker.string.uuid();
|
||||
|
||||
await poOmnichannelDepartments.createNew();
|
||||
|
||||
await test.step('expect name and email to be required', async () => {
|
||||
await expect(poOmnichannelDepartments.errorMessage(ERROR.requiredName)).not.toBeVisible();
|
||||
await poOmnichannelDepartments.btnSave.click();
|
||||
await expect(poOmnichannelDepartments.errorMessage(ERROR.requiredName)).toBeVisible();
|
||||
await expect(poOmnichannelDepartments.errorMessage(ERROR.requiredEmail)).toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('expect to fill required fields', async () => {
|
||||
await poOmnichannelDepartments.labelEnabled.click();
|
||||
await poOmnichannelDepartments.inputName.fill(departmentName);
|
||||
await poOmnichannelDepartments.inputEmail.fill(faker.internet.email());
|
||||
});
|
||||
|
||||
await test.step('expect to fetch agents a reasonable number of times', async () => {
|
||||
let requestCount = 0;
|
||||
|
||||
await page.route('**/v1/livechat/users/agent*', async (route) => {
|
||||
requestCount++;
|
||||
await route.continue();
|
||||
});
|
||||
|
||||
await poOmnichannelDepartments.inputAgents.click();
|
||||
await poOmnichannelDepartments.inputAgents.fill('user1');
|
||||
|
||||
await page.waitForTimeout(1000);
|
||||
await expect(requestCount).toBeGreaterThan(0);
|
||||
await expect(requestCount).toBeLessThan(3);
|
||||
|
||||
await poOmnichannelDepartments.inputAgents.click();
|
||||
});
|
||||
|
||||
await test.step('expect to add an agent', async () => {
|
||||
await poOmnichannelDepartments.inputAgents.click();
|
||||
await poOmnichannelDepartments.inputAgents.fill('user1');
|
||||
await poOmnichannelDepartments.findOption('user1 (@user1)').click();
|
||||
await poOmnichannelDepartments.btnAddAgent.click();
|
||||
await expect(poOmnichannelDepartments.agentsTable.findRowByName('user1')).toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('expect create new department', async () => {
|
||||
await poOmnichannelDepartments.btnSave.click();
|
||||
await poOmnichannelDepartments.search(departmentName);
|
||||
await expect(poOmnichannelDepartments.table.findRowByName(departmentName)).toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('expect to delete department', async () => {
|
||||
await poOmnichannelDepartments.search(departmentName);
|
||||
await poOmnichannelDepartments.getDepartmentMenuByName(departmentName).click();
|
||||
await poOmnichannelDepartments.menuDeleteOption.click();
|
||||
|
||||
await test.step('expect confirm delete department', async () => {
|
||||
await test.step('expect delete to be disabled when name is incorrect', async () => {
|
||||
await expect(poOmnichannelDepartments.deleteModal.btnDelete).toBeDisabled();
|
||||
await poOmnichannelDepartments.deleteModal.inputConfirmDepartmentName.fill('someramdomname');
|
||||
await expect(poOmnichannelDepartments.deleteModal.btnDelete).toBeDisabled();
|
||||
});
|
||||
|
||||
await test.step('expect to successfuly delete if department name is correct', async () => {
|
||||
await expect(poOmnichannelDepartments.deleteModal.btnDelete).toBeDisabled();
|
||||
await poOmnichannelDepartments.deleteModal.inputConfirmDepartmentName.fill(departmentName);
|
||||
await expect(poOmnichannelDepartments.deleteModal.btnDelete).toBeEnabled();
|
||||
await poOmnichannelDepartments.deleteModal.deleteDepartment(departmentName);
|
||||
});
|
||||
});
|
||||
|
||||
await test.step('expect department to have been deleted', async () => {
|
||||
await poOmnichannelDepartments.search(departmentName);
|
||||
await expect(poOmnichannelDepartments.table.findRowByName(departmentName)).toHaveCount(0);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('After creation', async () => {
|
||||
let department: Awaited<ReturnType<typeof createDepartment>>['data'];
|
||||
|
||||
test.beforeEach(async ({ api, page }) => {
|
||||
poOmnichannelDepartments = new OmnichannelDepartments(page);
|
||||
|
||||
department = await createDepartment(api).then((res) => res.data);
|
||||
await poOmnichannelDepartments.goto();
|
||||
});
|
||||
|
||||
test.afterEach(async ({ api }) => {
|
||||
await deleteDepartment(api, { id: department._id });
|
||||
});
|
||||
|
||||
test('Edit department', async () => {
|
||||
await test.step('expect create new department', async () => {
|
||||
await poOmnichannelDepartments.search(department.name);
|
||||
await expect(poOmnichannelDepartments.table.findRowByName(department.name)).toBeVisible();
|
||||
|
||||
return department;
|
||||
});
|
||||
|
||||
await test.step('expect update department name', async () => {
|
||||
await poOmnichannelDepartments.search(department.name);
|
||||
await poOmnichannelDepartments.getDepartmentMenuByName(department.name).click();
|
||||
await poOmnichannelDepartments.menuEditOption.click();
|
||||
|
||||
await poOmnichannelDepartments.inputName.fill(`edited-${department.name}`);
|
||||
await poOmnichannelDepartments.btnSave.click();
|
||||
|
||||
await poOmnichannelDepartments.search(`edited-${department.name}`);
|
||||
await expect(poOmnichannelDepartments.table.findRowByName(`edited-${department.name}`)).toBeVisible();
|
||||
});
|
||||
});
|
||||
|
||||
test('Archive department', async () => {
|
||||
await test.step('expect create new department', async () => {
|
||||
await poOmnichannelDepartments.search(department.name);
|
||||
await expect(poOmnichannelDepartments.table.findRowByName(department.name)).toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('expect archive department', async () => {
|
||||
await poOmnichannelDepartments.search(department.name);
|
||||
await expect(poOmnichannelDepartments.table.findRowByName(department.name)).toBeVisible();
|
||||
|
||||
await poOmnichannelDepartments.archiveDepartmentByName(department.name);
|
||||
await poOmnichannelDepartments.tabArchivedDepartments.click();
|
||||
await poOmnichannelDepartments.search(department.name);
|
||||
await expect(poOmnichannelDepartments.table.findRowByName(department.name)).toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('expect archived department to not be editable', async () => {
|
||||
await poOmnichannelDepartments.getDepartmentMenuByName(department.name).click();
|
||||
await expect(poOmnichannelDepartments.menuEditOption).not.toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('expect unarchive department', async () => {
|
||||
await poOmnichannelDepartments.menuUnarchiveOption.click();
|
||||
await expect(poOmnichannelDepartments.table.findRowByName(department.name)).toHaveCount(0);
|
||||
});
|
||||
});
|
||||
|
||||
test('Request tag(s) before closing conversation', async () => {
|
||||
await test.step('should create new department', async () => {
|
||||
await poOmnichannelDepartments.search(department.name);
|
||||
await expect(poOmnichannelDepartments.table.findRowByName(department.name)).toBeVisible();
|
||||
});
|
||||
|
||||
const tagName = faker.string.sample(5);
|
||||
await poOmnichannelDepartments.getDepartmentMenuByName(department.name).click();
|
||||
await poOmnichannelDepartments.menuEditOption.click();
|
||||
|
||||
await test.step('should be able to add a tag properly', async () => {
|
||||
await poOmnichannelDepartments.inputConversationClosingTags.fill(tagName);
|
||||
await poOmnichannelDepartments.btnAddTags.click();
|
||||
|
||||
await expect(poOmnichannelDepartments.btnTag(tagName)).toBeVisible();
|
||||
await expect(poOmnichannelDepartments.btnSave).toBeEnabled();
|
||||
});
|
||||
|
||||
await test.step('should be able to remove a tag properly', async () => {
|
||||
await poOmnichannelDepartments.btnTag(tagName).click();
|
||||
await expect(poOmnichannelDepartments.btnAddTags).toBeDisabled();
|
||||
});
|
||||
|
||||
await test.step('should not be possible to add empty tags', async () => {
|
||||
await poOmnichannelDepartments.inputConversationClosingTags.fill('');
|
||||
await expect(poOmnichannelDepartments.btnAddTags).toBeDisabled();
|
||||
});
|
||||
|
||||
await test.step('should not be possible to add same tag twice', async () => {
|
||||
const tagName = faker.string.sample(5);
|
||||
await poOmnichannelDepartments.inputConversationClosingTags.fill(tagName);
|
||||
await poOmnichannelDepartments.btnAddTags.click();
|
||||
await poOmnichannelDepartments.inputConversationClosingTags.fill(tagName);
|
||||
await expect(poOmnichannelDepartments.btnAddTags).toBeDisabled();
|
||||
});
|
||||
});
|
||||
|
||||
test('Toggle department removal', async ({ api, page }) => {
|
||||
await test.step('expect create new department', async () => {
|
||||
await poOmnichannelDepartments.search(department.name);
|
||||
await expect(poOmnichannelDepartments.table.findRowByName(department.name)).toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('expect to be able to delete department', async () => {
|
||||
await poOmnichannelDepartments.search(department.name);
|
||||
await poOmnichannelDepartments.getDepartmentMenuByName(department.name).click();
|
||||
await expect(poOmnichannelDepartments.menuDeleteOption).toBeEnabled();
|
||||
await page.keyboard.press('Escape');
|
||||
});
|
||||
|
||||
await test.step('expect to disable department removal setting', async () => {
|
||||
const statusCode = (await api.post('/settings/Omnichannel_enable_department_removal', { value: false })).status();
|
||||
expect(statusCode).toBe(200);
|
||||
});
|
||||
|
||||
await test.step('expect not to be able to delete department', async () => {
|
||||
await poOmnichannelDepartments.search(department.name);
|
||||
await poOmnichannelDepartments.getDepartmentMenuByName(department.name).click();
|
||||
await expect(poOmnichannelDepartments.menuDeleteOption).toBeDisabled();
|
||||
await page.keyboard.press('Escape');
|
||||
});
|
||||
|
||||
await test.step('expect to enable department removal setting', async () => {
|
||||
const statusCode = (await api.post('/settings/Omnichannel_enable_department_removal', { value: true })).status();
|
||||
expect(statusCode).toBe(200);
|
||||
});
|
||||
|
||||
await test.step('expect to delete department', async () => {
|
||||
const deleteRes = await deleteDepartment(api, { id: department._id });
|
||||
expect(deleteRes.status()).toBe(200);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,32 @@
|
||||
import type { Page } from '@playwright/test';
|
||||
|
||||
import { ADMIN_CREDENTIALS, IS_EE } from '../config/constants';
|
||||
import injectInitialData from '../fixtures/inject-initial-data';
|
||||
import { Login } from '../page-objects';
|
||||
import { test, expect } from '../utils/test';
|
||||
|
||||
// TODO: Replace this test with a unit test
|
||||
test.describe('OC - Enterprise Menu Items After Relogin', () => {
|
||||
// Create page object and redirect to home
|
||||
test.beforeEach(async ({ page }: { page: Page }) => {
|
||||
await new Login(page).goto('/omnichannel/current');
|
||||
|
||||
await page.locator('role=textbox[name=/username/i]').fill(ADMIN_CREDENTIALS.email);
|
||||
await page.locator('[name=password]').fill(ADMIN_CREDENTIALS.password);
|
||||
await page.locator('role=button[name="Login"]').click();
|
||||
|
||||
await page.locator('#main-content').waitFor();
|
||||
});
|
||||
|
||||
// Delete all data
|
||||
test.afterAll(async () => {
|
||||
await injectInitialData();
|
||||
});
|
||||
|
||||
test('OC - Enterprise Menu Items - Logout & Login', async ({ page }) => {
|
||||
test.skip(!IS_EE);
|
||||
await test.step('expect EE menu items to be visible', async () => {
|
||||
await expect(page.locator('a[href="/omnichannel/tags"]')).toBeVisible();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,129 @@
|
||||
import type { Page } from '@playwright/test';
|
||||
|
||||
import { createFakeVisitor } from '../../mocks/data';
|
||||
import { IS_EE } from '../config/constants';
|
||||
import { createAuxContext } from '../fixtures/createAuxContext';
|
||||
import { Users } from '../fixtures/userStates';
|
||||
import { HomeOmnichannel } from '../page-objects';
|
||||
import { OmnichannelLiveChat } from '../page-objects/omnichannel';
|
||||
import { setSettingValueById } from '../utils';
|
||||
import { createAgent, makeAgentAvailable } from '../utils/omnichannel/agents';
|
||||
import { test, expect } from '../utils/test';
|
||||
|
||||
test.use({ storageState: Users.user1.state });
|
||||
|
||||
test.describe('OC - Routing to Idle Agents', () => {
|
||||
test.skip(!IS_EE, 'Enterprise Edition Only');
|
||||
|
||||
let poHomeOmnichannel: HomeOmnichannel;
|
||||
let poLivechat: OmnichannelLiveChat;
|
||||
|
||||
let livechatPage: Page | undefined;
|
||||
|
||||
let agent: Awaited<ReturnType<typeof createAgent>>;
|
||||
let visitor: { name: string; email: string };
|
||||
|
||||
const routingMethods = ['Auto_Selection', 'Load_Balancing', 'Load_Rotation'];
|
||||
|
||||
test.beforeAll(async ({ api }) => {
|
||||
agent = await createAgent(api, 'user1');
|
||||
await expect(agent.response).toBeOK();
|
||||
|
||||
const settingResponses = await Promise.all([
|
||||
setSettingValueById(api, 'Accounts_Default_User_Preferences_idleTimeLimit', 300),
|
||||
setSettingValueById(api, 'Omnichannel_enable_department_removal', true),
|
||||
]);
|
||||
|
||||
for (const response of settingResponses) {
|
||||
await expect(response).toBeOK();
|
||||
}
|
||||
});
|
||||
|
||||
test.beforeEach(async ({ page, browser, api }) => {
|
||||
visitor = createFakeVisitor();
|
||||
await expect(await makeAgentAvailable(api, agent.data._id)).toBeOK();
|
||||
|
||||
poHomeOmnichannel = new HomeOmnichannel(page);
|
||||
await poHomeOmnichannel.goto();
|
||||
await expect(poHomeOmnichannel.navbar.getUserStatusBadge('online')).toBeVisible();
|
||||
|
||||
({ page: livechatPage } = await createAuxContext(browser, Users.user1, '/livechat', false));
|
||||
poLivechat = new OmnichannelLiveChat(livechatPage, api);
|
||||
});
|
||||
|
||||
test.afterEach(async ({ api }) => {
|
||||
if (livechatPage) {
|
||||
await livechatPage.context().close();
|
||||
}
|
||||
|
||||
await expect(await setSettingValueById(api, 'Accounts_Default_User_Preferences_idleTimeLimit', 300)).toBeOK();
|
||||
});
|
||||
|
||||
test.afterAll(async ({ api }) => {
|
||||
const responses = await Promise.all([
|
||||
agent.delete(),
|
||||
setSettingValueById(api, 'Livechat_Routing_Method', 'Auto_Selection'),
|
||||
setSettingValueById(api, 'Livechat_enabled_when_agent_idle', false),
|
||||
setSettingValueById(api, 'Omnichannel_enable_department_removal', false),
|
||||
]);
|
||||
|
||||
for (const response of responses) {
|
||||
await expect(response).toBeOK();
|
||||
}
|
||||
});
|
||||
|
||||
routingMethods.forEach((routingMethod) => {
|
||||
test.describe(`Routing method: ${routingMethod}`, () => {
|
||||
test(`should not route to idle agents`, async ({ api }) => {
|
||||
await test.step(`Setup routing method to ${routingMethod} and ignore idle agents`, async () => {
|
||||
await expect(await setSettingValueById(api, 'Livechat_Routing_Method', routingMethod)).toBeOK();
|
||||
await expect(await setSettingValueById(api, 'Livechat_enabled_when_agent_idle', false)).toBeOK();
|
||||
});
|
||||
|
||||
await test.step('Visitor tries to initiate a conversation with the away agent', async () => {
|
||||
await poLivechat.openAnyLiveChat();
|
||||
await poLivechat.sendMessage(visitor, false);
|
||||
await poLivechat.onlineAgentMessage.fill('Hello from visitor');
|
||||
|
||||
// Force Agent to become away by idle timeout
|
||||
await expect(await setSettingValueById(api, 'Accounts_Default_User_Preferences_idleTimeLimit', 1)).toBeOK();
|
||||
await poHomeOmnichannel.page.reload();
|
||||
await expect(poHomeOmnichannel.navbar.getUserStatusBadge('away')).toBeVisible();
|
||||
|
||||
await poLivechat.btnSendMessageToOnlineAgent.click();
|
||||
});
|
||||
|
||||
await test.step('Verify visitor is not taken by agent', async () => {
|
||||
await expect(
|
||||
poLivechat.alertMessage('Error starting a new conversation: Sorry, no online agents [no-agent-online]'),
|
||||
).toBeVisible();
|
||||
});
|
||||
});
|
||||
|
||||
test(`should route to agents even if they are idle when setting is enabled`, async ({ api }) => {
|
||||
await test.step(`Setup routing method to ${routingMethod} and allow idle agents`, async () => {
|
||||
await expect(await setSettingValueById(api, 'Livechat_Routing_Method', routingMethod)).toBeOK();
|
||||
await expect(await setSettingValueById(api, 'Livechat_enabled_when_agent_idle', true)).toBeOK();
|
||||
});
|
||||
|
||||
await test.step('Force agent to become away by idle timeout', async () => {
|
||||
await expect(await setSettingValueById(api, 'Accounts_Default_User_Preferences_idleTimeLimit', 1)).toBeOK();
|
||||
await poHomeOmnichannel.page.reload();
|
||||
await expect(poHomeOmnichannel.navbar.getUserStatusBadge('away')).toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('Visitor initiates chat', async () => {
|
||||
await poLivechat.openAnyLiveChatAndSendMessage({
|
||||
liveChatUser: visitor,
|
||||
message: 'test message',
|
||||
isOffline: false,
|
||||
});
|
||||
});
|
||||
|
||||
await test.step('Verify chat is served to an agent', async () => {
|
||||
await expect(poLivechat.headerTitle).toHaveText(agent.data.username);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,927 @@
|
||||
import { faker } from '@faker-js/faker/locale/af_ZA';
|
||||
import type { Page } from '@playwright/test';
|
||||
|
||||
import { createFakeVisitor } from '../../mocks/data';
|
||||
import { IS_EE } from '../config/constants';
|
||||
import { createAuxContext } from '../fixtures/createAuxContext';
|
||||
import { Users } from '../fixtures/userStates';
|
||||
import { HomeOmnichannel } from '../page-objects';
|
||||
import { OmnichannelLiveChatEmbedded } from '../page-objects/omnichannel';
|
||||
import { createAgent } from '../utils/omnichannel/agents';
|
||||
import { addAgentToDepartment, createDepartment } from '../utils/omnichannel/departments';
|
||||
import { test, expect } from '../utils/test';
|
||||
|
||||
// TODO: Use official widget typing once that is merged
|
||||
declare const window: Window & {
|
||||
// TODO: Improve tests to no longer use window object properties
|
||||
onPrechatFormSubmit: boolean;
|
||||
onAssignAgent: boolean;
|
||||
onAgentStatusChange: boolean;
|
||||
onOfflineFormSubmit: boolean;
|
||||
onChatStarted: boolean;
|
||||
onChatEnded: boolean;
|
||||
|
||||
RocketChat: {
|
||||
livechat: {
|
||||
clearBusinessUnit: () => void;
|
||||
clearDepartment: () => void;
|
||||
initialize: () => void;
|
||||
maximizeWidget: () => void;
|
||||
minimizeWidget: () => void;
|
||||
hideWidget: () => void;
|
||||
showWidget: () => void;
|
||||
pageVisited: () => void;
|
||||
registerGuest: (visitor: { name: string; email: string; token: string }) => void;
|
||||
setAgent: (agent: { username: string; _id: string }) => void;
|
||||
setBusinessUnit: (businessUnit?: string) => void;
|
||||
setCustomField: (field: { key: string; value: string }) => void;
|
||||
setDepartment: (dep: string) => void;
|
||||
setGuestEmail: (email: string) => void;
|
||||
setGuestName: (name: string) => void;
|
||||
setGuestToken: (token: string) => void;
|
||||
setParentUrl: (url: string) => void;
|
||||
setTheme: (theme: {
|
||||
color?: string;
|
||||
fontColor?: string;
|
||||
iconColor?: string;
|
||||
title?: string;
|
||||
offlineTitle?: string;
|
||||
hideExpandChat?: boolean;
|
||||
}) => void;
|
||||
setLanguage: (language: string) => void;
|
||||
transferChat: (department: string) => void;
|
||||
onChatMaximized: (callback: () => void) => void;
|
||||
onChatMinimized: (callback: () => void) => void;
|
||||
onChatStarted: (callback: () => void) => void;
|
||||
onChatEnded: (callback: () => void) => void;
|
||||
onPrechatFormSubmit: (callback: () => void) => void;
|
||||
onAssignAgent: (callback: () => void) => void;
|
||||
onAgentStatusChange: (callback: () => void) => void;
|
||||
onOfflineFormSubmit: (callback: () => void) => void;
|
||||
onWidgetHidden: (callback: () => void) => void;
|
||||
onWidgetShown: (callback: () => void) => void;
|
||||
onServiceOffline: (callback: () => void) => void;
|
||||
onQueuePositionChange: (callback: () => void) => void;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
const createFakeVisitorRegistration = (extra?: { department?: string }) => ({
|
||||
...createFakeVisitor(),
|
||||
token: faker.string.uuid(),
|
||||
...extra,
|
||||
});
|
||||
|
||||
test.describe('OC - Livechat API', () => {
|
||||
// TODO: Check if there is a way to add livechat to the global window object
|
||||
|
||||
test.describe('Basic Widget Interactions', () => {
|
||||
// Tests that rely only on the widget itself, without requiring further interaction from the main RC app
|
||||
let poAuxContext: { page: Page; poHomeOmnichannel: HomeOmnichannel };
|
||||
let poLiveChat: OmnichannelLiveChatEmbedded;
|
||||
let page: Page;
|
||||
let agent: Awaited<ReturnType<typeof createAgent>>;
|
||||
|
||||
test.beforeAll(async ({ browser, api }) => {
|
||||
agent = await createAgent(api, 'user1');
|
||||
|
||||
page = await browser.newPage();
|
||||
|
||||
poLiveChat = new OmnichannelLiveChatEmbedded(page);
|
||||
|
||||
const { page: pageCtx } = await createAuxContext(browser, Users.user1);
|
||||
poAuxContext = { page: pageCtx, poHomeOmnichannel: new HomeOmnichannel(pageCtx) };
|
||||
|
||||
await poLiveChat.goto();
|
||||
});
|
||||
|
||||
test.afterAll(async () => {
|
||||
await Promise.all([poAuxContext.page.close(), agent.delete(), page.close()]);
|
||||
});
|
||||
|
||||
test('OC - Livechat API - Open and Close widget', async () => {
|
||||
await test.step('Expect widget to be visible after maximizeWidget()', async () => {
|
||||
await poLiveChat.page.evaluate(() => window.RocketChat.livechat.maximizeWidget());
|
||||
|
||||
await expect(page.frameLocator('#rocketchat-iframe').getByText('Start Chat')).toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('Expect widget not be visible after minimizeWidget()', async () => {
|
||||
await poLiveChat.page.evaluate(() => window.RocketChat.livechat.minimizeWidget());
|
||||
|
||||
await expect(page.frameLocator('#rocketchat-iframe').getByText('Start Chat')).not.toBeVisible();
|
||||
});
|
||||
});
|
||||
|
||||
test('OC - Livechat API - Show and Hide widget', async () => {
|
||||
await test.step('Expect livechat button not be visible after minimizeWidget()', async () => {
|
||||
await poLiveChat.page.evaluate(() => window.RocketChat.livechat.hideWidget());
|
||||
|
||||
await expect(page.frameLocator('#rocketchat-iframe').getByRole('button', { name: 'Rocket.Chat' })).not.toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('Expect livechat button to be visible after show()', async () => {
|
||||
await poLiveChat.page.evaluate(() => window.RocketChat.livechat.showWidget());
|
||||
|
||||
await expect(page.frameLocator('#rocketchat-iframe').getByRole('button', { name: 'Rocket.Chat' })).toBeVisible();
|
||||
});
|
||||
});
|
||||
|
||||
test.skip('OC - Livechat API - setAgent', async () => {
|
||||
// Set agent does not actually set the agent, it just sets the default agent on the widget state
|
||||
// Maybe that is used in an integration? Since as it is now, when the user starts a chat, the agent will be overriden
|
||||
// TODO: Find the use case of the setAgent method
|
||||
await test.step('Expect setAgent to do something', async () => {
|
||||
await poLiveChat.page.evaluate(() => window.RocketChat.livechat.setAgent({ username: 'user1', _id: 'user1' }));
|
||||
});
|
||||
});
|
||||
|
||||
test('OC - Livechat API - setLanguage', async () => {
|
||||
await test.step('Expect language to be pt-BR', async () => {
|
||||
await poLiveChat.page.evaluate(() => window.RocketChat.livechat.maximizeWidget());
|
||||
|
||||
await poLiveChat.page.evaluate(() => window.RocketChat.livechat.setLanguage('pt-BR'));
|
||||
|
||||
await expect(
|
||||
page.frameLocator('#rocketchat-iframe').getByText('Por favor, conte-nos algumas informações para iniciarmos o chat'),
|
||||
).toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('Expect language to be en', async () => {
|
||||
await poLiveChat.page.evaluate(() => window.RocketChat.livechat.setLanguage('en'));
|
||||
|
||||
await expect(page.frameLocator('#rocketchat-iframe').getByText('Please, tell us some information to start the chat')).toBeVisible();
|
||||
});
|
||||
});
|
||||
|
||||
test('OC - Livechat API - setTheme', async () => {
|
||||
const registerGuestVisitor = createFakeVisitorRegistration();
|
||||
|
||||
await test.step('Expect setTheme set color', async () => {
|
||||
await poLiveChat.page.evaluate(() => {
|
||||
window.RocketChat.livechat.maximizeWidget();
|
||||
window.RocketChat.livechat.setTheme({ color: 'rgb(50, 50, 50)' });
|
||||
});
|
||||
|
||||
await expect(page.frameLocator('#rocketchat-iframe').locator('header')).toHaveCSS('background-color', 'rgb(50, 50, 50)');
|
||||
});
|
||||
|
||||
await test.step('Expect setTheme set fontColor', async () => {
|
||||
await poLiveChat.page.evaluate(() => {
|
||||
window.RocketChat.livechat.maximizeWidget();
|
||||
window.RocketChat.livechat.setTheme({ fontColor: 'rgb(50, 50, 50)' });
|
||||
});
|
||||
|
||||
await expect(page.frameLocator('#rocketchat-iframe').locator('header')).toHaveCSS('color', 'rgb(50, 50, 50)');
|
||||
});
|
||||
|
||||
await test.step('expect setTheme set hideExpandChat', async () => {
|
||||
await poLiveChat.page.evaluate(() => window.RocketChat.livechat.maximizeWidget());
|
||||
|
||||
await expect(poLiveChat.btnExpandChat).toBeVisible();
|
||||
|
||||
await poLiveChat.page.evaluate(() => window.RocketChat.livechat.setTheme({ hideExpandChat: true }));
|
||||
|
||||
await expect(poLiveChat.btnExpandChat).not.toBeVisible();
|
||||
|
||||
await poLiveChat.page.evaluate(() => window.RocketChat.livechat.setTheme({ hideExpandChat: false }));
|
||||
|
||||
await expect(poLiveChat.btnExpandChat).toBeVisible();
|
||||
});
|
||||
|
||||
// TODO: fix iconColor setTheme property
|
||||
// await test.step('Expect setTheme set iconColor', async () => {
|
||||
// await poLiveChat.page.evaluate(() => {
|
||||
// window.RocketChat.livechat.maximizeWidget();
|
||||
// window.RocketChat.livechat.setTheme({ iconColor: 'rgb(50, 50, 50)' });
|
||||
// });
|
||||
|
||||
// await expect(page.frameLocator('#rocketchat-iframe').locator('header')).toHaveCSS('color', 'rgb(50, 50, 50)');
|
||||
// });
|
||||
|
||||
await test.step('Expect setTheme set title', async () => {
|
||||
await poLiveChat.page.evaluate(() => {
|
||||
window.RocketChat.livechat.maximizeWidget();
|
||||
window.RocketChat.livechat.setTheme({ title: 'CustomTitle' });
|
||||
});
|
||||
|
||||
await poLiveChat.page.evaluate(
|
||||
(registerGuestVisitor) => window.RocketChat.livechat.registerGuest(registerGuestVisitor),
|
||||
registerGuestVisitor,
|
||||
);
|
||||
|
||||
await expect(page.frameLocator('#rocketchat-iframe').getByText('CustomTitle')).toBeVisible();
|
||||
});
|
||||
|
||||
// await test.step('Expect setTheme set offlineTitle', async () => {
|
||||
// await poLiveChat.page.evaluate(() => {
|
||||
// window.RocketChat.livechat.maximizeWidget();
|
||||
// window.RocketChat.livechat.setTheme({ offlineTitle: 'CustomOfflineTitle' });
|
||||
// });
|
||||
|
||||
// await expect(page.frameLocator('#rocketchat-iframe').getByText('CustomTitle')).toBeVisible();
|
||||
// });
|
||||
});
|
||||
|
||||
test.skip('OC - Livechat API - setParentUrl', async () => {
|
||||
// TODO: check how to test this, not sure there is a clear indication of parent url changes
|
||||
await test.step('Expect setParentUrl to do something', async () => {
|
||||
await poLiveChat.page.evaluate(() => window.RocketChat.livechat.setParentUrl('http://localhost:3000'));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('Complex Widget Interactions', () => {
|
||||
// Needs Departments to test this, so needs an EE license for multiple deps
|
||||
test.skip(!IS_EE, 'Enterprise Only');
|
||||
// Tests that requires interaction from an agent or more
|
||||
let poAuxContext: { page: Page; poHomeOmnichannel: HomeOmnichannel };
|
||||
let poLiveChat: OmnichannelLiveChatEmbedded;
|
||||
let page: Page;
|
||||
let agent: Awaited<ReturnType<typeof createAgent>>;
|
||||
let agent2: Awaited<ReturnType<typeof createAgent>>;
|
||||
let departments: Awaited<ReturnType<typeof createDepartment>>[];
|
||||
let pageContext: Page;
|
||||
|
||||
test.beforeAll(async ({ api }) => {
|
||||
agent = await createAgent(api, 'user1');
|
||||
agent2 = await createAgent(api, 'user2');
|
||||
|
||||
departments = await Promise.all([createDepartment(api), createDepartment(api)]);
|
||||
const [departmentA, departmentB] = departments.map(({ data }) => data);
|
||||
|
||||
await addAgentToDepartment(api, { department: departmentA, agentId: agent.data._id });
|
||||
await addAgentToDepartment(api, { department: departmentB, agentId: agent2.data._id });
|
||||
expect((await api.post('/settings/Livechat_offline_email', { value: 'test@testing.com' })).status()).toBe(200);
|
||||
await api.post('/settings/Livechat_enabled_when_agent_idle', { value: false });
|
||||
});
|
||||
|
||||
test.beforeEach(async ({ browser }, testInfo) => {
|
||||
page = await browser.newPage();
|
||||
|
||||
poLiveChat = new OmnichannelLiveChatEmbedded(page);
|
||||
|
||||
const { page: pageCtx } = await createAuxContext(browser, Users.user1);
|
||||
poAuxContext = { page: pageCtx, poHomeOmnichannel: new HomeOmnichannel(pageCtx) };
|
||||
|
||||
// This is needed since the livechat will not react to online/offline status changes if already loaded in a page
|
||||
if (testInfo.title === 'Expect onOfflineFormSubmit to trigger callback') {
|
||||
await poAuxContext.poHomeOmnichannel.navbar.changeUserStatus('offline');
|
||||
} else {
|
||||
await poAuxContext.poHomeOmnichannel.navbar.changeUserStatus('online');
|
||||
}
|
||||
|
||||
await poLiveChat.goto();
|
||||
});
|
||||
|
||||
test.afterEach(async () => {
|
||||
await Promise.all([poAuxContext.page.close(), page.close(), pageContext?.close()]);
|
||||
});
|
||||
|
||||
test.afterAll(async ({ api }) => {
|
||||
await agent.delete();
|
||||
await agent2.delete();
|
||||
|
||||
await expect((await api.post('/settings/Omnichannel_enable_department_removal', { value: true })).status()).toBe(200);
|
||||
await Promise.all([...departments.map((department) => department.delete())]);
|
||||
await expect((await api.post('/settings/Omnichannel_enable_department_removal', { value: false })).status()).toBe(200);
|
||||
await api.post('/settings/Livechat_enabled_when_agent_idle', { value: true });
|
||||
});
|
||||
|
||||
// clearBusinessUnit
|
||||
// clearDepartment
|
||||
// initialize
|
||||
// maximizeWidget
|
||||
// minimizeWidget
|
||||
// pageVisited
|
||||
// registerGuest
|
||||
// setAgent
|
||||
// setBusinessUnit
|
||||
// setCustomField
|
||||
// setDepartment
|
||||
// setGuestEmail
|
||||
// setGuestName
|
||||
// setGuestToken
|
||||
// setParentUrl
|
||||
// setTheme
|
||||
|
||||
test.skip('OC - Livechat API - clearBusinessUnit', async () => {
|
||||
// TODO: check how to test this, and if this is working as intended
|
||||
await test.step('Expect clearBusinessUnit to do something', async () => {
|
||||
await poLiveChat.page.evaluate(() => window.RocketChat.livechat.clearBusinessUnit());
|
||||
});
|
||||
});
|
||||
|
||||
test.skip('OC - Livechat API - setBusinessUnit', async () => {
|
||||
// TODO
|
||||
await test.step('Expect setBusinessUnit to do something', async () => {
|
||||
await poLiveChat.page.evaluate(() => window.RocketChat.livechat.setBusinessUnit());
|
||||
});
|
||||
});
|
||||
|
||||
test.skip('OC - Livechat API - setCustomField', async () => {
|
||||
// TODO
|
||||
await test.step('Expect setCustomField to do something', async () => {
|
||||
await poLiveChat.page.evaluate(() => window.RocketChat.livechat.setCustomField({ key: 'test', value: 'test' }));
|
||||
});
|
||||
});
|
||||
|
||||
test.skip('OC - Livechat API - clearDepartment', async () => {
|
||||
// TODO
|
||||
await test.step('Expect clearDepartment to do something', async () => {
|
||||
await poLiveChat.page.evaluate(() => window.RocketChat.livechat.clearDepartment());
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('OC - Livechat API - setDepartment', () => {
|
||||
let poAuxContext2: { page: Page; poHomeOmnichannel: HomeOmnichannel };
|
||||
|
||||
test.beforeEach(async ({ browser }) => {
|
||||
const { page: pageCtx2 } = await createAuxContext(browser, Users.user2);
|
||||
poAuxContext2 = { page: pageCtx2, poHomeOmnichannel: new HomeOmnichannel(pageCtx2) };
|
||||
});
|
||||
|
||||
test.afterEach(async () => {
|
||||
await poAuxContext2.page.close();
|
||||
});
|
||||
|
||||
test('setDepartment - Called during ongoing conversation', async () => {
|
||||
const [departmentA, departmentB] = departments.map(({ data }) => data);
|
||||
const registerGuestVisitor = createFakeVisitorRegistration({
|
||||
department: departmentA._id,
|
||||
});
|
||||
|
||||
// Start Chat
|
||||
await poLiveChat.page.evaluate(() => window.RocketChat.livechat.maximizeWidget());
|
||||
await expect(page.frameLocator('#rocketchat-iframe').getByText('Start Chat')).toBeVisible();
|
||||
|
||||
await poLiveChat.page.evaluate(
|
||||
(registerGuestVisitor) => window.RocketChat.livechat.registerGuest(registerGuestVisitor),
|
||||
registerGuestVisitor,
|
||||
);
|
||||
|
||||
await expect(page.frameLocator('#rocketchat-iframe').getByText('Start Chat')).not.toBeVisible();
|
||||
|
||||
await poLiveChat.onlineAgentMessage.type('this_a_test_message_from_visitor');
|
||||
await poLiveChat.btnSendMessageToOnlineAgent.click();
|
||||
|
||||
await test.step('Expect registered guest to be in dep1', async () => {
|
||||
await poAuxContext.poHomeOmnichannel.navbar.openChat(registerGuestVisitor.name);
|
||||
await expect(poAuxContext.poHomeOmnichannel.content.channelHeader).toContainText(registerGuestVisitor.name);
|
||||
});
|
||||
|
||||
const depId = departmentB._id;
|
||||
|
||||
await test.step('Expect chat not be transferred', async () => {
|
||||
await poLiveChat.page.evaluate((depId) => window.RocketChat.livechat.setDepartment(depId), depId);
|
||||
|
||||
await poAuxContext2.poHomeOmnichannel.navbar.searchInput.click();
|
||||
await poAuxContext2.poHomeOmnichannel.navbar.typeSearch(registerGuestVisitor.name);
|
||||
await expect(poAuxContext2.poHomeOmnichannel.navbar.getSearchRoomByName(registerGuestVisitor.name)).not.toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('Expect registered guest to still be in dep1', async () => {
|
||||
await poAuxContext.poHomeOmnichannel.navbar.openChat(registerGuestVisitor.name);
|
||||
await expect(poAuxContext.poHomeOmnichannel.content.channelHeader).toContainText(registerGuestVisitor.name);
|
||||
});
|
||||
});
|
||||
|
||||
test('setDepartment - Called before conversation', async () => {
|
||||
const departmentB = departments[1].data;
|
||||
const registerGuestVisitor = createFakeVisitor();
|
||||
|
||||
const depId = departmentB._id;
|
||||
|
||||
await poLiveChat.page.evaluate((depId) => window.RocketChat.livechat.setDepartment(depId), depId);
|
||||
|
||||
await poLiveChat.page.evaluate(() => window.RocketChat.livechat.maximizeWidget());
|
||||
await expect(page.frameLocator('#rocketchat-iframe').getByText('Start Chat')).toBeVisible();
|
||||
|
||||
await poLiveChat.sendMessage(registerGuestVisitor, false);
|
||||
|
||||
await poLiveChat.onlineAgentMessage.type('this_a_test_message_from_visitor');
|
||||
await poLiveChat.btnSendMessageToOnlineAgent.click();
|
||||
|
||||
await test.step('Expect registered guest to be in dep2', async () => {
|
||||
await poAuxContext2.poHomeOmnichannel.navbar.openChat(registerGuestVisitor.name);
|
||||
|
||||
await poAuxContext2.page.locator('role=main').waitFor();
|
||||
await poAuxContext2.page.locator('role=main >> role=heading[level=1]').waitFor();
|
||||
await expect(poAuxContext2.page.locator('role=main >> .rcx-skeleton')).toHaveCount(0);
|
||||
await expect(poAuxContext2.page.locator('role=main >> role=list')).not.toHaveAttribute('aria-busy', 'true');
|
||||
});
|
||||
|
||||
await test.step('Expect registered guest not to be in dep1', async () => {
|
||||
await poAuxContext.poHomeOmnichannel.navbar.typeSearch(registerGuestVisitor.name);
|
||||
await expect(poAuxContext.poHomeOmnichannel.navbar.getSearchRoomByName(registerGuestVisitor.name)).not.toBeVisible();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('OC - Livechat API - transferChat', () => {
|
||||
let poAuxContext2: { page: Page; poHomeOmnichannel: HomeOmnichannel };
|
||||
|
||||
test.beforeEach(async ({ browser }) => {
|
||||
const { page: pageCtx2 } = await createAuxContext(browser, Users.user2);
|
||||
poAuxContext2 = { page: pageCtx2, poHomeOmnichannel: new HomeOmnichannel(pageCtx2) };
|
||||
});
|
||||
|
||||
test.afterEach(async () => {
|
||||
await poAuxContext2.page.close();
|
||||
});
|
||||
|
||||
test('transferChat - Called during ongoing conversation', async () => {
|
||||
const [departmentA, departmentB] = departments.map(({ data }) => data);
|
||||
const registerGuestVisitor = createFakeVisitorRegistration({
|
||||
department: departmentA._id,
|
||||
});
|
||||
|
||||
// Start Chat
|
||||
await poLiveChat.page.evaluate(() => window.RocketChat.livechat.maximizeWidget());
|
||||
await expect(page.frameLocator('#rocketchat-iframe').getByText('Start Chat')).toBeVisible();
|
||||
|
||||
await poLiveChat.page.evaluate(
|
||||
(registerGuestVisitor) => window.RocketChat.livechat.registerGuest(registerGuestVisitor),
|
||||
registerGuestVisitor,
|
||||
);
|
||||
|
||||
await expect(page.frameLocator('#rocketchat-iframe').getByText('Start Chat')).not.toBeVisible();
|
||||
|
||||
await poLiveChat.onlineAgentMessage.type('this_a_test_message_from_visitor');
|
||||
await poLiveChat.btnSendMessageToOnlineAgent.click();
|
||||
|
||||
await test.step('Expect registered guest to be in dep1', async () => {
|
||||
await poAuxContext.poHomeOmnichannel.navbar.openChat(registerGuestVisitor.name);
|
||||
await expect(poAuxContext.poHomeOmnichannel.content.channelHeader).toContainText(registerGuestVisitor.name);
|
||||
});
|
||||
|
||||
const depId = departmentB._id;
|
||||
|
||||
await test.step('Expect chat to be transferred', async () => {
|
||||
await poLiveChat.page.evaluate((depId) => window.RocketChat.livechat.transferChat(depId), depId);
|
||||
|
||||
await poAuxContext2.poHomeOmnichannel.navbar.openChat(registerGuestVisitor.name);
|
||||
await poAuxContext2.poHomeOmnichannel.navbar.typeSearch(registerGuestVisitor.name);
|
||||
await expect(poAuxContext2.poHomeOmnichannel.navbar.getSearchRoomByName(registerGuestVisitor.name)).toBeVisible();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test('OC - Livechat API - registerGuest', async ({ browser }) => {
|
||||
const registerGuestVisitor = createFakeVisitorRegistration();
|
||||
|
||||
await test.step('Expect registerGuest to create a valid guest', async () => {
|
||||
await poLiveChat.page.evaluate(() => window.RocketChat.livechat.maximizeWidget());
|
||||
await expect(page.frameLocator('#rocketchat-iframe').getByText('Start Chat')).toBeVisible();
|
||||
|
||||
await poLiveChat.page.evaluate(
|
||||
(registerGuestVisitor) => window.RocketChat.livechat.registerGuest(registerGuestVisitor),
|
||||
registerGuestVisitor,
|
||||
);
|
||||
|
||||
await expect(page.frameLocator('#rocketchat-iframe').getByText('Start Chat')).not.toBeVisible();
|
||||
|
||||
await poLiveChat.onlineAgentMessage.type('this_a_test_message_from_visitor');
|
||||
await poLiveChat.btnSendMessageToOnlineAgent.click();
|
||||
});
|
||||
|
||||
await test.step('Expect registered guest to have valid info', async () => {
|
||||
await poAuxContext.poHomeOmnichannel.navbar.openChat(registerGuestVisitor.name);
|
||||
|
||||
await poAuxContext.poHomeOmnichannel.roomToolbar.openContactInfo();
|
||||
// For some reason the guest info email information is being set to lowercase
|
||||
await expect(poAuxContext.poHomeOmnichannel.contacts.contactInfo.infoContactEmail).toHaveText(
|
||||
registerGuestVisitor.email.toLowerCase(),
|
||||
);
|
||||
});
|
||||
|
||||
await test.step('Expect registerGuest to log in an existing guest and load chat history', async () => {
|
||||
({ page: pageContext } = await createAuxContext(browser, Users.user1));
|
||||
|
||||
await new OmnichannelLiveChatEmbedded(pageContext).goto();
|
||||
|
||||
await pageContext.evaluate(() => window.RocketChat.livechat.maximizeWidget());
|
||||
await expect(pageContext.frameLocator('#rocketchat-iframe').getByText('Start Chat')).toBeVisible();
|
||||
|
||||
await pageContext.evaluate(
|
||||
(registerGuestVisitor) => window.RocketChat.livechat.registerGuest(registerGuestVisitor),
|
||||
registerGuestVisitor,
|
||||
);
|
||||
|
||||
await expect(pageContext.frameLocator('#rocketchat-iframe').getByText('Start Chat')).not.toBeVisible();
|
||||
await expect(pageContext.frameLocator('#rocketchat-iframe').getByText('this_a_test_message_from_visitor')).toBeVisible();
|
||||
});
|
||||
});
|
||||
|
||||
test('OC - Livechat API - registerGuest different guests', async () => {
|
||||
const registerGuestVisitor1 = createFakeVisitorRegistration();
|
||||
|
||||
const registerGuestVisitor2 = createFakeVisitorRegistration();
|
||||
|
||||
await test.step('Expect registerGuest to create guest 1', async () => {
|
||||
await poLiveChat.page.evaluate(() => window.RocketChat.livechat.maximizeWidget());
|
||||
await expect(poLiveChat.page.frameLocator('#rocketchat-iframe').getByText('Start Chat')).toBeVisible();
|
||||
|
||||
await poLiveChat.page.evaluate(
|
||||
(registerGuestVisitor1) => window.RocketChat.livechat.registerGuest(registerGuestVisitor1),
|
||||
registerGuestVisitor1,
|
||||
);
|
||||
|
||||
await expect(poLiveChat.page.frameLocator('#rocketchat-iframe').getByText('Start Chat')).not.toBeVisible();
|
||||
|
||||
await poLiveChat.onlineAgentMessage.type('this_a_test_message_from_visitor_1');
|
||||
await poLiveChat.btnSendMessageToOnlineAgent.click();
|
||||
|
||||
await expect(poLiveChat.txtChatMessage('this_a_test_message_from_visitor_1')).toBeVisible();
|
||||
|
||||
await poAuxContext.poHomeOmnichannel.navbar.openChat(registerGuestVisitor1.name);
|
||||
await poAuxContext.poHomeOmnichannel.content.sendMessage('this_is_a_test_message_from_agent');
|
||||
await expect(poLiveChat.txtChatMessage('this_is_a_test_message_from_agent')).toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('Expect registerGuest to create guest 2', async () => {
|
||||
await poLiveChat.page.evaluate(
|
||||
(registerGuestVisitor2) => window.RocketChat.livechat.registerGuest(registerGuestVisitor2),
|
||||
registerGuestVisitor2,
|
||||
);
|
||||
|
||||
// wait for load messages to happen
|
||||
await page.waitForResponse((response) => response.url().includes(`token=${registerGuestVisitor2.token}`));
|
||||
|
||||
await poLiveChat.page
|
||||
.frameLocator('#rocketchat-iframe')
|
||||
.getByText('this_a_test_message_from_visitor_1')
|
||||
.waitFor({ state: 'hidden' });
|
||||
|
||||
await expect(poLiveChat.page.frameLocator('#rocketchat-iframe').getByText('Start Chat')).not.toBeVisible();
|
||||
|
||||
await poLiveChat.onlineAgentMessage.type('this_a_test_message_from_visitor_2');
|
||||
await poLiveChat.btnSendMessageToOnlineAgent.click();
|
||||
|
||||
await poLiveChat.txtChatMessage('this_a_test_message_from_visitor_2').waitFor({ state: 'visible' });
|
||||
await expect(poLiveChat.txtChatMessage('this_a_test_message_from_visitor_2')).toBeVisible();
|
||||
});
|
||||
});
|
||||
|
||||
test('OC - Livechat API - registerGuest multiple times', async () => {
|
||||
const registerGuestVisitor = createFakeVisitorRegistration();
|
||||
|
||||
await test.step('Expect registerGuest work with the same token, multiple times', async () => {
|
||||
await poLiveChat.page.evaluate(() => window.RocketChat.livechat.maximizeWidget());
|
||||
await expect(page.frameLocator('#rocketchat-iframe').getByText('Start Chat')).toBeVisible();
|
||||
|
||||
await poLiveChat.page.evaluate(
|
||||
(registerGuestVisitor) => window.RocketChat.livechat.registerGuest(registerGuestVisitor),
|
||||
registerGuestVisitor,
|
||||
);
|
||||
|
||||
await expect(page.frameLocator('#rocketchat-iframe').getByText('Start Chat')).not.toBeVisible();
|
||||
|
||||
await poLiveChat.onlineAgentMessage.fill('this_a_test_message_from_visitor');
|
||||
await poLiveChat.btnSendMessageToOnlineAgent.click();
|
||||
|
||||
await expect(poLiveChat.txtChatMessage('this_a_test_message_from_visitor')).toBeVisible();
|
||||
|
||||
await poLiveChat.page.evaluate((registerGuestVisitor) => {
|
||||
window.RocketChat.livechat.registerGuest(registerGuestVisitor);
|
||||
window.RocketChat.livechat.registerGuest(registerGuestVisitor);
|
||||
}, registerGuestVisitor);
|
||||
|
||||
await page.waitForResponse('**/api/v1/livechat/visitor');
|
||||
await page.waitForTimeout(500); // NOTE: timeout is necessary to allow websocket unsubscribes to happen
|
||||
|
||||
await poLiveChat.onlineAgentMessage.fill('this_a_new_test_message_from_visitor');
|
||||
await poLiveChat.btnSendMessageToOnlineAgent.click();
|
||||
|
||||
await expect(poLiveChat.txtChatMessage('this_a_test_message_from_visitor')).toBeVisible();
|
||||
await expect(poLiveChat.txtChatMessage('this_a_new_test_message_from_visitor')).toBeVisible();
|
||||
});
|
||||
});
|
||||
|
||||
test.skip('OC - Livechat API - setGuestEmail', async () => {
|
||||
const registerGuestVisitor = createFakeVisitorRegistration();
|
||||
// Start Chat
|
||||
await poLiveChat.page.evaluate(() => window.RocketChat.livechat.maximizeWidget());
|
||||
await expect(page.frameLocator('#rocketchat-iframe').getByText('Start Chat')).toBeVisible();
|
||||
|
||||
await poLiveChat.page.evaluate(
|
||||
(registerGuestVisitor) => window.RocketChat.livechat.registerGuest(registerGuestVisitor),
|
||||
registerGuestVisitor,
|
||||
);
|
||||
|
||||
await expect(page.frameLocator('#rocketchat-iframe').getByText('Start Chat')).not.toBeVisible();
|
||||
|
||||
await poLiveChat.onlineAgentMessage.type('this_a_test_message_from_visitor');
|
||||
await poLiveChat.btnSendMessageToOnlineAgent.click();
|
||||
|
||||
await test.step('Expect setGuestEmail to change a guest email', async () => {
|
||||
await poLiveChat.page.evaluate(
|
||||
(registerGuestVisitor) => window.RocketChat.livechat.setGuestEmail(`changed${registerGuestVisitor.email}`),
|
||||
registerGuestVisitor,
|
||||
);
|
||||
});
|
||||
|
||||
await test.step('Expect registered guest to have valid info', async () => {
|
||||
await poAuxContext.poHomeOmnichannel.navbar.openChat(registerGuestVisitor.name);
|
||||
|
||||
await poAuxContext.poHomeOmnichannel.roomToolbar.openContactInfo();
|
||||
// For some reason the guest info email information is being set to lowercase
|
||||
await expect(poAuxContext.poHomeOmnichannel.contacts.contactInfo.infoContactEmail).toHaveText(
|
||||
`changed${registerGuestVisitor.email}`.toLowerCase(),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
test('OC - Livechat API - setGuestName', async () => {
|
||||
const registerGuestVisitor = createFakeVisitorRegistration();
|
||||
// Start Chat
|
||||
await poLiveChat.page.evaluate(() => window.RocketChat.livechat.maximizeWidget());
|
||||
await expect(page.frameLocator('#rocketchat-iframe').getByText('Start Chat')).toBeVisible();
|
||||
|
||||
await poLiveChat.page.evaluate(
|
||||
(registerGuestVisitor) => window.RocketChat.livechat.registerGuest(registerGuestVisitor),
|
||||
registerGuestVisitor,
|
||||
);
|
||||
|
||||
await expect(page.frameLocator('#rocketchat-iframe').getByText('Start Chat')).not.toBeVisible();
|
||||
|
||||
await poLiveChat.onlineAgentMessage.type('this_a_test_message_from_visitor');
|
||||
await poLiveChat.btnSendMessageToOnlineAgent.click();
|
||||
|
||||
await poAuxContext.poHomeOmnichannel.navbar.openChat(registerGuestVisitor.name);
|
||||
|
||||
await test.step('Expect setGuestEmail to change a guest email', async () => {
|
||||
await poLiveChat.page.evaluate(
|
||||
(registerGuestVisitor) => window.RocketChat.livechat.setGuestName(`changed${registerGuestVisitor.name}`),
|
||||
registerGuestVisitor,
|
||||
);
|
||||
});
|
||||
|
||||
await test.step('Expect registered guest to have valid info', async () => {
|
||||
await expect(poAuxContext.poHomeOmnichannel.content.infoHeaderName).toContainText(`changed${registerGuestVisitor.name}`);
|
||||
});
|
||||
});
|
||||
|
||||
test('OC - Livechat API - setGuestToken', async ({ browser }) => {
|
||||
const registerGuestVisitor = createFakeVisitorRegistration();
|
||||
|
||||
// Register guest and send a message
|
||||
await poLiveChat.page.evaluate(() => window.RocketChat.livechat.maximizeWidget());
|
||||
|
||||
await poLiveChat.page.evaluate(
|
||||
(registerGuestVisitor) => window.RocketChat.livechat.registerGuest(registerGuestVisitor),
|
||||
registerGuestVisitor,
|
||||
);
|
||||
|
||||
await expect(page.frameLocator('#rocketchat-iframe').getByText('Start Chat')).not.toBeVisible();
|
||||
|
||||
await poLiveChat.onlineAgentMessage.type('this_a_test_message_from_visitor');
|
||||
await poLiveChat.btnSendMessageToOnlineAgent.click();
|
||||
|
||||
await test.step('Expect setGuestToken to log in an existing guest and load chat history', async () => {
|
||||
({ page: pageContext } = await createAuxContext(browser, Users.user1));
|
||||
|
||||
await new OmnichannelLiveChatEmbedded(pageContext).goto();
|
||||
|
||||
await pageContext.evaluate(() => window.RocketChat.livechat.maximizeWidget());
|
||||
await expect(pageContext.frameLocator('#rocketchat-iframe').getByText('Start Chat')).toBeVisible();
|
||||
|
||||
await pageContext.evaluate(
|
||||
(registerGuestVisitor) => window.RocketChat.livechat.setGuestToken(registerGuestVisitor.token),
|
||||
registerGuestVisitor,
|
||||
);
|
||||
|
||||
await expect(pageContext.frameLocator('#rocketchat-iframe').getByText('Start Chat')).not.toBeVisible();
|
||||
await expect(pageContext.frameLocator('#rocketchat-iframe').getByText('this_a_test_message_from_visitor')).toBeVisible();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('Widget Listeners', () => {
|
||||
// Tests that listen to events from the widget, and check if they are being triggered
|
||||
|
||||
let poAuxContext: { page: Page; poHomeOmnichannel: HomeOmnichannel };
|
||||
let poLiveChat: OmnichannelLiveChatEmbedded;
|
||||
let page: Page;
|
||||
let agent: Awaited<ReturnType<typeof createAgent>>;
|
||||
|
||||
test.beforeAll(async ({ api }) => {
|
||||
agent = await createAgent(api, 'user1');
|
||||
expect((await api.post('/settings/Livechat_offline_email', { value: 'test@testing.com' })).status()).toBe(200);
|
||||
await api.post('/settings/Livechat_enabled_when_agent_idle', { value: false });
|
||||
});
|
||||
|
||||
test.beforeEach(async ({ browser }, testInfo) => {
|
||||
page = await browser.newPage();
|
||||
|
||||
poLiveChat = new OmnichannelLiveChatEmbedded(page);
|
||||
|
||||
const { page: pageCtx } = await createAuxContext(browser, Users.user1);
|
||||
poAuxContext = { page: pageCtx, poHomeOmnichannel: new HomeOmnichannel(pageCtx) };
|
||||
|
||||
// This is needed since the livechat will not react to online/offline status changes if already loaded in a page
|
||||
if (testInfo.title === 'Expect onOfflineFormSubmit to trigger callback') {
|
||||
await poAuxContext.poHomeOmnichannel.navbar.changeUserStatus('offline');
|
||||
} else {
|
||||
await poAuxContext.poHomeOmnichannel.navbar.changeUserStatus('online');
|
||||
}
|
||||
|
||||
await poLiveChat.goto();
|
||||
});
|
||||
|
||||
test.afterEach(async () => {
|
||||
await poAuxContext.page.close();
|
||||
await page.close();
|
||||
});
|
||||
|
||||
test.afterAll(async ({ api }) => {
|
||||
await agent.delete();
|
||||
await api.post('/settings/Livechat_enabled_when_agent_idle', { value: true });
|
||||
});
|
||||
|
||||
test('OC - Livechat API - onChatMaximized & onChatMinimized', async () => {
|
||||
await test.step('Expect onChatMaximized to trigger callback', async () => {
|
||||
await poLiveChat.page.evaluate(
|
||||
() =>
|
||||
new Promise((resolve: (value?: unknown) => void) => {
|
||||
window.RocketChat.livechat.onChatMaximized(() => {
|
||||
resolve();
|
||||
});
|
||||
|
||||
window.RocketChat.livechat.maximizeWidget();
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
await test.step('Expect onChatMinimized to trigger callback', async () => {
|
||||
await poLiveChat.page.evaluate(
|
||||
() =>
|
||||
new Promise((resolve: (value?: unknown) => void) => {
|
||||
window.RocketChat.livechat.onChatMinimized(() => {
|
||||
resolve();
|
||||
});
|
||||
|
||||
window.RocketChat.livechat.minimizeWidget();
|
||||
}),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
test('OC - Livechat API - onChatStarted & onChatEnded', async () => {
|
||||
const newVisitor = createFakeVisitor();
|
||||
|
||||
await test.step('Expect onChatStarted to trigger callback', async () => {
|
||||
const watchForTrigger = page.waitForFunction(() => window.onChatStarted === true);
|
||||
|
||||
await poLiveChat.page.evaluate(() =>
|
||||
window.RocketChat.livechat.onChatStarted(() => {
|
||||
window.onChatStarted = true;
|
||||
}),
|
||||
);
|
||||
|
||||
await poLiveChat.openLiveChat();
|
||||
await poLiveChat.sendMessage(newVisitor, false);
|
||||
await poLiveChat.onlineAgentMessage.type('this_a_test_message_from_visitor');
|
||||
await poLiveChat.btnSendMessageToOnlineAgent.click();
|
||||
|
||||
await watchForTrigger;
|
||||
});
|
||||
|
||||
await test.step('Expect onChatEnded to trigger callback', async () => {
|
||||
const watchForTrigger = page.waitForFunction(() => window.onChatEnded === true);
|
||||
|
||||
await poLiveChat.page.evaluate(() =>
|
||||
window.RocketChat.livechat.onChatEnded(() => {
|
||||
window.onChatEnded = true;
|
||||
}),
|
||||
);
|
||||
|
||||
await poAuxContext.poHomeOmnichannel.navbar.openChat(newVisitor.name);
|
||||
await poAuxContext.poHomeOmnichannel.quickActionsRoomToolbar.closeChat({ comment: 'this_is_a_test_comment' });
|
||||
await watchForTrigger;
|
||||
});
|
||||
});
|
||||
|
||||
test('OC - Livechat API - onPrechatFormSubmit & onAssignAgent', async () => {
|
||||
const newVisitor = createFakeVisitor();
|
||||
|
||||
await test.step('Expect onPrechatFormSubmit to trigger callback', async () => {
|
||||
const watchForTrigger = page.waitForFunction(() => window.onPrechatFormSubmit === true);
|
||||
|
||||
await poLiveChat.page.evaluate(() =>
|
||||
window.RocketChat.livechat.onPrechatFormSubmit(() => {
|
||||
window.onPrechatFormSubmit = true;
|
||||
}),
|
||||
);
|
||||
|
||||
await poLiveChat.openLiveChat();
|
||||
await poLiveChat.sendMessage(newVisitor, false);
|
||||
await poLiveChat.onlineAgentMessage.type('this_a_test_message_from_visitor');
|
||||
await poLiveChat.btnSendMessageToOnlineAgent.click();
|
||||
|
||||
await watchForTrigger;
|
||||
});
|
||||
|
||||
await test.step('Expect onAssignAgent to trigger callback', async () => {
|
||||
const watchForTrigger = page.waitForFunction(() => window.onAssignAgent === true);
|
||||
|
||||
await poLiveChat.page.evaluate(() =>
|
||||
window.RocketChat.livechat.onAssignAgent(() => {
|
||||
window.onAssignAgent = true;
|
||||
}),
|
||||
);
|
||||
|
||||
await poLiveChat.btnSendMessageToOnlineAgent.click();
|
||||
|
||||
await watchForTrigger;
|
||||
});
|
||||
});
|
||||
|
||||
// TODO: Fix this Flaky test
|
||||
test.skip('onAgentStatusChange', async () => {
|
||||
const newVisitor = createFakeVisitor();
|
||||
|
||||
await poLiveChat.openLiveChat();
|
||||
await poLiveChat.sendMessage(newVisitor, false);
|
||||
await poLiveChat.onlineAgentMessage.type('this_a_test_message_from_visitor');
|
||||
await poLiveChat.btnSendMessageToOnlineAgent.click();
|
||||
|
||||
const watchForTrigger = page.waitForFunction(() => window.onAgentStatusChange === true);
|
||||
|
||||
await poLiveChat.page.evaluate(() =>
|
||||
window.RocketChat.livechat.onAgentStatusChange(() => {
|
||||
window.onAgentStatusChange = true;
|
||||
}),
|
||||
);
|
||||
|
||||
await poAuxContext.poHomeOmnichannel.navbar.openChat(newVisitor.name);
|
||||
await poAuxContext.poHomeOmnichannel.navbar.changeUserStatus('offline');
|
||||
|
||||
await watchForTrigger;
|
||||
});
|
||||
|
||||
test('OC - Livechat API - onOfflineFormSubmit', async () => {
|
||||
const newVisitor = createFakeVisitor();
|
||||
|
||||
await poAuxContext.poHomeOmnichannel.navbar.changeUserStatus('offline');
|
||||
await poAuxContext.poHomeOmnichannel.navbar.switchOmnichannelStatus('offline');
|
||||
|
||||
const watchForTrigger = page.waitForFunction(() => window.onOfflineFormSubmit === true);
|
||||
|
||||
await poLiveChat.page.reload();
|
||||
|
||||
await poLiveChat.page.evaluate(() =>
|
||||
window.RocketChat.livechat.onOfflineFormSubmit(() => {
|
||||
window.onOfflineFormSubmit = true;
|
||||
}),
|
||||
);
|
||||
|
||||
await poLiveChat.openLiveChat();
|
||||
await poLiveChat.sendMessage(newVisitor, true);
|
||||
|
||||
await watchForTrigger;
|
||||
});
|
||||
|
||||
test('OC - Livechat API - onWidgetHidden & onWidgetShown', async () => {
|
||||
await test.step('Expect onWidgetHidden to trigger callback', async () => {
|
||||
await poLiveChat.page.evaluate(
|
||||
() =>
|
||||
new Promise((resolve: (value?: unknown) => void) => {
|
||||
window.RocketChat.livechat.onWidgetHidden(() => {
|
||||
resolve();
|
||||
});
|
||||
|
||||
window.RocketChat.livechat.hideWidget();
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
await test.step('Expect onWidgetShown to trigger callback', async () => {
|
||||
await poLiveChat.page.evaluate(
|
||||
() =>
|
||||
new Promise((resolve: (value?: unknown) => void) => {
|
||||
window.RocketChat.livechat.onWidgetShown(() => {
|
||||
resolve();
|
||||
});
|
||||
|
||||
window.RocketChat.livechat.showWidget();
|
||||
}),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
test.skip('OC - Livechat API - onServiceOffline', async () => {
|
||||
// TODO: Not sure how to test this, need to check if playwright has a way to mock a server disconnect
|
||||
await test.step('Expect onServiceOffline to do something', async () => {
|
||||
await poLiveChat.page.evaluate(() => window.RocketChat.livechat.onServiceOffline(() => console.log('onServiceOffline')));
|
||||
});
|
||||
});
|
||||
|
||||
test.skip('OC - Livechat API - onQueuePositionChange', async () => {
|
||||
// TODO
|
||||
await test.step('Expect onQueuePositionChange to do something', async () => {
|
||||
await poLiveChat.page.evaluate(() => window.RocketChat.livechat.onQueuePositionChange(() => console.log('onQueuePositionChange')));
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,96 @@
|
||||
import type { Page } from '@playwright/test';
|
||||
|
||||
import { createFakeVisitor } from '../../mocks/data';
|
||||
import { createAuxContext } from '../fixtures/createAuxContext';
|
||||
import { Users } from '../fixtures/userStates';
|
||||
import { HomeOmnichannel } from '../page-objects';
|
||||
import { OmnichannelLiveChatEmbedded } from '../page-objects/omnichannel';
|
||||
import { createAgent, makeAgentAvailable } from '../utils/omnichannel/agents';
|
||||
import { test, expect } from '../utils/test';
|
||||
|
||||
declare const window: Window & {
|
||||
RocketChat: {
|
||||
livechat: {
|
||||
setTheme: (theme: { hideAgentAvatar?: boolean; hideGuestAvatar?: boolean }) => void;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
test.use({ storageState: Users.user1.state });
|
||||
|
||||
test.describe('OC - Livechat - Avatar visibility', async () => {
|
||||
let agent: Awaited<ReturnType<typeof createAgent>>;
|
||||
let poLiveChat: OmnichannelLiveChatEmbedded;
|
||||
let poAuxContext: { page: Page; poHomeOmnichannel: HomeOmnichannel };
|
||||
|
||||
test.beforeAll(async ({ api }) => {
|
||||
agent = await createAgent(api, 'user1');
|
||||
|
||||
const res = await makeAgentAvailable(api, agent.data._id);
|
||||
|
||||
if (res.status() !== 200) {
|
||||
throw new Error('Failed to make agent available');
|
||||
}
|
||||
});
|
||||
|
||||
test.beforeEach(async ({ browser }) => {
|
||||
const { page: pageCtx } = await createAuxContext(browser, Users.user1);
|
||||
poAuxContext = { page: pageCtx, poHomeOmnichannel: new HomeOmnichannel(pageCtx) };
|
||||
});
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
poLiveChat = new OmnichannelLiveChatEmbedded(page);
|
||||
|
||||
await poLiveChat.goto();
|
||||
});
|
||||
|
||||
test.afterEach(async ({ page }) => {
|
||||
await poAuxContext.page.close();
|
||||
await page.close();
|
||||
});
|
||||
|
||||
test.afterAll(async () => {
|
||||
await agent.delete();
|
||||
});
|
||||
|
||||
test('OC - Livechat - Change avatar visibility', async () => {
|
||||
const visitor = createFakeVisitor();
|
||||
|
||||
await test.step('should initiate Livechat conversation', async () => {
|
||||
await poLiveChat.openLiveChat();
|
||||
await poLiveChat.sendMessage(visitor, false);
|
||||
await poLiveChat.onlineAgentMessage.fill('this_a_test_message_from_user');
|
||||
await poLiveChat.btnSendMessageToOnlineAgent.click();
|
||||
await expect(poLiveChat.txtChatMessage('this_a_test_message_from_user')).toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('expect to send a message as agent', async () => {
|
||||
await poAuxContext.poHomeOmnichannel.navbar.openChat(visitor.name);
|
||||
await poAuxContext.poHomeOmnichannel.content.sendMessage('this_is_a_test_message_from_agent');
|
||||
await expect(poLiveChat.txtChatMessage('this_is_a_test_message_from_agent')).toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('expect visitor avatar to be hidden', async () => {
|
||||
await expect(poLiveChat.imgAvatar(visitor.name)).not.toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('expect agent avatar to be visible', async () => {
|
||||
await expect(poLiveChat.imgAvatar('user1')).toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('expect to make visitor avatar visible', async () => {
|
||||
await poLiveChat.page.evaluate(() => window.RocketChat.livechat.setTheme({ hideGuestAvatar: false }));
|
||||
await expect(poLiveChat.imgAvatar(visitor.name)).toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('expect to hide agent avatar', async () => {
|
||||
await poLiveChat.page.evaluate(() => window.RocketChat.livechat.setTheme({ hideAgentAvatar: false }));
|
||||
await expect(poLiveChat.imgAvatar('user1')).toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('should close the conversation', async () => {
|
||||
await poAuxContext.poHomeOmnichannel.navbar.openChat(visitor.name);
|
||||
await poAuxContext.poHomeOmnichannel.quickActionsRoomToolbar.closeChat({ comment: 'this_is_a_test_comment' });
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,99 @@
|
||||
import { createFakeVisitor } from '../../mocks/data';
|
||||
import { IS_EE } from '../config/constants';
|
||||
import { Users } from '../fixtures/userStates';
|
||||
import { OmnichannelLiveChatEmbedded } from '../page-objects/omnichannel';
|
||||
import { createAgent, makeAgentAvailable } from '../utils/omnichannel/agents';
|
||||
import { test, expect } from '../utils/test';
|
||||
|
||||
declare const window: Window & {
|
||||
RocketChat: {
|
||||
livechat: {
|
||||
setTheme: (theme: { background?: string }) => void;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
test.use({ storageState: Users.admin.state });
|
||||
|
||||
test.skip(!IS_EE, 'Enterprise Only');
|
||||
|
||||
test.describe('OC - Livechat - Message list background', async () => {
|
||||
let agent: Awaited<ReturnType<typeof createAgent>>;
|
||||
let poLiveChat: OmnichannelLiveChatEmbedded;
|
||||
|
||||
test.beforeAll(async ({ api }) => {
|
||||
agent = await createAgent(api, 'user1');
|
||||
|
||||
const res = await makeAgentAvailable(api, agent.data._id);
|
||||
|
||||
if (res.status() !== 200) {
|
||||
throw new Error('Failed to make agent available');
|
||||
}
|
||||
});
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
poLiveChat = new OmnichannelLiveChatEmbedded(page);
|
||||
|
||||
await poLiveChat.goto();
|
||||
});
|
||||
|
||||
test.afterEach(async ({ page }) => {
|
||||
await page.close();
|
||||
});
|
||||
|
||||
test.afterAll(async () => {
|
||||
await agent.delete();
|
||||
});
|
||||
|
||||
test('OC - Livechat - Change message list background', async ({ api, page }) => {
|
||||
const visitor = createFakeVisitor();
|
||||
|
||||
await test.step('should initiate Livechat conversation', async () => {
|
||||
await poLiveChat.openLiveChat();
|
||||
await poLiveChat.sendMessage(visitor, false);
|
||||
await poLiveChat.onlineAgentMessage.fill('message_from_user');
|
||||
await poLiveChat.btnSendMessageToOnlineAgent.click();
|
||||
await expect(poLiveChat.txtChatMessage('message_from_user')).toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('expect message list to have default background', async () => {
|
||||
await expect(await poLiveChat.messageListBackground).toBe('rgba(0, 0, 0, 0)');
|
||||
});
|
||||
|
||||
await test.step('expect to change message list background', async () => {
|
||||
const res = await api.post('/settings/Livechat_background', { value: 'rgb(186, 1, 85)' });
|
||||
await expect(res.status()).toBe(200);
|
||||
|
||||
await page.reload();
|
||||
await poLiveChat.openLiveChat();
|
||||
await expect(await poLiveChat.messageListBackground).toBe('rgb(186, 1, 85)');
|
||||
});
|
||||
|
||||
await test.step('expect to give priority to background provided via api', async () => {
|
||||
await poLiveChat.page.evaluate(() => window.RocketChat.livechat.setTheme({ background: 'rgb(186, 218, 85)' }));
|
||||
|
||||
await expect(await poLiveChat.messageListBackground).toBe('rgb(186, 218, 85)');
|
||||
});
|
||||
|
||||
await test.step('expect to fallback to setting if api background is not available', async () => {
|
||||
await poLiveChat.page.evaluate(() => window.RocketChat.livechat.setTheme({ background: undefined }));
|
||||
await expect(await poLiveChat.messageListBackground).toBe('rgb(186, 1, 85)');
|
||||
});
|
||||
|
||||
await test.step('expect to reset message list background to default', async () => {
|
||||
const res = await api.post('/settings/Livechat_background', { value: '' });
|
||||
await expect(res.status()).toBe(200);
|
||||
|
||||
await page.reload();
|
||||
await poLiveChat.openLiveChat();
|
||||
await expect(await poLiveChat.messageListBackground).toBe('rgba(0, 0, 0, 0)');
|
||||
});
|
||||
|
||||
await test.step('should close the conversation', async () => {
|
||||
await poLiveChat.btnOptions.click();
|
||||
await poLiveChat.btnCloseChat.click();
|
||||
await poLiveChat.btnCloseChatConfirm.click();
|
||||
await expect(poLiveChat.btnNewChat).toBeVisible();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,153 @@
|
||||
import { createFakeVisitor } from '../../mocks/data';
|
||||
import { IS_EE } from '../config/constants';
|
||||
import { createAuxContext } from '../fixtures/createAuxContext';
|
||||
import { Users } from '../fixtures/userStates';
|
||||
import { HomeOmnichannel } from '../page-objects';
|
||||
import { OmnichannelLiveChat } from '../page-objects/omnichannel';
|
||||
import { createAgent } from '../utils/omnichannel/agents';
|
||||
import { addAgentToDepartment, createDepartment } from '../utils/omnichannel/departments';
|
||||
import { test, expect } from '../utils/test';
|
||||
|
||||
test.use({ storageState: Users.user1.state });
|
||||
|
||||
test.describe('OC - Livechat - Department Flow', () => {
|
||||
// Needs Departments to test this, so needs an EE license for multiple deps
|
||||
test.skip(!IS_EE, 'Enterprise Only');
|
||||
|
||||
let poLiveChat: OmnichannelLiveChat;
|
||||
let poHomeOmnichannelAgent1: HomeOmnichannel;
|
||||
let poHomeOmnichannelAgent2: HomeOmnichannel;
|
||||
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'];
|
||||
|
||||
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 addAgentToDepartment(api, { department: departmentA, agentId: agent1._id });
|
||||
await addAgentToDepartment(api, { department: departmentB, agentId: agent2._id });
|
||||
});
|
||||
|
||||
test.beforeEach(async ({ page, api, browser }) => {
|
||||
// Create Pages
|
||||
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 OmnichannelLiveChat(page, api);
|
||||
await poLiveChat.goto();
|
||||
});
|
||||
|
||||
test.afterEach(async ({ page }) => {
|
||||
await poHomeOmnichannelAgent1.page.close();
|
||||
await poHomeOmnichannelAgent2.page.close();
|
||||
await page.close();
|
||||
});
|
||||
|
||||
test.afterAll(async ({ api }) => {
|
||||
await 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())]);
|
||||
await expect((await api.post('/settings/Omnichannel_enable_department_removal', { value: false })).status()).toBe(200);
|
||||
});
|
||||
|
||||
test('OC - Livechat - Chat with Department', async () => {
|
||||
const guest = createFakeVisitor();
|
||||
|
||||
await test.step('expect start Chat with department', async () => {
|
||||
await poLiveChat.openAnyLiveChat();
|
||||
await poLiveChat.sendMessage(guest, false, departmentA.name);
|
||||
await expect(poLiveChat.onlineAgentMessage).toBeVisible();
|
||||
await poLiveChat.onlineAgentMessage.fill('this_a_test_message_from_user');
|
||||
await poLiveChat.btnSendMessageToOnlineAgent.click();
|
||||
await expect(poLiveChat.page.locator('div >> text="this_a_test_message_from_user"')).toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('expect message to be received by department', async () => {
|
||||
await poHomeOmnichannelAgent1.navbar.openChat(guest.name);
|
||||
await expect(poHomeOmnichannelAgent1.content.lastUserMessage).toBeVisible();
|
||||
await expect(poHomeOmnichannelAgent1.content.lastUserMessage).toContainText('this_a_test_message_from_user');
|
||||
});
|
||||
|
||||
await test.step('expect message to be sent by department', async () => {
|
||||
await poHomeOmnichannelAgent1.content.sendMessage('this_a_test_message_from_agent');
|
||||
await expect(poLiveChat.page.locator('div >> text="this_a_test_message_from_agent"')).toBeVisible();
|
||||
});
|
||||
});
|
||||
|
||||
test('OC - Livechat - Change Department', async () => {
|
||||
const guest = createFakeVisitor();
|
||||
await test.step('expect start Chat with department', async () => {
|
||||
await poLiveChat.openAnyLiveChat();
|
||||
await poLiveChat.sendMessage(guest, false, departmentA.name);
|
||||
await expect(poLiveChat.onlineAgentMessage).toBeVisible();
|
||||
await poLiveChat.onlineAgentMessage.fill('this_a_test_message_from_user');
|
||||
await poLiveChat.btnSendMessageToOnlineAgent.click();
|
||||
await expect(poLiveChat.page.locator('div >> text="this_a_test_message_from_user"')).toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('expect message to be received by department 1', async () => {
|
||||
await poHomeOmnichannelAgent1.navbar.openChat(guest.name);
|
||||
await expect(poHomeOmnichannelAgent1.content.lastUserMessage).toBeVisible();
|
||||
await expect(poHomeOmnichannelAgent1.content.lastUserMessage).toContainText('this_a_test_message_from_user');
|
||||
});
|
||||
|
||||
await test.step('expect message to be sent by department 1', async () => {
|
||||
await poHomeOmnichannelAgent1.content.sendMessage('this_a_test_message_from_agent_department_1');
|
||||
await expect(poLiveChat.page.locator('div >> text="this_a_test_message_from_agent_department_1"')).toBeVisible();
|
||||
await poHomeOmnichannelAgent1.page.close();
|
||||
});
|
||||
|
||||
await test.step('expect to change department', async () => {
|
||||
await poLiveChat.btnOptions.click();
|
||||
await poLiveChat.btnChangeDepartment.click();
|
||||
|
||||
await expect(poLiveChat.selectDepartment).toBeVisible();
|
||||
await poLiveChat.selectDepartment.selectOption({ label: departmentB.name });
|
||||
|
||||
await expect(poLiveChat.btnSendMessage('Start chat')).toBeEnabled();
|
||||
await poLiveChat.btnSendMessage('Start chat').click();
|
||||
|
||||
await expect(poLiveChat.livechatModal).toBeVisible();
|
||||
|
||||
await expect(poLiveChat.livechatModalText('Are you sure you want to switch the department?')).toBeVisible();
|
||||
await poLiveChat.btnYes.click();
|
||||
|
||||
await expect(poLiveChat.livechatModal).toBeVisible();
|
||||
|
||||
await expect(poLiveChat.livechatModalText('Department switched')).toBeVisible();
|
||||
await poLiveChat.btnOk.click();
|
||||
|
||||
// Expect keep chat history
|
||||
await expect(poLiveChat.page.locator('div >> text="this_a_test_message_from_user"')).toBeVisible();
|
||||
|
||||
// Expect user to have changed
|
||||
await expect(await poLiveChat.headerTitle.textContent()).toEqual(agent2.username);
|
||||
|
||||
await poLiveChat.onlineAgentMessage.fill('this_a_test_message_from_user_to_department_2');
|
||||
await poLiveChat.btnSendMessageToOnlineAgent.click();
|
||||
await expect(poLiveChat.page.locator('div >> text="this_a_test_message_from_user_to_department_2"')).toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('expect message to be received by department', async () => {
|
||||
await poHomeOmnichannelAgent2.navbar.openChat(guest.name);
|
||||
await expect(poHomeOmnichannelAgent2.content.lastUserMessage).toBeVisible();
|
||||
await expect(poHomeOmnichannelAgent2.content.lastUserMessage).toContainText('this_a_test_message_from_user_to_department_2');
|
||||
});
|
||||
|
||||
await test.step('expect message to be sent by department', async () => {
|
||||
await poHomeOmnichannelAgent2.content.sendMessage('this_a_test_message_from_agent_department_2');
|
||||
await expect(poLiveChat.page.locator('div >> text="this_a_test_message_from_agent_department_2"')).toBeVisible();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,124 @@
|
||||
import { createFakeVisitor } from '../../mocks/data';
|
||||
import { createAuxContext } from '../fixtures/createAuxContext';
|
||||
import { Users } from '../fixtures/userStates';
|
||||
import { HomeOmnichannel } from '../page-objects';
|
||||
import { OmnichannelLiveChat } from '../page-objects/omnichannel';
|
||||
import { createAgent } from '../utils/omnichannel/agents';
|
||||
import { test, expect } from '../utils/test';
|
||||
|
||||
const visitor = createFakeVisitor();
|
||||
|
||||
// Endpoint defaults are reset after each test, so if not in matrix assume is true
|
||||
const endpointMatrix = [
|
||||
[{ url: '/settings/FileUpload_Enabled', value: false }],
|
||||
[{ url: '/settings/Livechat_fileupload_enabled', value: false }],
|
||||
[
|
||||
{ url: '/settings/FileUpload_Enabled', value: false },
|
||||
{ url: '/settings/Livechat_fileupload_enabled', value: false },
|
||||
],
|
||||
];
|
||||
|
||||
const beforeTest = async (poLiveChat: OmnichannelLiveChat) => {
|
||||
await poLiveChat.goto();
|
||||
|
||||
await poLiveChat.openAnyLiveChat();
|
||||
await poLiveChat.sendMessage(visitor, false);
|
||||
await poLiveChat.onlineAgentMessage.fill('this_a_test_message_from_user');
|
||||
await poLiveChat.btnSendMessageToOnlineAgent.click();
|
||||
|
||||
await poLiveChat.txtChatMessage('this_a_test_message_from_user').waitFor({ state: 'visible' });
|
||||
};
|
||||
|
||||
test.describe('OC - Livechat - OC - File Upload', () => {
|
||||
let poLiveChat: OmnichannelLiveChat;
|
||||
let poHomeOmnichannel: HomeOmnichannel;
|
||||
let agent: Awaited<ReturnType<typeof createAgent>>;
|
||||
|
||||
test.beforeAll(async ({ browser, api }) => {
|
||||
agent = await createAgent(api, 'user1');
|
||||
|
||||
const { page } = await createAuxContext(browser, Users.user1, '/');
|
||||
poHomeOmnichannel = new HomeOmnichannel(page);
|
||||
});
|
||||
|
||||
test.beforeEach(async ({ page, api }) => {
|
||||
poLiveChat = new OmnichannelLiveChat(page, api);
|
||||
});
|
||||
|
||||
test.afterAll(async ({ api }) => {
|
||||
await api.post('/settings/FileUpload_Enabled', { value: true });
|
||||
await api.post('/settings/Livechat_fileupload_enabled', { value: true });
|
||||
|
||||
await poHomeOmnichannel.page.close();
|
||||
await agent.delete();
|
||||
});
|
||||
|
||||
// Default settings are FileUpload_Enabled true and Livechat_fileupload_enabled true
|
||||
test('OC - Livechat - txt Drag & Drop', async () => {
|
||||
await beforeTest(poLiveChat);
|
||||
|
||||
await test.step('expect to upload a txt file', async () => {
|
||||
await poLiveChat.dragAndDropTxtFile();
|
||||
await expect(poLiveChat.findUploadedFileLink('any_file.txt')).toBeVisible();
|
||||
});
|
||||
});
|
||||
|
||||
test('OC - Livechat - lst Drag & Drop', async () => {
|
||||
await beforeTest(poLiveChat);
|
||||
|
||||
await test.step('expect to upload a lst file', async () => {
|
||||
await poLiveChat.dragAndDropLstFile();
|
||||
await expect(poLiveChat.findUploadedFileLink('lst-test.lst')).toBeVisible();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('OC - Livechat - OC - File Upload - Disabled', () => {
|
||||
let poLiveChat: OmnichannelLiveChat;
|
||||
let poHomeOmnichannel: HomeOmnichannel;
|
||||
let agent: Awaited<ReturnType<typeof createAgent>>;
|
||||
|
||||
test.beforeAll(async ({ browser, api }) => {
|
||||
agent = await createAgent(api, 'user1');
|
||||
|
||||
const { page } = await createAuxContext(browser, Users.user1, '/');
|
||||
poHomeOmnichannel = new HomeOmnichannel(page);
|
||||
});
|
||||
|
||||
test.afterAll(async ({ api }) => {
|
||||
await api.post('/settings/FileUpload_Enabled', { value: true });
|
||||
await api.post('/settings/Livechat_fileupload_enabled', { value: true });
|
||||
|
||||
await poHomeOmnichannel.page?.close();
|
||||
await agent.delete();
|
||||
});
|
||||
|
||||
endpointMatrix.forEach((endpoints) => {
|
||||
const testName = endpoints.map((endpoint) => endpoint.url.split('/').pop()?.concat(`=${endpoint.value}`)).join(' ');
|
||||
|
||||
test(`OC - Livechat - txt Drag & Drop - ${testName}`, async ({ page, api }) => {
|
||||
poLiveChat = new OmnichannelLiveChat(page, api);
|
||||
|
||||
await Promise.all(
|
||||
endpoints.map(async (endpoint: { url: string; value: boolean }) => {
|
||||
await api.post(endpoint.url, { value: endpoint.value });
|
||||
}),
|
||||
);
|
||||
|
||||
await poLiveChat.goto();
|
||||
|
||||
await poLiveChat.openAnyLiveChat();
|
||||
await poLiveChat.sendMessage(visitor, false);
|
||||
await poLiveChat.onlineAgentMessage.fill('this_a_test_message_from_user');
|
||||
await poLiveChat.btnSendMessageToOnlineAgent.click();
|
||||
|
||||
await poLiveChat.txtChatMessage('this_a_test_message_from_user').waitFor({ state: 'visible' });
|
||||
|
||||
await test.step('expect to upload a txt file', async () => {
|
||||
await poLiveChat.dragAndDropTxtFile();
|
||||
|
||||
await expect(poLiveChat.alertMessage('File upload is disabled')).toBeVisible();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,66 @@
|
||||
import { IS_EE } from '../config/constants';
|
||||
import { createAuxContext } from '../fixtures/createAuxContext';
|
||||
import { Users } from '../fixtures/userStates';
|
||||
import { OmnichannelLiveChat, OmnichannelLivechatAppearance } from '../page-objects/omnichannel';
|
||||
import { createAgent, makeAgentAvailable } from '../utils/omnichannel/agents';
|
||||
import { test, expect } from '../utils/test';
|
||||
|
||||
test.skip(!IS_EE, 'Enterprise Only');
|
||||
|
||||
test.use({ storageState: Users.admin.state });
|
||||
|
||||
test.describe('OC - Livechat - Hide "Expand chat"', async () => {
|
||||
let agent: Awaited<ReturnType<typeof createAgent>>;
|
||||
let poLiveChat: OmnichannelLiveChat;
|
||||
let poLivechatAppearance: OmnichannelLivechatAppearance;
|
||||
|
||||
test.beforeAll(async ({ api }) => {
|
||||
agent = await createAgent(api, 'user1');
|
||||
|
||||
const res = await makeAgentAvailable(api, agent.data._id);
|
||||
|
||||
await expect(res.status()).toBe(200);
|
||||
});
|
||||
|
||||
test.beforeEach(async ({ browser, api }) => {
|
||||
const { page: livechatPage } = await createAuxContext(browser, Users.user1, '/livechat', false);
|
||||
|
||||
poLiveChat = new OmnichannelLiveChat(livechatPage, api);
|
||||
});
|
||||
|
||||
test.afterEach(async () => {
|
||||
await poLiveChat.page.close();
|
||||
});
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
poLivechatAppearance = new OmnichannelLivechatAppearance(page);
|
||||
|
||||
await poLivechatAppearance.goto();
|
||||
});
|
||||
|
||||
test.afterAll(async ({ api }) => {
|
||||
const res = await api.post('/settings/Livechat_hide_expand_chat', { value: false });
|
||||
await expect(res.status()).toBe(200);
|
||||
});
|
||||
|
||||
test('OC - Livechat - Hide "Expand chat"', async () => {
|
||||
await test.step('expect to open Livechat', async () => {
|
||||
await poLiveChat.openLiveChat();
|
||||
});
|
||||
|
||||
await test.step('expect "Expand chat" button to start visible (default)', async () => {
|
||||
await expect(poLiveChat.btnExpandChat).toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('expect to change setting', async () => {
|
||||
await poLivechatAppearance.labelHideExpandChat.click();
|
||||
await poLivechatAppearance.btnSaveChanges.click();
|
||||
});
|
||||
|
||||
await test.step('expect "Expand chat" button to be hidden', async () => {
|
||||
await poLiveChat.page.reload();
|
||||
await poLiveChat.openLiveChat();
|
||||
await expect(poLiveChat.btnExpandChat).toBeHidden();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,63 @@
|
||||
import { IS_EE } from '../config/constants';
|
||||
import { createAuxContext } from '../fixtures/createAuxContext';
|
||||
import { Users } from '../fixtures/userStates';
|
||||
import { OmnichannelLiveChat, OmnichannelSettings } from '../page-objects/omnichannel';
|
||||
import { test, expect } from '../utils/test';
|
||||
|
||||
test.skip(!IS_EE, 'Enterprise Only');
|
||||
|
||||
test.use({ storageState: Users.admin.state });
|
||||
|
||||
test.describe('OC - Livechat - Widget logo', async () => {
|
||||
let poLiveChat: OmnichannelLiveChat;
|
||||
let poOmnichannelSettings: OmnichannelSettings;
|
||||
|
||||
test.beforeEach(async ({ browser, api }) => {
|
||||
const { page: livechatPage } = await createAuxContext(browser, Users.user1, '/livechat', false);
|
||||
|
||||
poLiveChat = new OmnichannelLiveChat(livechatPage, api);
|
||||
});
|
||||
|
||||
test.afterEach(async () => {
|
||||
await poLiveChat.page.close();
|
||||
});
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
poOmnichannelSettings = new OmnichannelSettings(page);
|
||||
|
||||
await poOmnichannelSettings.goto();
|
||||
});
|
||||
|
||||
test.afterAll(async ({ api }) => {
|
||||
const res = await api.post('/assets.unsetAsset', { assetName: 'livechat_widget_logo' });
|
||||
if (res.status() !== 200) {
|
||||
throw new Error('Failed to unset asset');
|
||||
}
|
||||
});
|
||||
|
||||
test('OC - Livechat - Change widget logo', async () => {
|
||||
await test.step('expect to have default logo', async () => {
|
||||
await poOmnichannelSettings.group('Livechat').click();
|
||||
await expect(poLiveChat.imgLogo).not.toBeVisible();
|
||||
await expect(poOmnichannelSettings.imgLivechatLogoPreview).not.toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('expect to change widget logo', async () => {
|
||||
await expect(poOmnichannelSettings.labelLivechatLogo).toHaveText('Livechat widget logo (svg, png, jpg)');
|
||||
await poOmnichannelSettings.inputLivechatLogo.setInputFiles('./tests/e2e/fixtures/files/test-image.jpeg');
|
||||
await expect(poOmnichannelSettings.imgLivechatLogoPreview).toBeVisible();
|
||||
|
||||
await poLiveChat.page.reload();
|
||||
await expect(poLiveChat.imgLogo).toBeVisible();
|
||||
await expect(poLiveChat.imgLogo).toHaveAttribute('src', 'assets/livechat_widget_logo.jpeg');
|
||||
});
|
||||
|
||||
await test.step('expect to remove custom logo', async () => {
|
||||
await poOmnichannelSettings.btnDeleteLivechatLogo.click();
|
||||
await expect(poOmnichannelSettings.imgLivechatLogoPreview).not.toBeVisible();
|
||||
|
||||
await poLiveChat.page.reload();
|
||||
await expect(poLiveChat.imgLogo).not.toBeVisible();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,103 @@
|
||||
import type { Page } from '@playwright/test';
|
||||
|
||||
import { createFakeVisitor } from '../../mocks/data';
|
||||
import { createAuxContext } from '../fixtures/createAuxContext';
|
||||
import { Users } from '../fixtures/userStates';
|
||||
import { HomeOmnichannel } from '../page-objects';
|
||||
import { OmnichannelLiveChatEmbedded } from '../page-objects/omnichannel';
|
||||
import { createAgent, makeAgentAvailable } from '../utils/omnichannel/agents';
|
||||
import { test, expect } from '../utils/test';
|
||||
|
||||
declare const window: Window & {
|
||||
RocketChat: {
|
||||
livechat: {
|
||||
setTheme: (theme: { guestBubbleBackgroundColor?: string; agentBubbleBackgroundColor?: string }) => void;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
test.use({ storageState: Users.user1.state });
|
||||
|
||||
test.describe('OC - Livechat - Bubble background color', async () => {
|
||||
let agent: Awaited<ReturnType<typeof createAgent>>;
|
||||
let poLiveChat: OmnichannelLiveChatEmbedded;
|
||||
let poAuxContext: { page: Page; poHomeOmnichannel: HomeOmnichannel };
|
||||
|
||||
test.beforeAll(async ({ api }) => {
|
||||
agent = await createAgent(api, 'user1');
|
||||
|
||||
const res = await makeAgentAvailable(api, agent.data._id);
|
||||
|
||||
if (res.status() !== 200) {
|
||||
throw new Error('Failed to make agent available');
|
||||
}
|
||||
});
|
||||
|
||||
test.beforeEach(async ({ browser }) => {
|
||||
const { page: pageCtx } = await createAuxContext(browser, Users.user1);
|
||||
poAuxContext = { page: pageCtx, poHomeOmnichannel: new HomeOmnichannel(pageCtx) };
|
||||
});
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
poLiveChat = new OmnichannelLiveChatEmbedded(page);
|
||||
|
||||
await poLiveChat.goto();
|
||||
});
|
||||
|
||||
test.afterEach(async ({ page }) => {
|
||||
await poAuxContext.page?.close();
|
||||
await page.close();
|
||||
});
|
||||
|
||||
test.afterAll(async () => {
|
||||
await agent.delete();
|
||||
});
|
||||
|
||||
test('OC - Livechat - Change bubble background color', async () => {
|
||||
const visitor = createFakeVisitor();
|
||||
|
||||
await test.step('should initiate Livechat conversation', async () => {
|
||||
await poLiveChat.openLiveChat();
|
||||
await poLiveChat.sendMessage(visitor, false);
|
||||
await poLiveChat.onlineAgentMessage.fill('message_from_user');
|
||||
await poLiveChat.btnSendMessageToOnlineAgent.click();
|
||||
await expect(poLiveChat.txtChatMessage('message_from_user')).toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('expect to send a message as agent', async () => {
|
||||
await poAuxContext.poHomeOmnichannel.navbar.openChat(visitor.name);
|
||||
await poAuxContext.poHomeOmnichannel.content.sendMessage('message_from_agent');
|
||||
});
|
||||
|
||||
await test.step('expect to have default bubble background color', async () => {
|
||||
expect(await poLiveChat.messageBubbleBackground('message_from_user')).toBe('rgb(193, 39, 45)');
|
||||
expect(await poLiveChat.messageBubbleBackground('message_from_agent')).toBe('rgb(247, 248, 250)');
|
||||
});
|
||||
|
||||
await test.step('expect to change bubble background color', async () => {
|
||||
await poLiveChat.page.evaluate(() =>
|
||||
window.RocketChat.livechat.setTheme({
|
||||
guestBubbleBackgroundColor: 'rgb(186, 218, 85)',
|
||||
agentBubbleBackgroundColor: 'rgb(0, 100, 250)',
|
||||
}),
|
||||
);
|
||||
|
||||
expect(await poLiveChat.messageBubbleBackground('message_from_user')).toBe('rgb(186, 218, 85)');
|
||||
expect(await poLiveChat.messageBubbleBackground('message_from_agent')).toBe('rgb(0, 100, 250)');
|
||||
});
|
||||
|
||||
await test.step('expect to reset bubble background color to defaults', async () => {
|
||||
await poLiveChat.page.evaluate(() =>
|
||||
window.RocketChat.livechat.setTheme({ guestBubbleBackgroundColor: undefined, agentBubbleBackgroundColor: undefined }),
|
||||
);
|
||||
|
||||
expect(await poLiveChat.messageBubbleBackground('message_from_user')).toBe('rgb(193, 39, 45)');
|
||||
expect(await poLiveChat.messageBubbleBackground('message_from_agent')).toBe('rgb(247, 248, 250)');
|
||||
});
|
||||
|
||||
await test.step('should close the conversation', async () => {
|
||||
await poAuxContext.poHomeOmnichannel.navbar.openChat(visitor.name);
|
||||
await poAuxContext.poHomeOmnichannel.quickActionsRoomToolbar.closeChat({ comment: 'this_is_a_test_comment' });
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,124 @@
|
||||
import type { BrowserContext } from '@playwright/test';
|
||||
|
||||
import { createFakeVisitor } from '../../mocks/data';
|
||||
import { IS_EE } from '../config/constants';
|
||||
import { createAuxContext } from '../fixtures/createAuxContext';
|
||||
import { Users } from '../fixtures/userStates';
|
||||
import { HomeOmnichannel } from '../page-objects';
|
||||
import { OmnichannelLiveChat } from '../page-objects/omnichannel';
|
||||
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;
|
||||
let liveChatContext: BrowserContext;
|
||||
|
||||
const waitingQueueMessage = 'This is a message from Waiting Queue';
|
||||
|
||||
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.navbar.switchOmnichannelStatus('offline');
|
||||
});
|
||||
|
||||
test.beforeEach(async ({ browser, api }) => {
|
||||
liveChatContext = await browser.newContext();
|
||||
const page2 = await liveChatContext.newPage();
|
||||
|
||||
poLiveChat = new OmnichannelLiveChat(page2, api);
|
||||
await poLiveChat.goto();
|
||||
});
|
||||
|
||||
test.afterAll(async ({ api }) => {
|
||||
await Promise.all([
|
||||
api.post('/settings/Livechat_accept_chats_with_no_agents', { value: false }),
|
||||
api.post('/settings/Livechat_waiting_queue', { value: false }),
|
||||
api.post('/settings/Livechat_waiting_queue_message', { value: '' }),
|
||||
api.delete('/livechat/users/agent/user1'),
|
||||
]);
|
||||
await poHomeOmnichannel.page.close();
|
||||
});
|
||||
|
||||
test.describe('OC - Queue Management - Auto Selection', () => {
|
||||
let poLiveChat2: OmnichannelLiveChat;
|
||||
let liveChat2Context: BrowserContext;
|
||||
|
||||
test.beforeEach(async ({ browser, api }) => {
|
||||
liveChat2Context = await browser.newContext();
|
||||
const page = await liveChat2Context.newPage();
|
||||
poLiveChat2 = new OmnichannelLiveChat(page, api);
|
||||
await poLiveChat2.goto();
|
||||
});
|
||||
|
||||
test.afterEach(async () => {
|
||||
await poLiveChat2.closeChat();
|
||||
await liveChat2Context.close();
|
||||
await poLiveChat.closeChat();
|
||||
await liveChatContext.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.queuePosition(1)).toBeVisible();
|
||||
});
|
||||
|
||||
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.queuePosition(2)).toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('should start the queue by making the agent available again', async () => {
|
||||
await poHomeOmnichannel.navbar.switchOmnichannelStatus('online');
|
||||
});
|
||||
|
||||
await test.step('user1 should get assigned to the first chat', async () => {
|
||||
await expect(poLiveChat.queuePosition(1)).not.toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('secondary session should be on position #1', async () => {
|
||||
await expect(poLiveChat2.queuePosition(1)).toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('secondary session should be taken by user1', async () => {
|
||||
await expect(poLiveChat2.queuePosition(1)).not.toBeVisible();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,247 @@
|
||||
import type { BrowserContext } from '@playwright/test';
|
||||
|
||||
import { createFakeVisitor } from '../../mocks/data';
|
||||
import { IS_EE } from '../config/constants';
|
||||
import { createAuxContext } from '../fixtures/createAuxContext';
|
||||
import { Users } from '../fixtures/userStates';
|
||||
import { HomeOmnichannel } from '../page-objects';
|
||||
import { OmnichannelLiveChat } from '../page-objects/omnichannel';
|
||||
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;
|
||||
let liveChatContext: BrowserContext;
|
||||
|
||||
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: 'Manual_Selection' }),
|
||||
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);
|
||||
});
|
||||
|
||||
test.beforeEach(async ({ browser, api }) => {
|
||||
liveChatContext = await browser.newContext();
|
||||
const page2 = await liveChatContext.newPage();
|
||||
|
||||
poLiveChat = new OmnichannelLiveChat(page2, api);
|
||||
await poLiveChat.goto();
|
||||
});
|
||||
|
||||
test.afterAll(async ({ api }) => {
|
||||
await Promise.all([
|
||||
api.post('/settings/Livechat_Routing_Method', { value: 'Auto_Selection' }),
|
||||
api.post('/settings/Livechat_waiting_queue', { value: false }),
|
||||
api.post('/settings/Livechat_waiting_queue_message', { value: '' }),
|
||||
api.delete('/livechat/users/agent/user1'),
|
||||
]);
|
||||
await poHomeOmnichannel.page.close();
|
||||
});
|
||||
|
||||
test.afterEach(async () => {
|
||||
await poLiveChat.closeChat();
|
||||
await liveChatContext.close();
|
||||
});
|
||||
|
||||
test('OC - Queue Management - Waiting Queue Message enabled', 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();
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('OC - Queue Management - Update Queue Position', () => {
|
||||
let poLiveChat2: OmnichannelLiveChat;
|
||||
let liveChat2Context: BrowserContext;
|
||||
|
||||
test.beforeEach(async ({ browser, api }) => {
|
||||
liveChat2Context = await browser.newContext();
|
||||
const page = await liveChat2Context.newPage();
|
||||
poLiveChat2 = new OmnichannelLiveChat(page, api);
|
||||
await poLiveChat2.goto();
|
||||
});
|
||||
|
||||
test.afterEach(async () => {
|
||||
await poLiveChat2.closeChat();
|
||||
await liveChat2Context.close();
|
||||
});
|
||||
|
||||
test('Update user position on Queue', async () => {
|
||||
await test.step('should start secondary livechat session', async () => {
|
||||
await poLiveChat2.openAnyLiveChatAndSendMessage({
|
||||
liveChatUser: secondVisitor,
|
||||
message: 'Test message',
|
||||
isOffline: false,
|
||||
});
|
||||
});
|
||||
|
||||
await test.step('should start primary livechat session', async () => {
|
||||
await poLiveChat.openAnyLiveChatAndSendMessage({
|
||||
liveChatUser: firstVisitor,
|
||||
message: 'Test message',
|
||||
isOffline: false,
|
||||
});
|
||||
});
|
||||
|
||||
await test.step('should verify the queue position of the primary user', async () => {
|
||||
await expect(poLiveChat.page.locator(`div[role='alert'] >> text=${queuePosition2}`)).toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('should allow the agent to take the secondary user chat', async () => {
|
||||
await poHomeOmnichannel.sidebar.getSidebarItemByName(secondVisitor.name).click();
|
||||
await expect(poHomeOmnichannel.content.btnTakeChat).toBeVisible();
|
||||
await poHomeOmnichannel.content.btnTakeChat.click();
|
||||
await expect(poHomeOmnichannel.content.lastSystemMessageBody).toHaveText('joined the channel');
|
||||
});
|
||||
|
||||
await test.step('expect the queue position of the primary user to update after the secondary users chat is taken', async () => {
|
||||
await expect(poLiveChat.page.locator(`div[role='alert'] >> text=${queuePosition1}`)).toBeVisible();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('OC - Contact Manager Routing', () => {
|
||||
test.skip(!IS_EE, 'Enterprise Only');
|
||||
|
||||
let poHomeOmnichannel: HomeOmnichannel;
|
||||
let poLiveChat: OmnichannelLiveChat;
|
||||
let liveChatContext: BrowserContext;
|
||||
|
||||
// User2 will be the contact manager
|
||||
let poHomeOmnichannelUser2: HomeOmnichannel;
|
||||
|
||||
const visitorWithManager = createFakeVisitor();
|
||||
const contactId = `contact-${Date.now()}`;
|
||||
|
||||
test.beforeAll(async ({ api, browser }) => {
|
||||
await api.post('/livechat/users/agent', { username: 'user2' });
|
||||
await api.post('/settings/Livechat_Routing_Method', { value: 'Manual_Selection' });
|
||||
await api.post('/omnichannel/contact', {
|
||||
_id: contactId,
|
||||
name: visitorWithManager.name,
|
||||
email: visitorWithManager.email,
|
||||
contactManager: {
|
||||
username: 'user2',
|
||||
},
|
||||
});
|
||||
|
||||
const { page: omniPage } = await createAuxContext(browser, Users.user1, '/', true);
|
||||
poHomeOmnichannel = new HomeOmnichannel(omniPage);
|
||||
|
||||
const { page: omniPageUser2 } = await createAuxContext(browser, Users.user2, '/', true);
|
||||
poHomeOmnichannelUser2 = new HomeOmnichannel(omniPageUser2);
|
||||
});
|
||||
|
||||
test.beforeEach(async ({ browser, api }) => {
|
||||
liveChatContext = await browser.newContext();
|
||||
const page = await liveChatContext.newPage();
|
||||
|
||||
poLiveChat = new OmnichannelLiveChat(page, api);
|
||||
await poLiveChat.goto();
|
||||
});
|
||||
|
||||
test.afterAll(async ({ api }) => {
|
||||
await Promise.all([
|
||||
api.post('/settings/Livechat_Routing_Method', { value: 'Auto_Selection' }),
|
||||
api.delete('/livechat/users/agent/user1'),
|
||||
api.delete('/livechat/users/agent/user2'),
|
||||
api.delete(`/omnichannel/contact/${contactId}`),
|
||||
]);
|
||||
|
||||
await poHomeOmnichannel.page.close();
|
||||
await poHomeOmnichannelUser2.page.close();
|
||||
});
|
||||
|
||||
test.afterEach(async () => {
|
||||
await poLiveChat.closeChat();
|
||||
await liveChatContext.close();
|
||||
});
|
||||
|
||||
test('should route inquiry only to the contact manager', async () => {
|
||||
await test.step('visitor with contact manager starts a chat', async () => {
|
||||
await poLiveChat.openAnyLiveChatAndSendMessage({
|
||||
liveChatUser: visitorWithManager,
|
||||
message: 'I need assistance',
|
||||
isOffline: false,
|
||||
});
|
||||
});
|
||||
|
||||
await test.step('verify non-manager agent does not see the inquiry', async () => {
|
||||
const nonManagerQueuedChat = poHomeOmnichannel.sidebar.getSidebarItemByName(visitorWithManager.name);
|
||||
await expect(nonManagerQueuedChat).toHaveCount(0);
|
||||
});
|
||||
|
||||
await test.step('verify the contact manager agent sees the inquiry', async () => {
|
||||
const managerQueuedChat = poHomeOmnichannelUser2.sidebar.getSidebarItemByName(visitorWithManager.name);
|
||||
await expect(managerQueuedChat).toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('contact manager can take the chat', async () => {
|
||||
await poHomeOmnichannelUser2.sidebar.getSidebarItemByName(visitorWithManager.name).click();
|
||||
await expect(poHomeOmnichannelUser2.content.btnTakeChat).toBeVisible();
|
||||
await poHomeOmnichannelUser2.content.btnTakeChat.click();
|
||||
await expect(poHomeOmnichannelUser2.content.lastSystemMessageBody).toHaveText('joined the channel');
|
||||
});
|
||||
});
|
||||
|
||||
test('inquiry should persist only in contact manager queue after page refresh', async () => {
|
||||
const anotherVisitorWithManager = createFakeVisitor();
|
||||
|
||||
await test.step('visitor with contact manager starts a chat', async () => {
|
||||
await poLiveChat.openAnyLiveChatAndSendMessage({
|
||||
liveChatUser: anotherVisitorWithManager,
|
||||
message: 'I need help after refresh test',
|
||||
isOffline: false,
|
||||
});
|
||||
});
|
||||
|
||||
await test.step('refresh both agent pages', async () => {
|
||||
await poHomeOmnichannel.page.reload();
|
||||
await poHomeOmnichannel.page.waitForLoadState('networkidle');
|
||||
|
||||
await poHomeOmnichannelUser2.page.reload();
|
||||
await poHomeOmnichannelUser2.page.waitForLoadState('networkidle');
|
||||
});
|
||||
|
||||
await test.step('verify non-manager agent still does not see the inquiry after refresh', async () => {
|
||||
const nonManagerQueuedChat = poHomeOmnichannel.sidebar.getSidebarItemByName(anotherVisitorWithManager.name);
|
||||
await expect(nonManagerQueuedChat).toHaveCount(0);
|
||||
});
|
||||
|
||||
await test.step('verify the contact manager still sees the inquiry after refresh', async () => {
|
||||
const managerQueuedChat = poHomeOmnichannelUser2.sidebar.getSidebarItemByName(anotherVisitorWithManager.name);
|
||||
await expect(managerQueuedChat).toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('contact manager can take the chat after refresh', async () => {
|
||||
await poHomeOmnichannelUser2.sidebar.getSidebarItemByName(anotherVisitorWithManager.name).click();
|
||||
await expect(poHomeOmnichannelUser2.content.btnTakeChat).toBeVisible();
|
||||
await poHomeOmnichannelUser2.content.btnTakeChat.click();
|
||||
await expect(poHomeOmnichannelUser2.content.lastSystemMessageBody).toHaveText('joined the channel');
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,88 @@
|
||||
import type { Page } from '@playwright/test';
|
||||
|
||||
import { createFakeVisitor } from '../../mocks/data';
|
||||
import { IS_EE } from '../config/constants';
|
||||
import { createAuxContext } from '../fixtures/createAuxContext';
|
||||
import { Users } from '../fixtures/userStates';
|
||||
import { HomeOmnichannel } from '../page-objects';
|
||||
import { OmnichannelLiveChat } from '../page-objects/omnichannel';
|
||||
import { setSettingValueById } from '../utils';
|
||||
import { createAgent } from '../utils/omnichannel/agents';
|
||||
import { test, expect } from '../utils/test';
|
||||
|
||||
const visitor = createFakeVisitor();
|
||||
|
||||
test.use({ storageState: Users.user1.state });
|
||||
|
||||
test.describe('OC - Livechat - Read Receipts', () => {
|
||||
let poLiveChat: OmnichannelLiveChat;
|
||||
let poHomeOmnichannel: HomeOmnichannel;
|
||||
let livechatPage: Page;
|
||||
let agentPage: Page;
|
||||
let agent: Awaited<ReturnType<typeof createAgent>>;
|
||||
|
||||
test.skip(!IS_EE, 'Enterprise Only');
|
||||
|
||||
test.beforeAll(async ({ api, browser }) => {
|
||||
agent = await createAgent(api, 'user1');
|
||||
|
||||
await Promise.all([
|
||||
setSettingValueById(api, 'Message_Read_Receipt_Enabled', true),
|
||||
setSettingValueById(api, 'Message_Read_Receipt_Store_Users', true),
|
||||
setSettingValueById(api, 'UI_Use_Real_Name', true),
|
||||
]);
|
||||
|
||||
({ page: agentPage } = await createAuxContext(browser, Users.user1, '/', true));
|
||||
poHomeOmnichannel = new HomeOmnichannel(agentPage);
|
||||
|
||||
({ page: livechatPage } = await createAuxContext(browser, Users.user1, '/livechat', false));
|
||||
poLiveChat = new OmnichannelLiveChat(livechatPage, api);
|
||||
});
|
||||
|
||||
test.afterAll(({ api }) =>
|
||||
Promise.all([
|
||||
setSettingValueById(api, 'Message_Read_Receipt_Enabled', false),
|
||||
setSettingValueById(api, 'Message_Read_Receipt_Store_Users', false),
|
||||
setSettingValueById(api, 'UI_Use_Real_Name', false),
|
||||
agent.delete(),
|
||||
livechatPage.close(),
|
||||
agentPage.close(),
|
||||
]),
|
||||
);
|
||||
|
||||
test('OC - Livechat - Read receipts should display visitor name', async () => {
|
||||
const testMessage = 'test_message_for_read_receipts';
|
||||
|
||||
await test.step('send message from livechat widget', async () => {
|
||||
await poLiveChat.page.reload();
|
||||
await poLiveChat.openAnyLiveChat();
|
||||
await poLiveChat.sendMessage(visitor, false);
|
||||
await poLiveChat.onlineAgentMessage.fill(testMessage);
|
||||
await poLiveChat.btnSendMessageToOnlineAgent.click();
|
||||
await expect(poLiveChat.txtChatMessage(testMessage)).toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('agent reads the message', async () => {
|
||||
const markedAsRead = agentPage.waitForResponse(
|
||||
(res) => /api\/v1\/subscriptions\.read(?:\/|\?|$)/.test(res.url()) && res.request().method() === 'POST',
|
||||
);
|
||||
await poHomeOmnichannel.navbar.openChat(visitor.name);
|
||||
await expect(poHomeOmnichannel.content.lastUserMessage).toBeVisible();
|
||||
await expect(poHomeOmnichannel.content.lastUserMessage).toContainText(testMessage);
|
||||
await markedAsRead;
|
||||
await expect(poHomeOmnichannel.content.lastUserMessage.getByRole('status', { name: 'Message viewed' })).toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('read receipts show both agent and visitor names', async () => {
|
||||
await poHomeOmnichannel.content.openLastMessageMenu();
|
||||
await agentPage.locator('role=menuitem[name="Read receipts"]').click();
|
||||
|
||||
const dialog = agentPage.getByRole('dialog', { name: 'Read by' });
|
||||
const listItems = dialog.getByRole('listitem');
|
||||
await expect(listItems).toHaveCount(2);
|
||||
await expect(listItems.filter({ hasText: visitor.name })).toHaveCount(1);
|
||||
await expect(listItems.filter({ hasText: 'user1' })).toHaveCount(1);
|
||||
await dialog.getByLabel('Close').click();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,99 @@
|
||||
import type { BrowserContext } from '@playwright/test';
|
||||
|
||||
import { createFakeVisitor } from '../../mocks/data';
|
||||
import { createAuxContext } from '../fixtures/createAuxContext';
|
||||
import { Users } from '../fixtures/userStates';
|
||||
import { HomeOmnichannel } from '../page-objects';
|
||||
import { OmnichannelLiveChat } from '../page-objects/omnichannel';
|
||||
import { createAgent } from '../utils/omnichannel/agents';
|
||||
import { test, expect } from '../utils/test';
|
||||
|
||||
test.describe('OC - Livechat - Cross Tab Communication', () => {
|
||||
let pageLivechat1: OmnichannelLiveChat;
|
||||
let pageLivechat2: OmnichannelLiveChat;
|
||||
let livechatContext: BrowserContext;
|
||||
|
||||
let poHomeOmnichannel: HomeOmnichannel;
|
||||
let agent: Awaited<ReturnType<typeof createAgent>>;
|
||||
|
||||
test.beforeAll(async ({ browser, api }) => {
|
||||
agent = await createAgent(api, 'user1');
|
||||
|
||||
const { page } = await createAuxContext(browser, Users.user1, '/');
|
||||
poHomeOmnichannel = new HomeOmnichannel(page);
|
||||
});
|
||||
|
||||
test.beforeEach(async ({ browser, api }) => {
|
||||
livechatContext = await browser.newContext();
|
||||
const p1 = await livechatContext.newPage();
|
||||
const p2 = await livechatContext.newPage();
|
||||
|
||||
pageLivechat1 = new OmnichannelLiveChat(p1, api);
|
||||
pageLivechat2 = new OmnichannelLiveChat(p2, api);
|
||||
|
||||
await pageLivechat1.goto();
|
||||
await pageLivechat2.goto();
|
||||
});
|
||||
|
||||
test.afterEach(async () => {
|
||||
// Both pages share the same context; closing it disposes both pages
|
||||
await livechatContext.close();
|
||||
});
|
||||
|
||||
test.afterAll(async () => {
|
||||
await poHomeOmnichannel.page.close();
|
||||
await agent.delete();
|
||||
});
|
||||
|
||||
test('OC - Livechat - Send messages, close chat and start again 2 tabs', async () => {
|
||||
const visitor = createFakeVisitor();
|
||||
|
||||
await test.step('expect livechat conversations to be synced', async () => {
|
||||
await pageLivechat1.openAnyLiveChat();
|
||||
|
||||
await pageLivechat1.sendMessage(visitor, false);
|
||||
await pageLivechat1.onlineAgentMessage.fill('this_a_test_message_from_user');
|
||||
await pageLivechat1.btnSendMessageToOnlineAgent.click();
|
||||
|
||||
await expect(pageLivechat1.txtChatMessage('this_a_test_message_from_user')).toBeVisible();
|
||||
await expect(pageLivechat2.txtChatMessage('this_a_test_message_from_user')).toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('expect to close livechat conversation', async () => {
|
||||
await expect(pageLivechat1.btnOptions).toBeVisible();
|
||||
await pageLivechat1.btnOptions.click();
|
||||
|
||||
await expect(pageLivechat1.btnCloseChat).toBeVisible();
|
||||
await pageLivechat1.btnCloseChat.click();
|
||||
|
||||
await pageLivechat1.btnCloseChatConfirm.click();
|
||||
});
|
||||
|
||||
await test.step('expect to restart a livechat conversation and tabs to be synced', async () => {
|
||||
await expect(pageLivechat1.btnNewChat).toBeVisible();
|
||||
await pageLivechat1.startNewChat();
|
||||
|
||||
await pageLivechat1.onlineAgentMessage.fill('this_a_test_message_from_user_after_close');
|
||||
await pageLivechat1.btnSendMessageToOnlineAgent.click();
|
||||
|
||||
await pageLivechat1.txtChatMessage('this_a_test_message_from_user').waitFor({ state: 'hidden' });
|
||||
await pageLivechat2.txtChatMessage('this_a_test_message_from_user').waitFor({ state: 'hidden' });
|
||||
|
||||
await expect(pageLivechat1.txtChatMessage('this_a_test_message_from_user')).not.toBeVisible();
|
||||
await expect(pageLivechat2.txtChatMessage('this_a_test_message_from_user')).not.toBeVisible();
|
||||
|
||||
await expect(pageLivechat1.txtChatMessage('this_a_test_message_from_user_after_close')).toBeVisible();
|
||||
await expect(pageLivechat2.txtChatMessage('this_a_test_message_from_user_after_close')).toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('expect to close livechat conversation', async () => {
|
||||
await expect(pageLivechat1.btnOptions).toBeVisible();
|
||||
await pageLivechat1.btnOptions.click();
|
||||
|
||||
await expect(pageLivechat1.btnCloseChat).toBeVisible();
|
||||
await pageLivechat1.btnCloseChat.click();
|
||||
|
||||
await pageLivechat1.btnCloseChatConfirm.click();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,60 @@
|
||||
import type { Page } from 'playwright-core';
|
||||
|
||||
import { createFakeVisitor } from '../../mocks/data';
|
||||
import { createAuxContext } from '../fixtures/createAuxContext';
|
||||
import { Users } from '../fixtures/userStates';
|
||||
import { HomeOmnichannel } from '../page-objects';
|
||||
import { OmnichannelLiveChat } from '../page-objects/omnichannel';
|
||||
import { test, expect } from '../utils/test';
|
||||
|
||||
const visitor = createFakeVisitor();
|
||||
|
||||
test.use({ storageState: Users.user1.state });
|
||||
|
||||
test.describe.serial('OC - Livechat - Typing indicator', () => {
|
||||
let poLiveChat: OmnichannelLiveChat;
|
||||
let poHomeOmnichannel: HomeOmnichannel;
|
||||
let livechatPage: Page;
|
||||
|
||||
test.beforeAll(async ({ api }) => {
|
||||
const statusCode = (await api.post('/livechat/users/agent', { username: 'user1' })).status();
|
||||
expect(statusCode).toBe(200);
|
||||
});
|
||||
|
||||
test.beforeAll(async ({ browser, api }) => {
|
||||
({ page: livechatPage } = await createAuxContext(browser, Users.user1, '/livechat', false));
|
||||
poLiveChat = new OmnichannelLiveChat(livechatPage, api);
|
||||
});
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
poHomeOmnichannel = new HomeOmnichannel(page);
|
||||
await poHomeOmnichannel.goto();
|
||||
});
|
||||
|
||||
test.afterAll(async ({ api }) => {
|
||||
await Promise.all([api.delete('/livechat/users/agent/user1'), livechatPage.close()]);
|
||||
});
|
||||
|
||||
test('OC - Livechat - Visitor/Agent types and sees typing indicator', async () => {
|
||||
await test.step('expect conversation to be started', async () => {
|
||||
await poLiveChat.page.reload();
|
||||
await poLiveChat.openAnyLiveChatAndSendMessage({
|
||||
liveChatUser: visitor,
|
||||
message: 'Hello, I need help',
|
||||
isOffline: false,
|
||||
});
|
||||
await poHomeOmnichannel.navbar.openChat(visitor.name);
|
||||
await expect(poHomeOmnichannel.content.lastUserMessage).toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('expect agent to see typing indicator when visitor types', async () => {
|
||||
await poLiveChat.onlineAgentMessage.pressSequentially('abc', { delay: 20 });
|
||||
await expect(poHomeOmnichannel.composer.typingIndicator).toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('expect visitor to see typing indicator when agent types', async () => {
|
||||
await poHomeOmnichannel.composer.inputMessage.pressSequentially('xyz', { delay: 20 });
|
||||
await expect(poLiveChat.typingIndicatorForVisitor).toBeVisible();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,73 @@
|
||||
import { createFakeVisitor } from '../../mocks/data';
|
||||
import { IS_EE } from '../config/constants';
|
||||
import { createAuxContext } from '../fixtures/createAuxContext';
|
||||
import { Users } from '../fixtures/userStates';
|
||||
import { OmnichannelLiveChat, OmnichannelSettings } from '../page-objects/omnichannel';
|
||||
import { createAgent, makeAgentAvailable } from '../utils/omnichannel/agents';
|
||||
import { test, expect } from '../utils/test';
|
||||
|
||||
const visitor = createFakeVisitor();
|
||||
|
||||
test.skip(!IS_EE, 'Enterprise Only');
|
||||
|
||||
test.use({ storageState: Users.admin.state });
|
||||
|
||||
test.describe('OC - Livechat - Hide watermark', async () => {
|
||||
let agent: Awaited<ReturnType<typeof createAgent>>;
|
||||
let poLiveChat: OmnichannelLiveChat;
|
||||
let poOmnichannelSettings: OmnichannelSettings;
|
||||
|
||||
test.beforeAll(async ({ api }) => {
|
||||
agent = await createAgent(api, 'user1');
|
||||
|
||||
const res = await makeAgentAvailable(api, agent.data._id);
|
||||
|
||||
await expect(res.status()).toBe(200);
|
||||
});
|
||||
|
||||
test.beforeEach(async ({ browser, api }) => {
|
||||
const { page: livechatPage } = await createAuxContext(browser, Users.user1, '/livechat', false);
|
||||
|
||||
poLiveChat = new OmnichannelLiveChat(livechatPage, api);
|
||||
});
|
||||
|
||||
test.afterEach(async () => {
|
||||
await poLiveChat.page.close();
|
||||
});
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
poOmnichannelSettings = new OmnichannelSettings(page);
|
||||
|
||||
await poOmnichannelSettings.goto();
|
||||
});
|
||||
|
||||
test.afterAll(async ({ api }) => {
|
||||
const res = await api.post('/settings/Livechat_hide_watermark', { value: false });
|
||||
await expect(res.status()).toBe(200);
|
||||
});
|
||||
|
||||
test('OC - Livechat - Hide watermark', async () => {
|
||||
await test.step('expect to open Livechat', async () => {
|
||||
await poLiveChat.openLiveChat();
|
||||
await poLiveChat.sendMessage(visitor, false);
|
||||
});
|
||||
|
||||
await test.step('expect watermark to start visible (default)', async () => {
|
||||
await expect(poLiveChat.onlineAgentMessage).toBeVisible();
|
||||
await expect(poLiveChat.txtWatermark).toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('expect to change setting', async () => {
|
||||
await poOmnichannelSettings.group('Livechat').click();
|
||||
await poOmnichannelSettings.labelHideWatermark.click();
|
||||
await poOmnichannelSettings.btnSaveChanges.click();
|
||||
});
|
||||
|
||||
await test.step('expect watermark to be hidden', async () => {
|
||||
await poLiveChat.page.reload();
|
||||
await poLiveChat.openLiveChat();
|
||||
await expect(poLiveChat.onlineAgentMessage).toBeVisible();
|
||||
await expect(poLiveChat.txtWatermark).toBeHidden();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,28 @@
|
||||
import type { Page } from '@playwright/test';
|
||||
|
||||
import { OmnichannelLiveChatEmbedded } from '../page-objects/omnichannel';
|
||||
import { test, expect } from '../utils/test';
|
||||
|
||||
test.describe('Omnichannel - Livechat Widget Embedded', () => {
|
||||
test.describe('Widget is working on Embedded View', () => {
|
||||
let page: Page;
|
||||
let poLiveChat: OmnichannelLiveChatEmbedded;
|
||||
|
||||
test.beforeAll(async ({ browser }) => {
|
||||
page = await browser.newPage();
|
||||
poLiveChat = new OmnichannelLiveChatEmbedded(page);
|
||||
|
||||
await poLiveChat.goto();
|
||||
});
|
||||
|
||||
test.afterAll(async () => {
|
||||
await page.close();
|
||||
});
|
||||
|
||||
test('Open and Close widget', async () => {
|
||||
await test.step('Expect widget to be visible while embedded in an iframe', async () => {
|
||||
await expect(poLiveChat.btnOpenLiveChat()).toBeVisible();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
350
apps/meteor/tests/e2e/omnichannel/omnichannel-livechat.spec.ts
Normal file
350
apps/meteor/tests/e2e/omnichannel/omnichannel-livechat.spec.ts
Normal file
@@ -0,0 +1,350 @@
|
||||
import type { Page } from 'playwright-core';
|
||||
|
||||
import { createFakeVisitor } from '../../mocks/data';
|
||||
import { createAuxContext } from '../fixtures/createAuxContext';
|
||||
import { Users } from '../fixtures/userStates';
|
||||
import { HomeOmnichannel } from '../page-objects';
|
||||
import { OmnichannelLiveChat } from '../page-objects/omnichannel';
|
||||
import { setSettingValueById } from '../utils';
|
||||
import { createAgent } from '../utils/omnichannel/agents';
|
||||
import { test, expect } from '../utils/test';
|
||||
|
||||
const firstVisitor = createFakeVisitor();
|
||||
|
||||
const secondVisitor = createFakeVisitor();
|
||||
|
||||
test.use({ storageState: Users.user1.state });
|
||||
|
||||
test.describe.serial('OC - Livechat', () => {
|
||||
let poLiveChat: OmnichannelLiveChat;
|
||||
let poHomeOmnichannel: HomeOmnichannel;
|
||||
let livechatPage: Page;
|
||||
|
||||
test.beforeAll(async ({ api }) => {
|
||||
const statusCode = (await api.post('/livechat/users/agent', { username: 'user1' })).status();
|
||||
expect(statusCode).toBe(200);
|
||||
});
|
||||
|
||||
test.beforeAll(async ({ browser, api }) => {
|
||||
({ page: livechatPage } = await createAuxContext(browser, Users.user1, '/livechat', false));
|
||||
|
||||
poLiveChat = new OmnichannelLiveChat(livechatPage, api);
|
||||
});
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
poHomeOmnichannel = new HomeOmnichannel(page);
|
||||
|
||||
await poHomeOmnichannel.goto();
|
||||
});
|
||||
|
||||
test.afterAll(async ({ api }) => {
|
||||
await Promise.all([api.delete('/livechat/users/agent/user1'), livechatPage.close()]);
|
||||
});
|
||||
|
||||
test('OC - Livechat - Send message to online agent', async () => {
|
||||
await test.step('expect message to be sent by livechat', async () => {
|
||||
await poLiveChat.page.reload();
|
||||
await poLiveChat.openAnyLiveChat();
|
||||
await poLiveChat.sendMessage(firstVisitor, false);
|
||||
|
||||
await poLiveChat.onlineAgentMessage.fill('this_a_test_message_from_user');
|
||||
await poLiveChat.btnSendMessageToOnlineAgent.click();
|
||||
|
||||
await expect(poLiveChat.page.locator('div >> text="this_a_test_message_from_user"')).toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('expect message to be received by agent', async () => {
|
||||
await poHomeOmnichannel.navbar.openChat(firstVisitor.name);
|
||||
await expect(poHomeOmnichannel.content.lastUserMessage).toBeVisible();
|
||||
await expect(poHomeOmnichannel.content.lastUserMessage).toContainText('this_a_test_message_from_user');
|
||||
});
|
||||
});
|
||||
|
||||
test('OC - Livechat - Send message to livechat customer', async () => {
|
||||
await poHomeOmnichannel.navbar.openChat(firstVisitor.name);
|
||||
|
||||
await test.step('expect message to be sent by agent', async () => {
|
||||
await poHomeOmnichannel.content.sendMessage('this_a_test_message_from_agent');
|
||||
await expect(poLiveChat.page.locator('div >> text="this_a_test_message_from_agent"')).toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('expect when user minimizes the livechat screen, the composer should be hidden', async () => {
|
||||
await poLiveChat.openAnyLiveChat();
|
||||
await expect(poLiveChat.page.locator('[contenteditable="true"]')).not.toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('expect message to be received by minimized livechat', async () => {
|
||||
await poHomeOmnichannel.content.sendMessage('this_a_test_message_again_from_agent');
|
||||
await expect(poLiveChat.unreadMessagesBadge(1)).toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('expect multiple messages to be received by minimized livechat', async () => {
|
||||
await poHomeOmnichannel.content.sendMessage('this_a_test_message_once_again_from_agent');
|
||||
await expect(poLiveChat.unreadMessagesBadge(2)).toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('expect unread messages to be visible after a reload', async () => {
|
||||
await poLiveChat.page.reload();
|
||||
await expect(poLiveChat.unreadMessagesBadge(2)).toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('expect unread counter to be empty after user sends a message after reload', async () => {
|
||||
const message = 'this_a_test_message_from_user_after_reload';
|
||||
|
||||
await poLiveChat.openAnyLiveChat();
|
||||
await poLiveChat.onlineAgentMessage.fill(message);
|
||||
await poLiveChat.btnSendMessageToOnlineAgent.click();
|
||||
await expect(poLiveChat.txtChatMessage(message)).toBeVisible();
|
||||
await expect(poLiveChat.unreadMessagesBadge(2)).toHaveCount(0);
|
||||
await expect(poLiveChat.unreadMessagesBadge(1)).toHaveCount(0);
|
||||
});
|
||||
});
|
||||
|
||||
test('OC - Livechat - Close livechat conversation', async () => {
|
||||
await poHomeOmnichannel.navbar.openChat(firstVisitor.name);
|
||||
|
||||
await test.step('expect livechat conversation to be closed by agent', async () => {
|
||||
await poHomeOmnichannel.quickActionsRoomToolbar.closeChat({ comment: 'this_is_a_test_comment' });
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test.describe.serial('OC - Livechat - Visitors closing the room is disabled', () => {
|
||||
let poLiveChat: OmnichannelLiveChat;
|
||||
let poHomeOmnichannel: HomeOmnichannel;
|
||||
let livechatPage: Page;
|
||||
let omniPage: Page;
|
||||
|
||||
test.beforeAll(async ({ api }) => {
|
||||
await api.post('/livechat/users/agent', { username: 'user1' });
|
||||
});
|
||||
|
||||
test.beforeAll(async ({ browser, api }) => {
|
||||
({ page: livechatPage } = await createAuxContext(browser, Users.user1, '/livechat', false));
|
||||
|
||||
poLiveChat = new OmnichannelLiveChat(livechatPage, api);
|
||||
});
|
||||
|
||||
test.beforeAll(async ({ browser, api }) => {
|
||||
await setSettingValueById(api, 'Livechat_allow_visitor_closing_chat', false);
|
||||
({ page: omniPage } = await createAuxContext(browser, Users.user1, '/', true));
|
||||
poHomeOmnichannel = new HomeOmnichannel(omniPage);
|
||||
});
|
||||
|
||||
test.afterAll(async ({ api }) => {
|
||||
await Promise.all([
|
||||
setSettingValueById(api, 'Livechat_allow_visitor_closing_chat', true),
|
||||
api.delete('/livechat/users/agent/user1'),
|
||||
livechatPage.close(),
|
||||
omniPage.close(),
|
||||
]);
|
||||
});
|
||||
|
||||
test('OC - Livechat - Close Chat disabled', async () => {
|
||||
await poLiveChat.page.reload();
|
||||
await poLiveChat.openAnyLiveChat();
|
||||
await poLiveChat.sendMessage(firstVisitor, false);
|
||||
await poLiveChat.onlineAgentMessage.fill('this_a_test_message_from_user');
|
||||
await poLiveChat.btnSendMessageToOnlineAgent.click();
|
||||
|
||||
await test.step('expect to close a livechat conversation', async () => {
|
||||
await expect(poLiveChat.btnOptions).not.toBeVisible();
|
||||
await expect(poLiveChat.btnCloseChat).not.toBeVisible();
|
||||
});
|
||||
});
|
||||
|
||||
test('OC - Livechat - Close chat disabled, agents can close', async () => {
|
||||
await poHomeOmnichannel.navbar.openChat(firstVisitor.name);
|
||||
|
||||
await test.step('expect livechat conversation to be closed by agent', async () => {
|
||||
await poHomeOmnichannel.quickActionsRoomToolbar.closeChat({ comment: 'this_is_a_test_comment' });
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test.describe.serial('OC - Livechat - Resub after close room', () => {
|
||||
let poLiveChat: OmnichannelLiveChat;
|
||||
let poHomeOmnichannel: HomeOmnichannel;
|
||||
let livechatPage: Page;
|
||||
let omniPage: Page;
|
||||
|
||||
test.beforeAll(async ({ api }) => {
|
||||
const statusCode = (await api.post('/livechat/users/agent', { username: 'user1' })).status();
|
||||
expect(statusCode).toBe(200);
|
||||
});
|
||||
|
||||
test.beforeAll(async ({ browser, api }) => {
|
||||
await api.post('/settings/Livechat_clear_local_storage_when_chat_ended', { value: true });
|
||||
({ page: omniPage } = await createAuxContext(browser, Users.user1, '/', true));
|
||||
poHomeOmnichannel = new HomeOmnichannel(omniPage);
|
||||
|
||||
({ page: livechatPage } = await createAuxContext(browser, Users.user1, '/livechat', false));
|
||||
poLiveChat = new OmnichannelLiveChat(livechatPage, api);
|
||||
|
||||
await poLiveChat.sendMessageAndCloseChat(firstVisitor);
|
||||
});
|
||||
|
||||
test.afterAll(async ({ api }) => {
|
||||
await Promise.all([
|
||||
api.post('/settings/Livechat_clear_local_storage_when_chat_ended', { value: false }),
|
||||
api.delete('/livechat/users/agent/user1'),
|
||||
livechatPage.close(),
|
||||
omniPage.close(),
|
||||
]);
|
||||
});
|
||||
|
||||
test('OC - Livechat - Resub after close room', async () => {
|
||||
await test.step('expect livechat conversation to be opened again, different guest', async () => {
|
||||
await poLiveChat.startNewChat();
|
||||
await poLiveChat.sendMessage(secondVisitor, false);
|
||||
await poLiveChat.onlineAgentMessage.fill('this_a_test_message_from_user');
|
||||
await poLiveChat.btnSendMessageToOnlineAgent.click();
|
||||
await expect(poLiveChat.page.locator('div >> text="this_a_test_message_from_user"')).toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('expect message to be received by agent', async () => {
|
||||
await poHomeOmnichannel.navbar.openChat(secondVisitor.name);
|
||||
await expect(poHomeOmnichannel.content.lastUserMessage).toBeVisible();
|
||||
await expect(poHomeOmnichannel.content.lastUserMessage).toContainText('this_a_test_message_from_user');
|
||||
});
|
||||
|
||||
await test.step('expect message to be sent by agent', async () => {
|
||||
await poHomeOmnichannel.content.sendMessage('this_a_test_message_from_agent');
|
||||
await expect(poLiveChat.page.locator('div >> text="this_a_test_message_from_agent"')).toBeVisible();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('OC - Livechat - Resume chat after closing', () => {
|
||||
let poLiveChat: OmnichannelLiveChat;
|
||||
let poHomeOmnichannel: HomeOmnichannel;
|
||||
let livechatPage: Page;
|
||||
let omniPage: Page;
|
||||
|
||||
test.beforeAll(async ({ api }) => {
|
||||
const statusCode = (await api.post('/livechat/users/agent', { username: 'user1' })).status();
|
||||
expect(statusCode).toBe(200);
|
||||
});
|
||||
|
||||
test.beforeAll(async ({ browser, api }) => {
|
||||
({ page: omniPage } = await createAuxContext(browser, Users.user1, '/', true));
|
||||
poHomeOmnichannel = new HomeOmnichannel(omniPage);
|
||||
|
||||
({ page: livechatPage } = await createAuxContext(browser, Users.user1, '/livechat', false));
|
||||
poLiveChat = new OmnichannelLiveChat(livechatPage, api);
|
||||
|
||||
await poLiveChat.sendMessageAndCloseChat(firstVisitor);
|
||||
});
|
||||
|
||||
test.afterAll(async ({ api }) => {
|
||||
await Promise.all([api.delete('/livechat/users/agent/user1'), livechatPage.close(), omniPage.close()]);
|
||||
});
|
||||
|
||||
test('OC - Livechat - Resume chat after closing', async () => {
|
||||
await test.step('expect livechat conversation to be opened again', async () => {
|
||||
await poLiveChat.startNewChat();
|
||||
await expect(poLiveChat.onlineAgentMessage).toBeVisible();
|
||||
await poLiveChat.onlineAgentMessage.fill('this_a_test_message_from_user');
|
||||
await poLiveChat.btnSendMessageToOnlineAgent.click();
|
||||
await expect(poLiveChat.page.locator('div >> text="this_a_test_message_from_user"')).toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('expect message to be received by agent', async () => {
|
||||
await poHomeOmnichannel.navbar.openChat(firstVisitor.name);
|
||||
await expect(poHomeOmnichannel.content.lastUserMessage).toBeVisible();
|
||||
await expect(poHomeOmnichannel.content.lastUserMessage).toContainText('this_a_test_message_from_user');
|
||||
});
|
||||
|
||||
await test.step('expect message to be sent by agent', async () => {
|
||||
await poHomeOmnichannel.content.sendMessage('this_a_test_message_from_agent');
|
||||
await expect(poLiveChat.page.locator('div >> text="this_a_test_message_from_agent"')).toBeVisible();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('OC - Livechat - Close chat using widget', () => {
|
||||
let poLiveChat: OmnichannelLiveChat;
|
||||
let agent: Awaited<ReturnType<typeof createAgent>>;
|
||||
|
||||
test.beforeAll(async ({ api, browser }) => {
|
||||
agent = await createAgent(api, 'user1');
|
||||
|
||||
await createAuxContext(browser, Users.user1, '/', true);
|
||||
});
|
||||
|
||||
test.beforeEach(async ({ page, api }) => {
|
||||
poLiveChat = new OmnichannelLiveChat(page, api);
|
||||
|
||||
await poLiveChat.goto();
|
||||
});
|
||||
|
||||
test.afterAll(async () => {
|
||||
await agent.delete();
|
||||
});
|
||||
|
||||
test('OC - Livechat - Close Chat', async () => {
|
||||
await poLiveChat.openAnyLiveChat();
|
||||
await poLiveChat.sendMessage(firstVisitor, false);
|
||||
await poLiveChat.onlineAgentMessage.fill('this_a_test_message_from_user');
|
||||
await poLiveChat.btnSendMessageToOnlineAgent.click();
|
||||
|
||||
await test.step('expect to close a livechat conversation', async () => {
|
||||
await expect(poLiveChat.btnOptions).toBeVisible();
|
||||
await poLiveChat.btnOptions.click();
|
||||
|
||||
await expect(poLiveChat.btnCloseChat).toBeVisible();
|
||||
await poLiveChat.btnCloseChat.click();
|
||||
|
||||
await poLiveChat.btnCloseChatConfirm.click();
|
||||
|
||||
await expect(poLiveChat.btnNewChat).toBeVisible();
|
||||
});
|
||||
});
|
||||
|
||||
test('OC - Livechat - Close Chat twice', async () => {
|
||||
await poLiveChat.sendMessageAndCloseChat(firstVisitor);
|
||||
await poLiveChat.startNewChat();
|
||||
await poLiveChat.onlineAgentMessage.fill('this_a_test_message_from_user');
|
||||
await poLiveChat.btnSendMessageToOnlineAgent.click();
|
||||
|
||||
await test.step('expect to close a livechat conversation a second time', async () => {
|
||||
await expect(poLiveChat.btnOptions).toBeVisible();
|
||||
await poLiveChat.btnOptions.click();
|
||||
|
||||
await expect(poLiveChat.btnCloseChat).toBeVisible();
|
||||
await poLiveChat.btnCloseChat.click();
|
||||
|
||||
await poLiveChat.btnCloseChatConfirm.click();
|
||||
|
||||
await expect(poLiveChat.btnNewChat).toBeVisible();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('OC - Livechat - Livechat_Display_Offline_Form', () => {
|
||||
let poLiveChat: OmnichannelLiveChat;
|
||||
const message = 'This form is not available';
|
||||
|
||||
test.beforeAll(async ({ api }) => {
|
||||
await api.post('/settings/Livechat_display_offline_form', { value: false });
|
||||
await api.post('/settings/Livechat_offline_form_unavailable', { value: message });
|
||||
});
|
||||
|
||||
test.beforeEach(async ({ page, api }) => {
|
||||
poLiveChat = new OmnichannelLiveChat(page, api);
|
||||
await poLiveChat.goto();
|
||||
});
|
||||
|
||||
test.afterAll(async ({ api }) => {
|
||||
await api.post('/settings/Livechat_display_offline_form', { value: true });
|
||||
await api.post('/settings/Livechat_offline_form_unavailable', { value: '' });
|
||||
});
|
||||
|
||||
test('OC - Livechat - Livechat_Display_Offline_Form false', async () => {
|
||||
await test.step('expect offline form to not be visible', async () => {
|
||||
await poLiveChat.openAnyLiveChat();
|
||||
await expect(poLiveChat.page.locator(`div >> text=${message}`)).toBeVisible();
|
||||
await expect(poLiveChat.textAreaMessage).not.toBeVisible();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,229 @@
|
||||
import { faker } from '@faker-js/faker';
|
||||
import type { Page } from '@playwright/test';
|
||||
|
||||
import { IS_EE } from '../config/constants';
|
||||
import { Users } from '../fixtures/userStates';
|
||||
import { HomeOmnichannel } from '../page-objects';
|
||||
import { OmnichannelAgents, OmnichannelManager, OmnichannelMonitors } from '../page-objects/omnichannel';
|
||||
import { setSettingValueById } from '../utils';
|
||||
import { createAgent, makeAgentAvailable } from '../utils/omnichannel/agents';
|
||||
import { createDepartment } from '../utils/omnichannel/departments';
|
||||
import { createManager } from '../utils/omnichannel/managers';
|
||||
import { createConversation } from '../utils/omnichannel/rooms';
|
||||
import { test, expect } from '../utils/test';
|
||||
|
||||
const MANAGER = 'user3';
|
||||
const ROOM_A = faker.person.fullName();
|
||||
const ROOM_B = faker.person.fullName();
|
||||
const ROOM_C = faker.person.fullName();
|
||||
|
||||
test.use({ storageState: Users.user3.state });
|
||||
|
||||
test.describe('OC - Manager Role', () => {
|
||||
test.skip(!IS_EE, 'Enterprise Edition Only');
|
||||
|
||||
let departments: Awaited<ReturnType<typeof createDepartment>>[];
|
||||
let conversations: Awaited<ReturnType<typeof createConversation>>[];
|
||||
let agents: Awaited<ReturnType<typeof createAgent>>[];
|
||||
let poOmnichannel: HomeOmnichannel;
|
||||
|
||||
let manager: Awaited<ReturnType<typeof createManager>>;
|
||||
|
||||
// Allow manual on hold
|
||||
test.beforeAll(async ({ api }) => {
|
||||
const responses = await Promise.all([
|
||||
api.post('/settings/Livechat_allow_manual_on_hold', { value: true }),
|
||||
api.post('/settings/Livechat_allow_manual_on_hold_upon_agent_engagement_only', { value: false }),
|
||||
]);
|
||||
responses.forEach((res) => expect(res.status()).toBe(200));
|
||||
});
|
||||
|
||||
// Create agents
|
||||
test.beforeAll(async ({ api }) => {
|
||||
agents = await Promise.all([createAgent(api, 'user1'), createAgent(api, 'user2'), createAgent(api, MANAGER)]);
|
||||
|
||||
const agentsStatuses = await Promise.all(agents.slice(0, 2).map(({ data: agent }) => makeAgentAvailable(api, agent._id)));
|
||||
|
||||
agentsStatuses.forEach((res) => expect(res.status()).toBe(200));
|
||||
});
|
||||
|
||||
// Create departments
|
||||
test.beforeAll(async ({ api }) => {
|
||||
departments = await Promise.all([createDepartment(api), createDepartment(api)]);
|
||||
});
|
||||
|
||||
// Create manager
|
||||
test.beforeAll(async ({ api }) => {
|
||||
manager = await createManager(api, MANAGER);
|
||||
});
|
||||
|
||||
// Create conversations
|
||||
test.beforeAll(async ({ api }) => {
|
||||
const [departmentA, departmentB] = departments.map(({ data }) => data);
|
||||
|
||||
conversations = await Promise.all([
|
||||
createConversation(api, {
|
||||
visitorName: ROOM_A,
|
||||
visitorToken: 'roomA',
|
||||
agentId: `user1`,
|
||||
departmentId: departmentA._id,
|
||||
}),
|
||||
createConversation(api, {
|
||||
visitorName: ROOM_B,
|
||||
visitorToken: 'roomB',
|
||||
agentId: `user2`,
|
||||
departmentId: departmentB._id,
|
||||
}),
|
||||
createConversation(api, {
|
||||
visitorName: ROOM_C,
|
||||
visitorToken: 'roomC',
|
||||
agentId: `user2`,
|
||||
}),
|
||||
]);
|
||||
await setSettingValueById(api, 'Omnichannel_enable_department_removal', true);
|
||||
});
|
||||
|
||||
// Delete all created data
|
||||
test.afterAll(async ({ api }) => {
|
||||
await Promise.all([
|
||||
...agents.map((agent) => agent.delete()),
|
||||
...departments.map((department) => department.delete()),
|
||||
...conversations.map((conversation) => conversation.delete()),
|
||||
manager.delete(),
|
||||
// Reset setting
|
||||
api.post('/settings/Livechat_allow_manual_on_hold', { value: false }),
|
||||
api.post('/settings/Livechat_allow_manual_on_hold_upon_agent_engagement_only', { value: true }),
|
||||
]);
|
||||
await setSettingValueById(api, 'Omnichannel_enable_department_removal', false);
|
||||
});
|
||||
|
||||
test.beforeEach(async ({ page }: { page: Page }) => {
|
||||
poOmnichannel = new HomeOmnichannel(page);
|
||||
await poOmnichannel.chats.goto();
|
||||
});
|
||||
|
||||
test('OC - Manager Role - Basic permissions', async () => {
|
||||
await test.step('expect agent to not have access to omnichannel administration', async () => {
|
||||
await expect(poOmnichannel.omnisidenav.getSidebarLinkByName('Contact Center')).toBeVisible();
|
||||
await expect(poOmnichannel.omnisidenav.getSidebarLinkByName('Analytics')).toBeVisible();
|
||||
await expect(poOmnichannel.omnisidenav.getSidebarLinkByName('Real-time Monitoring')).toBeVisible();
|
||||
await expect(poOmnichannel.omnisidenav.getSidebarLinkByName('Agents')).toBeVisible();
|
||||
await expect(poOmnichannel.omnisidenav.getSidebarLinkByName('Departments')).toBeVisible();
|
||||
await expect(poOmnichannel.omnisidenav.getSidebarLinkByName('Business Hours')).toBeVisible();
|
||||
await expect(poOmnichannel.omnisidenav.getSidebarLinkByName('Reports')).toBeVisible();
|
||||
await expect(poOmnichannel.omnisidenav.getSidebarLinkByName('Canned Responses')).toBeVisible();
|
||||
});
|
||||
});
|
||||
|
||||
test('OC - Manager Role - Contact Center', async () => {
|
||||
await test.step('expect to be able to view all chats', async () => {
|
||||
await expect(poOmnichannel.chats.table.findRowByName(ROOM_A)).toBeVisible();
|
||||
await expect(poOmnichannel.chats.table.findRowByName(ROOM_B)).toBeVisible();
|
||||
await expect(poOmnichannel.chats.table.findRowByName(ROOM_C)).toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('expect to be able to join chats', async () => {
|
||||
await poOmnichannel.chats.openChat(ROOM_A);
|
||||
await expect(poOmnichannel.composer.btnJoinRoom).toBeVisible();
|
||||
await expect(poOmnichannel.composer.inputMessage).not.toBeVisible();
|
||||
|
||||
await poOmnichannel.composer.btnJoinRoom.click();
|
||||
await expect(poOmnichannel.content.lastSystemMessageBody).toHaveText('joined the channel');
|
||||
await expect(poOmnichannel.composer.btnJoinRoom).not.toBeVisible();
|
||||
await expect(poOmnichannel.composer.inputMessage).toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('expect to be able to put a conversation from another agent on hold', async () => {
|
||||
await poOmnichannel.quickActionsRoomToolbar.placeChatOnHold();
|
||||
await expect(poOmnichannel.content.lastSystemMessageBody).toHaveText(
|
||||
`Chat On Hold: The chat was manually placed On Hold by ${MANAGER}`,
|
||||
);
|
||||
await expect(poOmnichannel.composer.inputMessage).not.toBeVisible();
|
||||
await expect(poOmnichannel.content.btnResume).toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('expect to be able resume a conversation from another agent on hold', async () => {
|
||||
await poOmnichannel.content.btnResume.click();
|
||||
await expect(poOmnichannel.content.btnResume).not.toBeVisible();
|
||||
await expect(poOmnichannel.composer.inputMessage).toBeVisible();
|
||||
await expect(poOmnichannel.quickActionsRoomToolbar.btnOnHold).toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('expect to be able to close a conversation from another agent', async () => {
|
||||
await poOmnichannel.quickActionsRoomToolbar.closeChat();
|
||||
await poOmnichannel.chats.goto();
|
||||
});
|
||||
|
||||
await test.step('expect to be able to remove closed rooms', async () => {
|
||||
await poOmnichannel.chats.removeChatByName(ROOM_A);
|
||||
await expect(poOmnichannel.chats.table.findRowByName(ROOM_A)).not.toBeVisible();
|
||||
});
|
||||
});
|
||||
|
||||
test('OC - Manager Role - Add/remove agents', async ({ page }) => {
|
||||
const poOmnichannelAgents = new OmnichannelAgents(page);
|
||||
await poOmnichannelAgents.goto();
|
||||
|
||||
await test.step('expect add "user1" as agent', async () => {
|
||||
await poOmnichannelAgents.selectUsername('user1');
|
||||
await poOmnichannelAgents.btnAddAgent.click();
|
||||
|
||||
await poOmnichannelAgents.inputSearch.fill('user1');
|
||||
await expect(poOmnichannelAgents.table.findRowByName('user1')).toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('expect remove "user1" as agent', async () => {
|
||||
await poOmnichannelAgents.inputSearch.fill('user1');
|
||||
await poOmnichannelAgents.deleteAgent('user1');
|
||||
|
||||
await poOmnichannelAgents.inputSearch.fill('');
|
||||
await poOmnichannelAgents.inputSearch.fill('user1');
|
||||
await expect(poOmnichannelAgents.table.findRowByName('user1')).toBeHidden();
|
||||
});
|
||||
});
|
||||
|
||||
test('OC - Manager Role - Add/remove managers', async ({ page }) => {
|
||||
const poOmnichannelManagers = new OmnichannelManager(page);
|
||||
await poOmnichannelManagers.goto();
|
||||
|
||||
await test.step('expect add "user1" as manager', async () => {
|
||||
await poOmnichannelManagers.selectUsername('user1');
|
||||
await poOmnichannelManagers.btnAddManager.click();
|
||||
|
||||
await expect(poOmnichannelManagers.table.findRowByName('user1')).toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('expect search for manager', async () => {
|
||||
await poOmnichannelManagers.search('user1');
|
||||
await expect(poOmnichannelManagers.table.findRowByName('user1')).toBeVisible();
|
||||
|
||||
await poOmnichannelManagers.search('NonExistingUser');
|
||||
await expect(poOmnichannelManagers.table.findRowByName('user1')).toBeHidden();
|
||||
await poOmnichannelManagers.clearSearch();
|
||||
});
|
||||
|
||||
await test.step('expect remove "user1" as manager', async () => {
|
||||
await poOmnichannelManagers.search('user1');
|
||||
await poOmnichannelManagers.removeManager('user1');
|
||||
|
||||
await expect(poOmnichannelManagers.table.findRowByName('user1')).toBeHidden();
|
||||
});
|
||||
});
|
||||
|
||||
test('OC - Manager Role - Add/remove monitors', async ({ page }) => {
|
||||
const poOmnichannelMonitors = new OmnichannelMonitors(page);
|
||||
await poOmnichannelMonitors.goto();
|
||||
|
||||
await test.step('expect to add agent as monitor', async () => {
|
||||
await expect(poOmnichannelMonitors.table.findRowByName('user1')).not.toBeVisible();
|
||||
await poOmnichannelMonitors.addMonitor('user1');
|
||||
await expect(poOmnichannelMonitors.table.findRowByName('user1')).toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('expect to remove agent from monitor', async () => {
|
||||
await poOmnichannelMonitors.removeMonitor('user1');
|
||||
|
||||
await expect(poOmnichannelMonitors.table.findRowByName('user1')).not.toBeVisible();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,45 @@
|
||||
import { Users } from '../fixtures/userStates';
|
||||
import { OmnichannelManager } from '../page-objects/omnichannel';
|
||||
import { test, expect } from '../utils/test';
|
||||
|
||||
test.use({ storageState: Users.admin.state });
|
||||
|
||||
test.describe.serial('omnichannel-manager', () => {
|
||||
let poOmnichannelManagers: OmnichannelManager;
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
poOmnichannelManagers = new OmnichannelManager(page);
|
||||
await poOmnichannelManagers.goto();
|
||||
});
|
||||
|
||||
test('OC - Manage Managers - Add, Search and Remove', async ({ page }) => {
|
||||
await test.step('expect "user1" be first ', async () => {
|
||||
await poOmnichannelManagers.inputUsername.fill('user');
|
||||
await expect(page.locator('role=option[name="user1"]')).toContainText('user1');
|
||||
});
|
||||
|
||||
await test.step('expect add "user1" as manager', async () => {
|
||||
await poOmnichannelManagers.selectUsername('user1');
|
||||
await poOmnichannelManagers.btnAddManager.click();
|
||||
|
||||
await expect(poOmnichannelManagers.table.findRowByName('user1')).toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('expect search for manager', async () => {
|
||||
await poOmnichannelManagers.search('user1');
|
||||
await expect(poOmnichannelManagers.table.findRowByName('user1')).toBeVisible();
|
||||
|
||||
await poOmnichannelManagers.search('NonExistingUser');
|
||||
await expect(poOmnichannelManagers.table.findRowByName('user1')).toBeHidden();
|
||||
|
||||
await poOmnichannelManagers.clearSearch();
|
||||
});
|
||||
|
||||
await test.step('expect remove "user1" as manager', async () => {
|
||||
await poOmnichannelManagers.search('user1');
|
||||
await poOmnichannelManagers.removeManager('user1');
|
||||
|
||||
await expect(poOmnichannelManagers.table.findRowByName('user1')).toBeHidden();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,76 @@
|
||||
import type { Page } from '@playwright/test';
|
||||
|
||||
import { DEFAULT_USER_CREDENTIALS } from '../config/constants';
|
||||
import injectInitialData from '../fixtures/inject-initial-data';
|
||||
import { Users } from '../fixtures/userStates';
|
||||
import { HomeOmnichannel } from '../page-objects';
|
||||
import { createAgent, makeAgentAvailable } from '../utils/omnichannel/agents';
|
||||
import { createConversation } from '../utils/omnichannel/rooms';
|
||||
import { test, expect } from '../utils/test';
|
||||
|
||||
test.use({ storageState: Users.user1.state });
|
||||
|
||||
test.describe('OC - Manual Selection After Relogin', () => {
|
||||
let poOmnichannel: HomeOmnichannel;
|
||||
let agent: Awaited<ReturnType<typeof createAgent>>;
|
||||
|
||||
// Change routing method to manual selection
|
||||
test.beforeAll(async ({ api }) => {
|
||||
const res = await api.post('/settings/Livechat_Routing_Method', { value: 'Manual_Selection' });
|
||||
expect(res.status()).toBe(200);
|
||||
});
|
||||
|
||||
// Create agent and make it available
|
||||
test.beforeAll(async ({ api }) => {
|
||||
agent = await createAgent(api, 'user1');
|
||||
await makeAgentAvailable(api, agent.data._id);
|
||||
});
|
||||
|
||||
// Create page object and redirect to home
|
||||
test.beforeEach(async ({ page }: { page: Page }) => {
|
||||
poOmnichannel = new HomeOmnichannel(page);
|
||||
await poOmnichannel.goto();
|
||||
|
||||
await poOmnichannel.navbar.logout();
|
||||
await poOmnichannel.page.locator('role=textbox[name=/username/i]').waitFor({ state: 'visible' });
|
||||
await poOmnichannel.page.locator('role=textbox[name=/username/i]').fill('user1');
|
||||
await poOmnichannel.page.locator('[name=password]').fill(DEFAULT_USER_CREDENTIALS.password);
|
||||
await poOmnichannel.page.locator('role=button[name="Login"]').click();
|
||||
|
||||
await poOmnichannel.page.locator('#main-content').waitFor();
|
||||
});
|
||||
|
||||
// Delete all data
|
||||
test.afterAll(async ({ api }) => {
|
||||
await agent.delete();
|
||||
await api.post('/settings/Livechat_Routing_Method', { value: 'Auto_Selection' });
|
||||
await injectInitialData();
|
||||
});
|
||||
|
||||
test('OC - Manual Selection - Logout & Login', async ({ api }) => {
|
||||
expect(await poOmnichannel.page.locator('#omnichannel-status-toggle').getAttribute('title')).toEqual('Turn off answer chats');
|
||||
|
||||
const {
|
||||
data: { room },
|
||||
} = await createConversation(api);
|
||||
|
||||
await test.step('expect login and see the chat in queue after login', async () => {
|
||||
await poOmnichannel.sidebar.getSidebarItemByName(room.fname).click();
|
||||
await expect(poOmnichannel.composer.inputMessage).not.toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('expect take chat to be visible and return to queue not visible', async () => {
|
||||
await expect(poOmnichannel.content.btnTakeChat).toBeVisible();
|
||||
await expect(poOmnichannel.content.btnReturnToQueue).not.toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('expect to be able take chat', async () => {
|
||||
await poOmnichannel.content.btnTakeChat.click();
|
||||
await expect(poOmnichannel.content.lastSystemMessageBody).toHaveText('joined the channel');
|
||||
await expect(poOmnichannel.composer.inputMessage).toBeVisible();
|
||||
await expect(poOmnichannel.content.btnTakeChat).not.toBeVisible();
|
||||
await expect(poOmnichannel.content.btnReturnToQueue).toBeVisible();
|
||||
await expect(poOmnichannel.sidebar.getSidebarItemByName(room.fname)).toBeVisible();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,105 @@
|
||||
import type { Page } from '@playwright/test';
|
||||
|
||||
import { createAuxContext } from '../fixtures/createAuxContext';
|
||||
import { Users } from '../fixtures/userStates';
|
||||
import { HomeOmnichannel } from '../page-objects';
|
||||
import { createAgent, makeAgentAvailable } from '../utils/omnichannel/agents';
|
||||
import { createConversation } from '../utils/omnichannel/rooms';
|
||||
import { test, expect } from '../utils/test';
|
||||
|
||||
test.use({ storageState: Users.user3.state });
|
||||
|
||||
test.describe('OC - Manual Selection', () => {
|
||||
let poOmnichannel: HomeOmnichannel;
|
||||
let agents: Awaited<ReturnType<typeof createAgent>>[];
|
||||
let agentB: { page: Page; poHomeOmnichannel: HomeOmnichannel };
|
||||
|
||||
// Change routing method to manual selection
|
||||
test.beforeAll(async ({ api }) => {
|
||||
const res = await api.post('/settings/Livechat_Routing_Method', { value: 'Manual_Selection' });
|
||||
expect(res.status()).toBe(200);
|
||||
});
|
||||
|
||||
// Create agent and make it available
|
||||
test.beforeAll(async ({ api }) => {
|
||||
agents = await Promise.all([await createAgent(api, 'user3'), await createAgent(api, 'user1')]);
|
||||
(await Promise.all(agents.map(({ data: agent }) => makeAgentAvailable(api, agent._id)))).forEach((res) => {
|
||||
expect(res.status()).toBe(200);
|
||||
});
|
||||
});
|
||||
|
||||
// Create page object and redirect to home
|
||||
test.beforeEach(async ({ page }: { page: Page }) => {
|
||||
poOmnichannel = new HomeOmnichannel(page);
|
||||
await poOmnichannel.goto();
|
||||
});
|
||||
|
||||
// Create agent b session
|
||||
test.beforeEach(async ({ browser }) => {
|
||||
agentB = await createAuxContext(browser, Users.user1).then(({ page }) => ({ page, poHomeOmnichannel: new HomeOmnichannel(page) }));
|
||||
});
|
||||
|
||||
test.afterEach(async () => {
|
||||
await agentB.page.close();
|
||||
});
|
||||
// Delete all data
|
||||
test.afterAll(async ({ api }) => {
|
||||
await Promise.all([
|
||||
...agents.map((agent) => agent.delete()),
|
||||
api.post('/settings/Livechat_Routing_Method', { value: 'Auto_Selection' }),
|
||||
]);
|
||||
});
|
||||
|
||||
test('OC - Manual Selection - Queue', async ({ page, api }) => {
|
||||
const {
|
||||
data: { room },
|
||||
} = await createConversation(api);
|
||||
|
||||
await test.step('expect not be able to see queue when livechat is disabled', async () => {
|
||||
await poOmnichannel.navbar.switchOmnichannelStatus('offline');
|
||||
await agentB.poHomeOmnichannel.navbar.switchOmnichannelStatus('offline');
|
||||
await expect(poOmnichannel.sidebar.getSidebarItemByName(room.fname)).not.toBeVisible();
|
||||
await expect(agentB.poHomeOmnichannel.sidebar.getSidebarItemByName(room.fname)).not.toBeVisible();
|
||||
await poOmnichannel.navbar.switchOmnichannelStatus('online');
|
||||
await agentB.poHomeOmnichannel.navbar.switchOmnichannelStatus('online');
|
||||
await expect(poOmnichannel.sidebar.getSidebarItemByName(room.fname)).toBeVisible();
|
||||
await expect(agentB.poHomeOmnichannel.sidebar.getSidebarItemByName(room.fname)).toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('expect to be able join chat in read mode', async () => {
|
||||
await poOmnichannel.sidebar.getSidebarItemByName(room.fname).click();
|
||||
await expect(poOmnichannel.composer.inputMessage).not.toBeVisible();
|
||||
await expect(poOmnichannel.content.btnTakeChat).toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('expect to be able take chat', async () => {
|
||||
await poOmnichannel.content.btnTakeChat.click();
|
||||
await expect(poOmnichannel.content.lastSystemMessageBody).toHaveText('joined the channel');
|
||||
await expect(poOmnichannel.composer.inputMessage).toBeVisible();
|
||||
await expect(poOmnichannel.content.btnTakeChat).not.toBeVisible();
|
||||
await expect(poOmnichannel.sidebar.getSidebarItemByName(room.fname)).toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('expect chat to leave the queue', async () => {
|
||||
await page.waitForTimeout(250);
|
||||
await expect(agentB.poHomeOmnichannel.sidebar.getSidebarItemByName(room.fname)).not.toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('expect to be able return to queue', async () => {
|
||||
await poOmnichannel.content.btnReturnToQueue.click();
|
||||
await poOmnichannel.content.returnToQueueModal.confirm();
|
||||
await expect(page).toHaveURL('/home');
|
||||
});
|
||||
|
||||
await test.step('expect chat to be back in queue', async () => {
|
||||
// the returning agent can transiently see the room twice (queued inquiry + not-yet-removed subscription)
|
||||
await expect(poOmnichannel.sidebar.getSidebarItemByName(room.fname)).toHaveCount(1);
|
||||
await expect(poOmnichannel.sidebar.getSidebarItemByName(room.fname)).toBeVisible();
|
||||
await expect(agentB.poHomeOmnichannel.sidebar.getSidebarItemByName(room.fname)).toBeVisible();
|
||||
|
||||
await poOmnichannel.sidebar.getSidebarItemByName(room.fname).click();
|
||||
await expect(poOmnichannel.composer.inputMessage).not.toBeVisible();
|
||||
await expect(poOmnichannel.content.btnTakeChat).toBeVisible();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,184 @@
|
||||
import { faker } from '@faker-js/faker';
|
||||
import type { Page } from '@playwright/test';
|
||||
|
||||
import { IS_EE } from '../config/constants';
|
||||
import { Users } from '../fixtures/userStates';
|
||||
import { OmnichannelDepartments } from '../page-objects/omnichannel';
|
||||
import { setSettingValueById } from '../utils';
|
||||
import { createAgent } from '../utils/omnichannel/agents';
|
||||
import { createDepartment } from '../utils/omnichannel/departments';
|
||||
import { createMonitor } from '../utils/omnichannel/monitors';
|
||||
import { createOrUpdateUnit } from '../utils/omnichannel/units';
|
||||
import { test, expect } from '../utils/test';
|
||||
|
||||
const MONITOR = 'user3';
|
||||
|
||||
test.use({ storageState: Users.user3.state });
|
||||
|
||||
test.describe.serial('OC - Monitor Role', () => {
|
||||
test.skip(!IS_EE, 'Enterprise Edition Only');
|
||||
|
||||
let departments: Awaited<ReturnType<typeof createDepartment>>[];
|
||||
let agents: Awaited<ReturnType<typeof createAgent>>[];
|
||||
let monitor: Awaited<ReturnType<typeof createMonitor>>;
|
||||
let units: Awaited<ReturnType<typeof createOrUpdateUnit>>[];
|
||||
let poOmnichannelDepartments: OmnichannelDepartments;
|
||||
const newDepartmentName = faker.string.uuid();
|
||||
|
||||
// Reset user3 roles
|
||||
test.beforeAll(async ({ api }) => {
|
||||
const res = await api.post('/users.update', { data: { roles: ['user'] }, userId: MONITOR });
|
||||
await expect(res.status()).toBe(200);
|
||||
});
|
||||
|
||||
// Create agents
|
||||
test.beforeAll(async ({ api }) => {
|
||||
agents = await Promise.all([createAgent(api, 'user1'), createAgent(api, 'user2')]);
|
||||
});
|
||||
|
||||
// Create department
|
||||
test.beforeAll(async ({ api }) => {
|
||||
departments = await Promise.all([createDepartment(api), createDepartment(api)]);
|
||||
});
|
||||
|
||||
// Create monitor
|
||||
test.beforeAll(async ({ api }) => {
|
||||
monitor = await createMonitor(api, MONITOR);
|
||||
});
|
||||
|
||||
// Create unit
|
||||
test.beforeAll(async ({ api }) => {
|
||||
const [departmentA, departmentB] = departments.map((dep) => dep.data);
|
||||
|
||||
units = await Promise.all([
|
||||
await createOrUpdateUnit(api, {
|
||||
monitors: [{ monitorId: 'user2', username: 'user2' }],
|
||||
departments: [{ departmentId: departmentB._id }],
|
||||
}),
|
||||
await createOrUpdateUnit(api, {
|
||||
monitors: [{ monitorId: MONITOR, username: MONITOR }],
|
||||
departments: [{ departmentId: departmentA._id }],
|
||||
}),
|
||||
await createOrUpdateUnit(api, {
|
||||
monitors: [{ monitorId: MONITOR, username: MONITOR }],
|
||||
departments: [{ departmentId: departmentA._id }],
|
||||
}),
|
||||
]);
|
||||
await setSettingValueById(api, 'Omnichannel_enable_department_removal', true);
|
||||
});
|
||||
|
||||
// Delete all created data
|
||||
test.afterAll(async ({ api }) => {
|
||||
await Promise.all([
|
||||
...agents.map((agent) => agent.delete()),
|
||||
...departments.map((department) => department.delete()),
|
||||
...units.map((unit) => unit.delete()),
|
||||
monitor.delete(),
|
||||
]);
|
||||
await setSettingValueById(api, 'Omnichannel_enable_department_removal', false);
|
||||
});
|
||||
|
||||
test.beforeEach(async ({ page }: { page: Page }) => {
|
||||
poOmnichannelDepartments = new OmnichannelDepartments(page);
|
||||
|
||||
await poOmnichannelDepartments.goto();
|
||||
});
|
||||
|
||||
test('OC - Monitor Role - Create department with business unit', async () => {
|
||||
const [departmentA] = departments.map((dep) => dep.data);
|
||||
const [unitA, unitB, unitC] = units.map((unit) => unit.data);
|
||||
|
||||
await test.step('expect to see only departmentA in the list', async () => {
|
||||
await expect(poOmnichannelDepartments.table.findRowByName(departmentA.name)).toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('expect to fill departments mandatory field', async () => {
|
||||
await poOmnichannelDepartments.createNew();
|
||||
await poOmnichannelDepartments.inputName.fill(newDepartmentName);
|
||||
await poOmnichannelDepartments.inputEmail.fill(faker.internet.email());
|
||||
});
|
||||
|
||||
await test.step('expect to only have the units from monitor visible', async () => {
|
||||
await expect(poOmnichannelDepartments.inputUnit).not.toBeDisabled();
|
||||
await poOmnichannelDepartments.inputUnit.click();
|
||||
await expect(poOmnichannelDepartments.findOption(unitA.name)).not.toBeVisible();
|
||||
await expect(poOmnichannelDepartments.findOption(unitB.name)).toBeVisible();
|
||||
await expect(poOmnichannelDepartments.findOption(unitC.name)).toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('expect to be able to switch freely between available units', async () => {
|
||||
await poOmnichannelDepartments.findOption(unitC.name).click();
|
||||
await expect(poOmnichannelDepartments.inputUnit).not.toBeDisabled();
|
||||
await poOmnichannelDepartments.inputUnit.click();
|
||||
await poOmnichannelDepartments.findOption(unitB.name).click();
|
||||
});
|
||||
|
||||
await test.step('expect unit field to be required', async () => {
|
||||
await poOmnichannelDepartments.inputUnit.click();
|
||||
await poOmnichannelDepartments.findOption('None').click();
|
||||
await poOmnichannelDepartments.btnSave.click();
|
||||
await expect(poOmnichannelDepartments.errorMessage('Unit required')).toBeVisible();
|
||||
|
||||
await poOmnichannelDepartments.inputUnit.click();
|
||||
await poOmnichannelDepartments.findOption(unitB.name).click();
|
||||
await expect(poOmnichannelDepartments.errorMessage('Unit required')).not.toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('expect to save department', async () => {
|
||||
await poOmnichannelDepartments.labelEnabled.click();
|
||||
await poOmnichannelDepartments.btnSave.click();
|
||||
});
|
||||
|
||||
await test.step('expect to have departmentA and departmentB visible', async () => {
|
||||
await expect(poOmnichannelDepartments.table.findRowByName(departmentA.name)).toBeVisible();
|
||||
await expect(poOmnichannelDepartments.table.findRowByName(newDepartmentName)).toBeVisible();
|
||||
});
|
||||
});
|
||||
|
||||
test('OC - Monitor Role - Not allow editing department business unit', async () => {
|
||||
await test.step('expect not to be able to edit unit', async () => {
|
||||
await poOmnichannelDepartments.search(newDepartmentName);
|
||||
await poOmnichannelDepartments.getDepartmentMenuByName(newDepartmentName).click();
|
||||
await poOmnichannelDepartments.menuEditOption.click();
|
||||
await expect(poOmnichannelDepartments.inputUnit).toBeDisabled();
|
||||
});
|
||||
});
|
||||
|
||||
// TODO: We are going to prevent editing busines unit for now
|
||||
test.skip('OC - Monitor Role - Edit department business unit', async () => {
|
||||
const [departmentA] = departments.map((dep) => dep.data);
|
||||
const [, , unitC] = units.map((unit) => unit.data);
|
||||
|
||||
await test.step('expect to edit unit', async () => {
|
||||
await poOmnichannelDepartments.search(newDepartmentName);
|
||||
await poOmnichannelDepartments.getDepartmentMenuByName(newDepartmentName).click();
|
||||
await poOmnichannelDepartments.menuEditOption.click();
|
||||
await poOmnichannelDepartments.selectUnit(unitC.name);
|
||||
await poOmnichannelDepartments.labelEnabled.click();
|
||||
await poOmnichannelDepartments.btnSave.click();
|
||||
});
|
||||
|
||||
await test.step('expect departmentB to still be visible', async () => {
|
||||
await expect(poOmnichannelDepartments.table.findRowByName(departmentA.name)).toBeVisible();
|
||||
await expect(poOmnichannelDepartments.table.findRowByName(newDepartmentName)).toBeVisible();
|
||||
});
|
||||
});
|
||||
|
||||
test.skip('OC - Monitor Role - Edit department and remove business unit', async () => {
|
||||
const [departmentA] = departments.map((dep) => dep.data);
|
||||
|
||||
await test.step('expect to edit unit', async () => {
|
||||
await poOmnichannelDepartments.search(newDepartmentName);
|
||||
await poOmnichannelDepartments.getDepartmentMenuByName(newDepartmentName).click();
|
||||
await poOmnichannelDepartments.menuEditOption.click();
|
||||
await poOmnichannelDepartments.selectUnit('None');
|
||||
await poOmnichannelDepartments.labelEnabled.click();
|
||||
await poOmnichannelDepartments.btnSave.click();
|
||||
});
|
||||
|
||||
await test.step('expect departmentB to not be visible', async () => {
|
||||
await expect(poOmnichannelDepartments.table.findRowByName(departmentA.name)).toBeVisible();
|
||||
await expect(poOmnichannelDepartments.table.findRowByName(newDepartmentName)).not.toBeVisible();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,273 @@
|
||||
import { faker } from '@faker-js/faker';
|
||||
import type { Page } from '@playwright/test';
|
||||
|
||||
import { IS_EE } from '../config/constants';
|
||||
import { Users } from '../fixtures/userStates';
|
||||
import { HomeOmnichannel } from '../page-objects';
|
||||
import { setSettingValueById } from '../utils';
|
||||
import { createAgent, makeAgentAvailable } from '../utils/omnichannel/agents';
|
||||
import { createDepartment } from '../utils/omnichannel/departments';
|
||||
import { createMonitor } from '../utils/omnichannel/monitors';
|
||||
import { createConversation } from '../utils/omnichannel/rooms';
|
||||
import { createOrUpdateUnit, fetchUnitMonitors } from '../utils/omnichannel/units';
|
||||
import { test, expect } from '../utils/test';
|
||||
|
||||
const MONITOR = 'user3';
|
||||
const MONITOR_ADMIN = 'rocketchat.internal.admin.test';
|
||||
const ROOM_A = faker.person.fullName();
|
||||
const ROOM_B = faker.person.fullName();
|
||||
const ROOM_C = faker.person.fullName();
|
||||
const ROOM_D = faker.person.fullName();
|
||||
|
||||
test.use({ storageState: Users.user3.state });
|
||||
|
||||
test.describe('OC - Monitor Role', () => {
|
||||
test.skip(!IS_EE, 'Enterprise Edition Only');
|
||||
|
||||
let departments: Awaited<ReturnType<typeof createDepartment>>[];
|
||||
let conversations: Awaited<ReturnType<typeof createConversation>>[];
|
||||
let agents: Awaited<ReturnType<typeof createAgent>>[];
|
||||
let monitors: Awaited<ReturnType<typeof createMonitor>>[];
|
||||
let units: Awaited<ReturnType<typeof createOrUpdateUnit>>[];
|
||||
let poOmnichannel: HomeOmnichannel;
|
||||
|
||||
// Reset user3 roles
|
||||
test.beforeAll(async ({ api }) => {
|
||||
const res = await api.post('/users.update', {
|
||||
data: { roles: ['user'] },
|
||||
userId: 'user3',
|
||||
});
|
||||
expect(res.status()).toBe(200);
|
||||
});
|
||||
|
||||
// Allow manual on hold
|
||||
test.beforeAll(async ({ api }) => {
|
||||
const responses = await Promise.all([
|
||||
api.post('/settings/Livechat_allow_manual_on_hold', { value: true }),
|
||||
api.post('/settings/Livechat_allow_manual_on_hold_upon_agent_engagement_only', { value: false }),
|
||||
setSettingValueById(api, 'Omnichannel_enable_department_removal', true),
|
||||
// This is required now we're sending a chat into a department with no agents and no default agent
|
||||
api.post('/settings/Livechat_accept_chats_with_no_agents', { value: true }),
|
||||
]);
|
||||
responses.forEach((res) => expect(res.status()).toBe(200));
|
||||
});
|
||||
|
||||
// Create agents
|
||||
test.beforeAll(async ({ api }) => {
|
||||
agents = await Promise.all([createAgent(api, 'user1'), createAgent(api, 'user2')]);
|
||||
|
||||
const agentsStatuses = await Promise.all(agents.map(({ data: agent }) => makeAgentAvailable(api, agent._id)));
|
||||
|
||||
agentsStatuses.forEach((res) => expect(res.status()).toBe(200));
|
||||
});
|
||||
|
||||
// Create departments
|
||||
test.beforeAll(async ({ api }) => {
|
||||
departments = await Promise.all([createDepartment(api), createDepartment(api), createDepartment(api)]);
|
||||
});
|
||||
|
||||
// Create conversations
|
||||
test.beforeAll(async ({ api }) => {
|
||||
const [departmentA, departmentB, departmentC] = departments.map(({ data }) => data);
|
||||
|
||||
conversations = await Promise.all([
|
||||
createConversation(api, {
|
||||
visitorName: ROOM_A,
|
||||
agentId: `user1`,
|
||||
departmentId: departmentA._id,
|
||||
}),
|
||||
createConversation(api, {
|
||||
visitorName: ROOM_B,
|
||||
agentId: `user2`,
|
||||
departmentId: departmentA._id,
|
||||
}),
|
||||
createConversation(api, {
|
||||
visitorName: ROOM_C,
|
||||
agentId: `user2`,
|
||||
departmentId: departmentB._id,
|
||||
}),
|
||||
createConversation(api, {
|
||||
visitorName: ROOM_D,
|
||||
departmentId: departmentC._id,
|
||||
}),
|
||||
]);
|
||||
});
|
||||
|
||||
// Create monitors
|
||||
test.beforeAll(async ({ api }) => {
|
||||
monitors = await Promise.all([createMonitor(api, MONITOR), createMonitor(api, MONITOR_ADMIN)]);
|
||||
});
|
||||
|
||||
// Create units
|
||||
test.beforeAll(async ({ api }) => {
|
||||
const [departmentA, departmentB, departmentC] = departments.map(({ data }) => data);
|
||||
|
||||
units = await Promise.all([
|
||||
createOrUpdateUnit(api, {
|
||||
monitors: [{ monitorId: MONITOR, username: MONITOR }],
|
||||
departments: [{ departmentId: departmentA._id }, { departmentId: departmentB._id }],
|
||||
}),
|
||||
createOrUpdateUnit(api, {
|
||||
monitors: [{ monitorId: MONITOR_ADMIN, username: MONITOR_ADMIN }],
|
||||
departments: [{ departmentId: departmentC._id }],
|
||||
}),
|
||||
]);
|
||||
});
|
||||
|
||||
// Delete all created data
|
||||
test.afterAll(async ({ api }) => {
|
||||
await Promise.all([
|
||||
...agents.map((agent) => agent.delete()),
|
||||
...departments.map((department) => department.delete()),
|
||||
...conversations.map((conversation) => conversation.delete()),
|
||||
...units.map((unit) => unit.delete()),
|
||||
...monitors.map((monitor) => monitor.delete()),
|
||||
// Reset setting
|
||||
api.post('/settings/Livechat_allow_manual_on_hold', { value: false }),
|
||||
api.post('/settings/Livechat_allow_manual_on_hold_upon_agent_engagement_only', { value: true }),
|
||||
setSettingValueById(api, 'Omnichannel_enable_department_removal', false),
|
||||
api.post('/settings/Livechat_accept_chats_with_no_agents', { value: false }),
|
||||
]);
|
||||
});
|
||||
|
||||
test.beforeEach(async ({ page }: { page: Page }) => {
|
||||
poOmnichannel = new HomeOmnichannel(page);
|
||||
await poOmnichannel.chats.goto();
|
||||
});
|
||||
|
||||
test('OC - Monitor Role - Basic permissions', async () => {
|
||||
await test.step('expect agent to not have access to omnichannel administration', async () => {
|
||||
await expect(poOmnichannel.omnisidenav.getSidebarLinkByName('Contact Center')).toBeVisible();
|
||||
await expect(poOmnichannel.omnisidenav.getSidebarLinkByName('Analytics')).toBeVisible();
|
||||
await expect(poOmnichannel.omnisidenav.getSidebarLinkByName('Real-time Monitoring')).toBeVisible();
|
||||
await expect(poOmnichannel.omnisidenav.getSidebarLinkByName('Agents')).toBeVisible();
|
||||
await expect(poOmnichannel.omnisidenav.getSidebarLinkByName('Departments')).toBeVisible();
|
||||
await expect(poOmnichannel.omnisidenav.getSidebarLinkByName('Business Hours')).toBeVisible();
|
||||
await expect(poOmnichannel.omnisidenav.getSidebarLinkByName('Reports')).toBeVisible();
|
||||
await expect(poOmnichannel.omnisidenav.getSidebarLinkByName('Canned Responses')).toBeVisible();
|
||||
});
|
||||
|
||||
// await test.step('expect to be able to see contact center', async () => {});
|
||||
|
||||
// await test.step('expect to be able to see queue', async () => {});
|
||||
|
||||
// await test.step('expect to be able to edit custom fields', async () => {});
|
||||
});
|
||||
|
||||
test('OC - Monitor Role - Canned responses', async () => {
|
||||
// TODO: move to unit test
|
||||
await test.step('expect not to be able to create public canned responses (administration)', async () => {
|
||||
await poOmnichannel.cannedResponses.goto();
|
||||
await poOmnichannel.cannedResponses.btnNew.click();
|
||||
await expect(poOmnichannel.cannedResponses.radioPublic).toBeDisabled();
|
||||
});
|
||||
});
|
||||
|
||||
test('OC - Monitor Role - Contact Center', async () => {
|
||||
await test.step('expect to be able to view only chats from same unit', async () => {
|
||||
await expect(poOmnichannel.chats.table.findRowByName(ROOM_A)).toBeVisible();
|
||||
await expect(poOmnichannel.chats.table.findRowByName(ROOM_B)).toBeVisible();
|
||||
await expect(poOmnichannel.chats.table.findRowByName(ROOM_C)).toBeVisible();
|
||||
await expect(poOmnichannel.chats.table.findRowByName(ROOM_D)).not.toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('expect to be able to join chats from same unit', async () => {
|
||||
await poOmnichannel.chats.openChat(ROOM_A);
|
||||
await expect(poOmnichannel.composer.btnJoinRoom).toBeVisible();
|
||||
await expect(poOmnichannel.composer.inputMessage).not.toBeVisible();
|
||||
|
||||
await poOmnichannel.composer.btnJoinRoom.click();
|
||||
await expect(poOmnichannel.content.lastSystemMessageBody).toHaveText('joined the channel');
|
||||
await expect(poOmnichannel.composer.btnJoinRoom).not.toBeVisible();
|
||||
await expect(poOmnichannel.composer.inputMessage).toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('expect to be able to put a conversation from another agent on hold', async () => {
|
||||
await poOmnichannel.quickActionsRoomToolbar.placeChatOnHold();
|
||||
await expect(poOmnichannel.content.lastSystemMessageBody).toHaveText(
|
||||
`Chat On Hold: The chat was manually placed On Hold by ${MONITOR}`,
|
||||
);
|
||||
await expect(poOmnichannel.composer.inputMessage).not.toBeVisible();
|
||||
await expect(poOmnichannel.content.btnResume).toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('expect to be able resume a conversation from another agent on hold', async () => {
|
||||
await poOmnichannel.content.btnResume.click();
|
||||
await expect(poOmnichannel.content.btnResume).not.toBeVisible();
|
||||
await expect(poOmnichannel.composer.inputMessage).toBeVisible();
|
||||
await expect(poOmnichannel.quickActionsRoomToolbar.btnOnHold).toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('expect to be able to close a conversation from another agent', async () => {
|
||||
await poOmnichannel.quickActionsRoomToolbar.closeChat();
|
||||
await poOmnichannel.chats.goto();
|
||||
});
|
||||
|
||||
await test.step('expect not to be able to remove closed room', async () => {
|
||||
await expect(poOmnichannel.chats.table.findRowByName(ROOM_A)).toBeVisible();
|
||||
await expect(poOmnichannel.chats.table.btnRemoveByName(ROOM_A)).not.toBeVisible();
|
||||
});
|
||||
});
|
||||
|
||||
test('OC - Monitor Role - Permission revoked', async ({ page, api }) => {
|
||||
const [unitA, unitB] = units;
|
||||
const [monitor] = monitors;
|
||||
|
||||
const poContactCenterChats = poOmnichannel.chats;
|
||||
await poContactCenterChats.goto();
|
||||
|
||||
await test.step('expect not to be able to see chats from removed department', async () => {
|
||||
await test.step('expect rooms from both departments to be visible', async () => {
|
||||
await expect(poContactCenterChats.table.findRowByName(ROOM_B)).toBeVisible();
|
||||
await expect(poContactCenterChats.table.findRowByName(ROOM_C)).toBeVisible();
|
||||
await expect(poContactCenterChats.table.findRowByName(ROOM_D)).not.toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('expect to remove departmentB from unit', async () => {
|
||||
const [departmentA] = departments.map(({ data }) => data);
|
||||
|
||||
await createOrUpdateUnit(api, {
|
||||
id: unitA.data._id,
|
||||
monitors: [{ monitorId: MONITOR, username: MONITOR }],
|
||||
departments: [{ departmentId: departmentA._id }],
|
||||
});
|
||||
|
||||
await page.reload();
|
||||
});
|
||||
|
||||
await test.step('expect to have only room B visible', async () => {
|
||||
await expect(poContactCenterChats.table.findRowByName(ROOM_B)).toBeVisible();
|
||||
await expect(poContactCenterChats.table.findRowByName(ROOM_C)).not.toBeVisible();
|
||||
await expect(poContactCenterChats.table.findRowByName(ROOM_D)).not.toBeVisible();
|
||||
});
|
||||
});
|
||||
|
||||
await test.step('expect not to be able to see conversations once unit is removed', async () => {
|
||||
const res = await unitA.delete();
|
||||
expect(res.status()).toBe(200);
|
||||
await page.reload();
|
||||
await expect(poContactCenterChats.table.findRowByName(ROOM_B)).not.toBeVisible();
|
||||
await expect(poContactCenterChats.table.findRowByName(ROOM_C)).not.toBeVisible();
|
||||
await expect(poContactCenterChats.table.findRowByName(ROOM_D)).not.toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('expect to be able to see all conversations once all units are removed', async () => {
|
||||
const res = await unitB.delete();
|
||||
expect(res.status()).toBe(200);
|
||||
await page.reload();
|
||||
await expect(poContactCenterChats.table.findRowByName(ROOM_D)).toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('expect not to be able to see chats once role is removed', async () => {
|
||||
const res = await monitor.delete();
|
||||
expect(res.status()).toBe(200);
|
||||
await page.reload();
|
||||
await expect(page.locator('p >> text="You are not authorized to view this page."')).toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('expect monitor to be automaticaly removed from unit once monitor is removed', async () => {
|
||||
const { data: monitors } = await fetchUnitMonitors(api, unitA.data._id);
|
||||
expect(monitors).toHaveLength(0);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,82 @@
|
||||
import { IS_EE } from '../config/constants';
|
||||
import { Users } from '../fixtures/userStates';
|
||||
import { OmnichannelMonitors } from '../page-objects/omnichannel';
|
||||
import { test, expect } from '../utils/test';
|
||||
|
||||
test.use({ storageState: Users.user1.state });
|
||||
|
||||
test.skip(!IS_EE, 'OC - Manage Monitors > Enterprise Only');
|
||||
|
||||
test.describe.serial('OC - Manage Monitors', () => {
|
||||
let poMonitors: OmnichannelMonitors;
|
||||
|
||||
test.beforeAll(async ({ api }) => {
|
||||
await Promise.all([
|
||||
api.post('/livechat/users/agent', { username: 'user1' }),
|
||||
api.post('/livechat/users/agent', { username: 'user2' }),
|
||||
api.post('/livechat/users/manager', { username: 'user1' }),
|
||||
]);
|
||||
});
|
||||
|
||||
test.afterAll(async ({ api }) => {
|
||||
await Promise.all([
|
||||
api.delete('/livechat/users/agent/user1'),
|
||||
api.delete('/livechat/users/manager/user1'),
|
||||
api.delete('/livechat/users/agent/user2'),
|
||||
api.delete('/livechat/users/manager/user2'),
|
||||
]);
|
||||
});
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
poMonitors = new OmnichannelMonitors(page);
|
||||
await poMonitors.goto();
|
||||
});
|
||||
|
||||
test('OC - Manager Monitors - Add monitor', async () => {
|
||||
await test.step('expect to add agent as monitor', async () => {
|
||||
await expect(poMonitors.table.findRowByName('user1')).not.toBeVisible();
|
||||
await poMonitors.addMonitor('user1');
|
||||
await expect(poMonitors.table.findRowByName('user1')).toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('expect to remove agent from monitor', async () => {
|
||||
await poMonitors.removeMonitor('user1');
|
||||
await expect(poMonitors.table.findRowByName('user1')).not.toBeVisible();
|
||||
});
|
||||
});
|
||||
|
||||
test('OC - Manager Monitors - Search', async () => {
|
||||
await test.step('expect to add 2 monitors', async () => {
|
||||
await poMonitors.addMonitor('user1');
|
||||
await expect(poMonitors.table.findRowByName('user1')).toBeVisible();
|
||||
|
||||
await poMonitors.addMonitor('user2');
|
||||
await expect(poMonitors.table.findRowByName('user2')).toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('expect to search monitor', async () => {
|
||||
await expect(poMonitors.table.findRowByName('user1')).toBeVisible();
|
||||
await expect(poMonitors.table.findRowByName('user2')).toBeVisible();
|
||||
|
||||
await poMonitors.inputSearch.fill('user1');
|
||||
await expect(poMonitors.table.findRowByName('user1')).toBeVisible();
|
||||
await expect(poMonitors.table.findRowByName('user2')).not.toBeVisible();
|
||||
|
||||
await poMonitors.inputSearch.fill('user2');
|
||||
await expect(poMonitors.table.findRowByName('user1')).not.toBeVisible();
|
||||
await expect(poMonitors.table.findRowByName('user2')).toBeVisible();
|
||||
|
||||
await poMonitors.inputSearch.fill('');
|
||||
await expect(poMonitors.table.findRowByName('user1')).toBeVisible();
|
||||
await expect(poMonitors.table.findRowByName('user2')).toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('expect to remove monitors', async () => {
|
||||
await poMonitors.removeMonitor('user1');
|
||||
await expect(poMonitors.table.findRowByName('user1')).not.toBeVisible();
|
||||
|
||||
await poMonitors.removeMonitor('user2');
|
||||
await expect(poMonitors.table.findRowByName('user2')).not.toBeVisible();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,103 @@
|
||||
import { createFakeVisitor } from '../../mocks/data';
|
||||
import { IS_EE } from '../config/constants';
|
||||
import { Users } from '../fixtures/userStates';
|
||||
import { HomeOmnichannel } from '../page-objects';
|
||||
import { createConversation } from '../utils/omnichannel/rooms';
|
||||
import { test, expect } from '../utils/test';
|
||||
|
||||
const visitor = createFakeVisitor();
|
||||
|
||||
const getPrioritySystemMessage = (username: string, priority: string) =>
|
||||
`Priority changed: ${username} changed the priority to ${priority}`;
|
||||
|
||||
test.skip(!IS_EE, 'Omnichannel Priorities > Enterprise Only');
|
||||
|
||||
test.use({ storageState: Users.user1.state });
|
||||
|
||||
test.describe.serial('OC - Priorities [Sidebar]', () => {
|
||||
let poHomeChannel: HomeOmnichannel;
|
||||
|
||||
test.beforeAll(async ({ api }) => {
|
||||
(
|
||||
await Promise.all([
|
||||
api.post('/livechat/users/agent', { username: 'user1' }),
|
||||
api.post('/livechat/users/manager', { username: 'user1' }),
|
||||
api.post('/settings/Livechat_Routing_Method', { value: 'Manual_Selection' }),
|
||||
])
|
||||
).every((res) => expect(res.status()).toBe(200));
|
||||
});
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
poHomeChannel = new HomeOmnichannel(page);
|
||||
});
|
||||
|
||||
test.beforeEach(async () => {
|
||||
await poHomeChannel.goto();
|
||||
});
|
||||
|
||||
test.beforeEach(async ({ api }) => {
|
||||
await createConversation(api, { visitorName: visitor.name });
|
||||
});
|
||||
|
||||
test.afterAll(async ({ api }) => {
|
||||
(
|
||||
await Promise.all([
|
||||
api.delete('/livechat/users/agent/user1'),
|
||||
api.delete('/livechat/users/manager/user1'),
|
||||
api.post('/settings/Livechat_Routing_Method', { value: 'Auto_Selection' }),
|
||||
])
|
||||
).every((res) => expect(res.status()).toBe(200));
|
||||
});
|
||||
|
||||
test('OC - Priorities [Sidebar] - Update conversation priority', async ({ page }) => {
|
||||
const systemMessage = poHomeChannel.content.lastSystemMessageBody;
|
||||
await page.emulateMedia({ reducedMotion: 'reduce' });
|
||||
|
||||
await test.step('expect to change inquiry priority using sidebar menu', async () => {
|
||||
await poHomeChannel.sidebar.getSidebarItemByName(visitor.name).click();
|
||||
await expect(poHomeChannel.content.btnTakeChat).toBeVisible();
|
||||
|
||||
await expect(poHomeChannel.roomInfo.getLabel('Priority')).not.toBeVisible();
|
||||
|
||||
await poHomeChannel.sidebar.selectPriority(visitor.name, 'Lowest');
|
||||
await systemMessage.locator(`text="${getPrioritySystemMessage('user1', 'Lowest')}"`).waitFor();
|
||||
await expect(poHomeChannel.roomInfo.getLabel('Priority')).toBeVisible();
|
||||
await expect(poHomeChannel.sidebar.getBadgeIndicator(visitor.name, 'Lowest')).toBeVisible();
|
||||
await expect(poHomeChannel.roomInfo.getInfo('Lowest')).toBeVisible();
|
||||
|
||||
await poHomeChannel.sidebar.selectPriority(visitor.name, 'Highest');
|
||||
await systemMessage.locator(`text="${getPrioritySystemMessage('user1', 'Highest')}"`).waitFor();
|
||||
await expect(poHomeChannel.roomInfo.getInfo('Highest')).toBeVisible();
|
||||
await expect(poHomeChannel.sidebar.getBadgeIndicator(visitor.name, 'Highest')).toBeVisible();
|
||||
|
||||
await poHomeChannel.sidebar.selectPriority(visitor.name, 'Unprioritized');
|
||||
await systemMessage.locator(`text="${getPrioritySystemMessage('user1', 'Unprioritized')}"`).waitFor();
|
||||
await expect(poHomeChannel.roomInfo.getLabel('Priority')).not.toBeVisible();
|
||||
await expect(poHomeChannel.sidebar.getBadgeIndicator(visitor.name, 'Unprioritized')).not.toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('expect to change subscription priority using sidebar menu', async () => {
|
||||
await poHomeChannel.content.btnTakeChat.click();
|
||||
await systemMessage.locator('text="joined the channel"').waitFor();
|
||||
await page.waitForTimeout(500);
|
||||
|
||||
await expect(poHomeChannel.roomInfo.getLabel('Priority')).not.toBeVisible();
|
||||
|
||||
await poHomeChannel.sidebar.selectPriority(visitor.name, 'Lowest');
|
||||
await systemMessage.locator(`text="${getPrioritySystemMessage('user1', 'Lowest')}"`).waitFor();
|
||||
await expect(poHomeChannel.roomInfo.getLabel('Priority')).toBeVisible();
|
||||
await expect(poHomeChannel.roomInfo.getInfo('Lowest')).toBeVisible();
|
||||
await expect(poHomeChannel.sidebar.getBadgeIndicator(visitor.name, 'Lowest')).toBeVisible();
|
||||
|
||||
await poHomeChannel.sidebar.selectPriority(visitor.name, 'Highest');
|
||||
await systemMessage.locator(`text="${getPrioritySystemMessage('user1', 'Highest')}"`).waitFor();
|
||||
await expect(poHomeChannel.roomInfo.getInfo('Highest')).toBeVisible();
|
||||
await expect(poHomeChannel.sidebar.getBadgeIndicator(visitor.name, 'Highest')).toBeVisible();
|
||||
|
||||
await poHomeChannel.sidebar.selectPriority(visitor.name, 'Unprioritized');
|
||||
await systemMessage.locator(`text="${getPrioritySystemMessage('user1', 'Unprioritized')}"`).waitFor();
|
||||
await expect(poHomeChannel.roomInfo.getLabel('Priority')).not.toBeVisible();
|
||||
await expect(poHomeChannel.roomInfo.getInfo('Unprioritized')).not.toBeVisible();
|
||||
});
|
||||
});
|
||||
});
|
||||
127
apps/meteor/tests/e2e/omnichannel/omnichannel-priorities.spec.ts
Normal file
127
apps/meteor/tests/e2e/omnichannel/omnichannel-priorities.spec.ts
Normal file
@@ -0,0 +1,127 @@
|
||||
import { faker } from '@faker-js/faker';
|
||||
|
||||
import { IS_EE } from '../config/constants';
|
||||
import { Users } from '../fixtures/userStates';
|
||||
import { OmnichannelPriorities } from '../page-objects/omnichannel';
|
||||
import { test, expect } from '../utils/test';
|
||||
|
||||
const PRIORITY_NAME = faker.person.firstName();
|
||||
|
||||
const ERROR = {
|
||||
fieldNameRequired: 'Name required',
|
||||
};
|
||||
|
||||
test.skip(!IS_EE, 'Omnichannel Priorities > Enterprise Only');
|
||||
|
||||
test.use({ storageState: Users.user1.state });
|
||||
|
||||
test.describe.serial('Omnichannel Priorities', () => {
|
||||
let poOmnichannelPriorities: OmnichannelPriorities;
|
||||
|
||||
test.beforeAll(async ({ api }) => {
|
||||
await Promise.all([
|
||||
api.post('/livechat/users/agent', { username: 'user1' }),
|
||||
api.post('/livechat/users/manager', { username: 'user1' }),
|
||||
]);
|
||||
});
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
poOmnichannelPriorities = new OmnichannelPriorities(page);
|
||||
await poOmnichannelPriorities.goto();
|
||||
});
|
||||
|
||||
test.afterAll(async ({ api }) => {
|
||||
await Promise.all([api.delete('/livechat/users/agent/user1'), api.delete('/livechat/users/manager/user1')]);
|
||||
});
|
||||
|
||||
test('Manage Priorities', async () => {
|
||||
await test.step('All default priorities should be visible', async () => {
|
||||
await Promise.all([
|
||||
expect(poOmnichannelPriorities.findPriority('Highest')).toBeVisible(),
|
||||
expect(poOmnichannelPriorities.findPriority('High')).toBeVisible(),
|
||||
expect(poOmnichannelPriorities.findPriority('Medium')).toBeVisible(),
|
||||
expect(poOmnichannelPriorities.findPriority('Low')).toBeVisible(),
|
||||
expect(poOmnichannelPriorities.findPriority('Lowest')).toBeVisible(),
|
||||
]);
|
||||
});
|
||||
|
||||
await test.step('Add new priority', async () => {
|
||||
await expect(poOmnichannelPriorities.btnReset).toBeDisabled();
|
||||
await poOmnichannelPriorities.findPriority('Highest').click();
|
||||
|
||||
await test.step('default state', async () => {
|
||||
await Promise.all([
|
||||
expect(poOmnichannelPriorities.editPriority.btnSave).not.toBeDisabled(),
|
||||
expect(poOmnichannelPriorities.editPriority.inputName).toHaveValue('Highest'),
|
||||
]);
|
||||
});
|
||||
|
||||
await test.step('field name is required', async () => {
|
||||
await poOmnichannelPriorities.editPriority.inputName.fill('any_text');
|
||||
await poOmnichannelPriorities.editPriority.inputName.clear();
|
||||
await poOmnichannelPriorities.editPriority.btnSave.click();
|
||||
await expect(poOmnichannelPriorities.editPriority.errorMessage(ERROR.fieldNameRequired)).toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('should trim field name and show error if only spaces', async () => {
|
||||
await poOmnichannelPriorities.editPriority.inputName.fill(' ');
|
||||
await poOmnichannelPriorities.editPriority.btnSave.click();
|
||||
await expect(poOmnichannelPriorities.editPriority.errorMessage(ERROR.fieldNameRequired)).toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('edit and save priority', async () => {
|
||||
await poOmnichannelPriorities.editPriority.inputName.fill(PRIORITY_NAME);
|
||||
await expect(poOmnichannelPriorities.editPriority.errorMessage(ERROR.fieldNameRequired)).not.toBeVisible();
|
||||
await poOmnichannelPriorities.editPriority.save();
|
||||
|
||||
await Promise.all([
|
||||
expect(poOmnichannelPriorities.findPriority(PRIORITY_NAME)).toBeVisible(),
|
||||
expect(poOmnichannelPriorities.findPriority('Highest')).not.toBeVisible(),
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
await test.step('Reset priority', async () => {
|
||||
await test.step('reset individual', async () => {
|
||||
await poOmnichannelPriorities.findPriority(PRIORITY_NAME).click();
|
||||
await expect(poOmnichannelPriorities.editPriority.btnReset).toBeVisible();
|
||||
await poOmnichannelPriorities.editPriority.btnReset.click();
|
||||
await Promise.all([
|
||||
expect(poOmnichannelPriorities.editPriority.inputName).toHaveValue('Highest'),
|
||||
expect(poOmnichannelPriorities.editPriority.btnReset).toBeDisabled(),
|
||||
]);
|
||||
|
||||
await expect(poOmnichannelPriorities.editPriority.btnSave).toBeEnabled();
|
||||
await poOmnichannelPriorities.editPriority.save();
|
||||
await expect(poOmnichannelPriorities.findPriority('Highest')).toBeVisible();
|
||||
await expect(poOmnichannelPriorities.btnReset).toBeDisabled();
|
||||
});
|
||||
|
||||
await test.step('reset all', async () => {
|
||||
await poOmnichannelPriorities.findPriority('Highest').click();
|
||||
|
||||
await poOmnichannelPriorities.editPriority.inputName.fill(PRIORITY_NAME);
|
||||
await Promise.all([
|
||||
expect(poOmnichannelPriorities.editPriority.btnReset).toBeVisible(),
|
||||
expect(poOmnichannelPriorities.editPriority.btnSave).toBeEnabled(),
|
||||
]);
|
||||
await poOmnichannelPriorities.editPriority.save();
|
||||
|
||||
await Promise.all([
|
||||
expect(poOmnichannelPriorities.editPriority.inputName).not.toBeVisible(),
|
||||
expect(poOmnichannelPriorities.findPriority(PRIORITY_NAME)).toBeVisible(),
|
||||
expect(poOmnichannelPriorities.findPriority('Highest')).not.toBeVisible(),
|
||||
]);
|
||||
|
||||
await expect(poOmnichannelPriorities.btnReset).toBeEnabled();
|
||||
await poOmnichannelPriorities.resetPriorities();
|
||||
|
||||
await Promise.all([
|
||||
expect(poOmnichannelPriorities.btnReset).toBeDisabled(),
|
||||
expect(poOmnichannelPriorities.findPriority(PRIORITY_NAME)).not.toBeVisible(),
|
||||
expect(poOmnichannelPriorities.findPriority('Highest')).toBeVisible(),
|
||||
]);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
364
apps/meteor/tests/e2e/omnichannel/omnichannel-reports.spec.ts
Normal file
364
apps/meteor/tests/e2e/omnichannel/omnichannel-reports.spec.ts
Normal file
@@ -0,0 +1,364 @@
|
||||
import type { Route } from '@playwright/test';
|
||||
|
||||
import { IS_EE } from '../config/constants';
|
||||
import { Users } from '../fixtures/userStates';
|
||||
import { OmnichannelReports } from '../page-objects/omnichannel';
|
||||
import { test, expect } from '../utils/test';
|
||||
|
||||
const ENDPOINTS = {
|
||||
BY_STATUS: /\/v1\/livechat\/analytics\/dashboards\/conversations-by-status/,
|
||||
BY_SOURCE: /\/v1\/livechat\/analytics\/dashboards\/conversations-by-source/,
|
||||
BY_DEPARTMENT: /\/v1\/livechat\/analytics\/dashboards\/conversations-by-department/,
|
||||
BY_TAGS: /\/v1\/livechat\/analytics\/dashboards\/conversations-by-tags/,
|
||||
BY_AGENT: /\/v1\/livechat\/analytics\/dashboards\/conversations-by-agent/,
|
||||
};
|
||||
|
||||
test.skip(!IS_EE, 'Omnichannel Reports > Enterprise Only');
|
||||
|
||||
test.use({ storageState: Users.user1.state });
|
||||
|
||||
test.describe.serial('Omnichannel Reports', () => {
|
||||
let poReports: OmnichannelReports;
|
||||
|
||||
test.beforeAll(async ({ api }) => {
|
||||
const requests = await Promise.all([
|
||||
api.post('/livechat/users/agent', { username: 'user1' }),
|
||||
api.post('/livechat/users/manager', { username: 'user1' }),
|
||||
]);
|
||||
await expect(requests.every((request) => request.status() === 200)).toBe(true);
|
||||
});
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
poReports = new OmnichannelReports(page);
|
||||
});
|
||||
|
||||
test.beforeEach(async () => {
|
||||
await poReports.goto();
|
||||
});
|
||||
|
||||
test.afterAll(async ({ api }) => {
|
||||
await Promise.all([api.delete('/livechat/users/agent/user1'), api.delete('/livechat/users/manager/user1')]);
|
||||
});
|
||||
|
||||
test('Status Section', async ({ page }) => {
|
||||
await test.step('Empty state', async () => {
|
||||
await page.route(ENDPOINTS.BY_STATUS, async (route: Route) => {
|
||||
await route.fulfill({ json: { data: [], total: 0 } });
|
||||
});
|
||||
|
||||
await poReports.statusSection.selectPeriod('this week');
|
||||
await expect(poReports.statusSection.txtStateTitle).toHaveText('No data available for the selected period');
|
||||
await expect(poReports.statusSection.txtStateSubtitle).toHaveText('This chart will update as soon as conversations start.');
|
||||
await expect(poReports.statusSection.txtSummary).toHaveText('0 conversations, this week');
|
||||
});
|
||||
|
||||
await test.step('Error state', async () => {
|
||||
await page.route(ENDPOINTS.BY_STATUS, async (route: Route) => {
|
||||
await route.abort();
|
||||
});
|
||||
|
||||
await poReports.statusSection.selectPeriod('this month');
|
||||
await expect(poReports.statusSection.element).toHaveAttribute('aria-busy', 'false');
|
||||
await expect(poReports.statusSection.btnRetry).toBeVisible();
|
||||
await expect(poReports.statusSection.txtStateTitle).toHaveText('Something went wrong');
|
||||
|
||||
await test.step('Retry', async () => {
|
||||
await page.route(ENDPOINTS.BY_STATUS, async (route: Route) => {
|
||||
await route.fulfill({ json: { data: [], total: 0 } });
|
||||
});
|
||||
|
||||
const responsePromise = page.waitForResponse(ENDPOINTS.BY_STATUS);
|
||||
await poReports.statusSection.btnRetry.click();
|
||||
await responsePromise;
|
||||
});
|
||||
});
|
||||
|
||||
await test.step('Render data', async () => {
|
||||
const mock = {
|
||||
data: [
|
||||
{ label: 'Open', value: 25 },
|
||||
{ label: 'Queued', value: 25 },
|
||||
{ label: 'Closed', value: 25 },
|
||||
{ label: 'On_Hold', value: 25 },
|
||||
],
|
||||
total: 100,
|
||||
};
|
||||
|
||||
await page.route(ENDPOINTS.BY_STATUS, async (route: Route) => {
|
||||
const response = await route.fetch();
|
||||
await route.fulfill({ response, json: mock });
|
||||
});
|
||||
|
||||
await poReports.statusSection.selectPeriod('this year');
|
||||
await expect(poReports.statusSection.legendItem(`Closed 25 (25%)`)).toBeVisible();
|
||||
await expect(poReports.statusSection.legendItem(`Open 25 (25%)`)).toBeVisible();
|
||||
await expect(poReports.statusSection.legendItem(`Queued 25 (25%)`)).toBeVisible();
|
||||
await expect(poReports.statusSection.legendItem(`On hold 25 (25%)`)).toBeVisible();
|
||||
await expect(poReports.statusSection.txtSummary).toHaveText('100 conversations, this year');
|
||||
});
|
||||
});
|
||||
|
||||
test('Channels Section', async ({ page }) => {
|
||||
await test.step('Empty state', async () => {
|
||||
await page.route(ENDPOINTS.BY_SOURCE, async (route: Route) => {
|
||||
await route.fulfill({ json: { data: [], total: 0 } });
|
||||
});
|
||||
|
||||
await poReports.channelsSection.selectPeriod('this week');
|
||||
await expect(poReports.channelsSection.txtStateTitle).toHaveText('No data available for the selected period');
|
||||
await expect(poReports.channelsSection.txtStateSubtitle).toHaveText('This chart shows the most used channels.');
|
||||
await expect(poReports.channelsSection.txtSummary).toHaveText('0 conversations, this week');
|
||||
});
|
||||
|
||||
await test.step('Error state', async () => {
|
||||
await page.route(ENDPOINTS.BY_SOURCE, async (route: Route) => {
|
||||
await route.abort();
|
||||
});
|
||||
|
||||
await poReports.channelsSection.selectPeriod('last 15 days');
|
||||
await expect(poReports.channelsSection.element).toHaveAttribute('aria-busy', 'false');
|
||||
await expect(poReports.channelsSection.btnRetry).toBeVisible();
|
||||
await expect(poReports.channelsSection.txtStateTitle).toHaveText('Something went wrong');
|
||||
|
||||
await test.step('Retry', async () => {
|
||||
await page.route(ENDPOINTS.BY_SOURCE, async (route: Route) => {
|
||||
await route.fulfill({ json: { data: [], total: 0 } });
|
||||
});
|
||||
|
||||
const responsePromise = page.waitForResponse(ENDPOINTS.BY_SOURCE);
|
||||
await poReports.channelsSection.btnRetry.click();
|
||||
await responsePromise;
|
||||
});
|
||||
});
|
||||
|
||||
await test.step('Render data', async () => {
|
||||
const mock = {
|
||||
data: [
|
||||
{ label: 'Channel 1', value: 50 },
|
||||
{ label: 'Channel 2', value: 50 },
|
||||
],
|
||||
total: 100,
|
||||
};
|
||||
await page.route(ENDPOINTS.BY_SOURCE, async (route: Route) => {
|
||||
const response = await route.fetch();
|
||||
await route.fulfill({ response, json: mock });
|
||||
});
|
||||
|
||||
await poReports.channelsSection.selectPeriod('this year');
|
||||
await expect(poReports.channelsSection.legendItem(`Channel 1 50 (50%)`)).toBeVisible();
|
||||
await expect(poReports.channelsSection.legendItem(`Channel 2 50 (50%)`)).toBeVisible();
|
||||
await expect(poReports.channelsSection.txtSummary).toHaveText('100 conversations, this year');
|
||||
});
|
||||
|
||||
await test.step('More than 5 channels', async () => {
|
||||
const mock = {
|
||||
data: [
|
||||
{ label: 'Channel 1', value: 15 },
|
||||
{ label: 'Channel 2', value: 15 },
|
||||
{ label: 'Channel 3', value: 15 },
|
||||
{ label: 'Channel 4', value: 15 },
|
||||
{ label: 'Channel 5', value: 15 },
|
||||
{ label: 'Channel 6', value: 15 },
|
||||
{ label: 'Channel 7', value: 15 },
|
||||
{ label: 'Channel 8', value: 15 },
|
||||
],
|
||||
total: 120,
|
||||
};
|
||||
await page.route(ENDPOINTS.BY_SOURCE, async (route: Route) => {
|
||||
const response = await route.fetch();
|
||||
await route.fulfill({ response, json: mock });
|
||||
});
|
||||
|
||||
await poReports.channelsSection.selectPeriod('last 6 months');
|
||||
await expect(poReports.channelsSection.legendItem(`Others 45 (37.5%)`)).toBeVisible();
|
||||
await expect(poReports.channelsSection.txtSummary).toHaveText('120 conversations, last 6 months');
|
||||
});
|
||||
});
|
||||
|
||||
test('Departments Section', async ({ page }) => {
|
||||
await test.step('Empty state', async () => {
|
||||
await page.route(ENDPOINTS.BY_DEPARTMENT, async (route: Route) => {
|
||||
await route.fulfill({ json: { data: [], total: 0 } });
|
||||
});
|
||||
|
||||
await poReports.departmentsSection.selectPeriod('this week');
|
||||
await expect(poReports.departmentsSection.txtStateTitle).toHaveText('No data available for the selected period');
|
||||
await expect(poReports.departmentsSection.txtStateSubtitle).toHaveText(
|
||||
'This chart displays the departments that receive the most conversations.',
|
||||
);
|
||||
await expect(poReports.departmentsSection.txtSummary).toHaveText('0 departments and 0 conversations, this week');
|
||||
});
|
||||
|
||||
await test.step('Error state', async () => {
|
||||
await page.route(ENDPOINTS.BY_DEPARTMENT, async (route: Route) => {
|
||||
await route.abort();
|
||||
});
|
||||
|
||||
await poReports.departmentsSection.selectPeriod('this month');
|
||||
await expect(poReports.departmentsSection.element).toHaveAttribute('aria-busy', 'false');
|
||||
await expect(poReports.departmentsSection.btnRetry).toBeVisible();
|
||||
await expect(poReports.departmentsSection.txtStateTitle).toHaveText('Something went wrong');
|
||||
|
||||
await test.step('Retry', async () => {
|
||||
await page.route(ENDPOINTS.BY_DEPARTMENT, async (route: Route) => {
|
||||
await route.fulfill({ json: { data: [], total: 0 } });
|
||||
});
|
||||
|
||||
const responsePromise = page.waitForResponse(ENDPOINTS.BY_DEPARTMENT);
|
||||
await poReports.departmentsSection.btnRetry.click();
|
||||
await responsePromise;
|
||||
});
|
||||
});
|
||||
|
||||
await test.step('Render data', async () => {
|
||||
const mock = {
|
||||
data: [
|
||||
{ label: 'Department 1', value: 10 },
|
||||
{ label: 'Department 2', value: 20 },
|
||||
{ label: 'Department 3', value: 30 },
|
||||
{ label: 'Department 4', value: 40 },
|
||||
],
|
||||
total: 100,
|
||||
unspecified: 42,
|
||||
};
|
||||
await page.route(ENDPOINTS.BY_DEPARTMENT, async (route: Route) => {
|
||||
const response = await route.fetch();
|
||||
await route.fulfill({ response, json: mock });
|
||||
});
|
||||
|
||||
await poReports.departmentsSection.selectPeriod('last 6 months');
|
||||
await expect(poReports.departmentsSection.chartItem('Department 1', 10)).toBeVisible();
|
||||
await expect(poReports.departmentsSection.chartItem('Department 2', 20)).toBeVisible();
|
||||
await expect(poReports.departmentsSection.chartItem('Department 3', 30)).toBeVisible();
|
||||
await expect(poReports.departmentsSection.chartItem('Department 4', 40)).toBeVisible();
|
||||
await expect(poReports.departmentsSection.txtSummary).toHaveText(
|
||||
'4 departments and 100 conversations, last 6 months (42 without department)',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
test('Tags Section', async ({ page }) => {
|
||||
await test.step('Empty state', async () => {
|
||||
await page.route(ENDPOINTS.BY_TAGS, async (route: Route) => {
|
||||
await route.fulfill({ json: { data: [], total: 0 } });
|
||||
});
|
||||
|
||||
await poReports.tagsSection.selectPeriod('this week');
|
||||
await expect(poReports.tagsSection.txtStateTitle).toHaveText('No data available for the selected period');
|
||||
await expect(poReports.tagsSection.txtStateSubtitle).toHaveText('This chart shows the most frequently used tags.');
|
||||
await expect(poReports.tagsSection.txtSummary).toHaveText('0 tags and 0 conversations, this week');
|
||||
});
|
||||
|
||||
await test.step('Error state', async () => {
|
||||
await page.route(ENDPOINTS.BY_TAGS, async (route: Route) => {
|
||||
await route.abort();
|
||||
});
|
||||
|
||||
await poReports.tagsSection.selectPeriod('this month');
|
||||
await expect(poReports.tagsSection.element).toHaveAttribute('aria-busy', 'false');
|
||||
await expect(poReports.tagsSection.btnRetry).toBeVisible();
|
||||
await expect(poReports.tagsSection.txtStateTitle).toHaveText('Something went wrong');
|
||||
|
||||
await test.step('Retry', async () => {
|
||||
await page.route(ENDPOINTS.BY_TAGS, async (route: Route) => {
|
||||
await route.fulfill({ json: { data: [], total: 0 } });
|
||||
});
|
||||
|
||||
const responsePromise = page.waitForResponse(ENDPOINTS.BY_TAGS);
|
||||
await poReports.tagsSection.btnRetry.click();
|
||||
await responsePromise;
|
||||
});
|
||||
});
|
||||
|
||||
await test.step('Render data', async () => {
|
||||
const mock = {
|
||||
data: [
|
||||
{ label: 'Tag 1', value: 10 },
|
||||
{ label: 'Tag 2', value: 20 },
|
||||
{ label: 'Tag 3', value: 30 },
|
||||
{ label: 'Tag 4', value: 40 },
|
||||
],
|
||||
total: 100,
|
||||
unspecified: 42,
|
||||
};
|
||||
await page.route(ENDPOINTS.BY_TAGS, async (route: Route) => {
|
||||
const response = await route.fetch();
|
||||
await route.fulfill({ response, json: mock });
|
||||
});
|
||||
|
||||
await poReports.tagsSection.selectPeriod('last 6 months');
|
||||
await expect(poReports.tagsSection.chartItem('Tag 1', 10)).toBeVisible();
|
||||
await expect(poReports.tagsSection.chartItem('Tag 2', 20)).toBeVisible();
|
||||
await expect(poReports.tagsSection.chartItem('Tag 3', 30)).toBeVisible();
|
||||
await expect(poReports.tagsSection.chartItem('Tag 4', 40)).toBeVisible();
|
||||
await expect(poReports.tagsSection.txtSummary).toHaveText('4 tags and 100 conversations, last 6 months (42 without tags)');
|
||||
});
|
||||
});
|
||||
|
||||
test('Agents Section', async ({ page }) => {
|
||||
await test.step('Empty state', async () => {
|
||||
await page.route(ENDPOINTS.BY_AGENT, async (route: Route) => {
|
||||
await route.fulfill({ json: { data: [], total: 0 } });
|
||||
});
|
||||
|
||||
await poReports.agentsSection.selectPeriod('this week');
|
||||
await expect(poReports.agentsSection.txtStateTitle).toHaveText('No data available for the selected period');
|
||||
await expect(poReports.agentsSection.txtStateSubtitle).toHaveText(
|
||||
'This chart displays which agents receive the highest volume of conversations.',
|
||||
);
|
||||
await expect(poReports.agentsSection.txtSummary).toHaveText('0 agents and 0 conversations, this week');
|
||||
});
|
||||
|
||||
await test.step('Error state', async () => {
|
||||
await page.route(ENDPOINTS.BY_AGENT, async (route: Route) => {
|
||||
await route.abort();
|
||||
});
|
||||
|
||||
await poReports.agentsSection.selectPeriod('this month');
|
||||
await expect(poReports.agentsSection.element).toHaveAttribute('aria-busy', 'false');
|
||||
await expect(poReports.agentsSection.btnRetry).toBeVisible();
|
||||
await expect(poReports.agentsSection.txtStateTitle).toHaveText('Something went wrong');
|
||||
|
||||
await test.step('Retry', async () => {
|
||||
await page.route(ENDPOINTS.BY_AGENT, async (route: Route) => {
|
||||
await route.fulfill({ json: { data: [], total: 0 } });
|
||||
});
|
||||
|
||||
const responsePromise = page.waitForResponse(ENDPOINTS.BY_AGENT);
|
||||
await poReports.agentsSection.btnRetry.click();
|
||||
await responsePromise;
|
||||
});
|
||||
});
|
||||
|
||||
await test.step('Render data', async () => {
|
||||
const mock = {
|
||||
data: [
|
||||
{ label: 'Agent 1', value: 10 },
|
||||
{ label: 'Agent 2', value: 20 },
|
||||
{ label: 'Agent 3', value: 30 },
|
||||
{ label: 'Agent 4', value: 40 },
|
||||
],
|
||||
total: 100,
|
||||
unspecified: 42,
|
||||
};
|
||||
await page.route(ENDPOINTS.BY_AGENT, async (route: Route) => {
|
||||
const response = await route.fetch();
|
||||
await route.fulfill({ response, json: mock });
|
||||
});
|
||||
|
||||
await poReports.agentsSection.selectPeriod('last 6 months');
|
||||
|
||||
await expect(poReports.agentsSection.txtSummary).toHaveText('4 agents and 100 conversations, last 6 months (42 without assignee)');
|
||||
|
||||
await expect(poReports.agentsSection.chartItem('Agent 1', 10)).toBeVisible();
|
||||
await expect(poReports.agentsSection.chartItem('Agent 2', 20)).toBeVisible();
|
||||
await expect(poReports.agentsSection.chartItem('Agent 3', 30)).toBeVisible();
|
||||
await expect(poReports.agentsSection.chartItem('Agent 4', 40)).toBeVisible();
|
||||
|
||||
await expect(poReports.agentsSection.findRowByName('Agent 1')).toBeVisible();
|
||||
await expect(poReports.agentsSection.findRowByName('Agent 2')).toBeVisible();
|
||||
await expect(poReports.agentsSection.findRowByName('Agent 3')).toBeVisible();
|
||||
await expect(poReports.agentsSection.findRowByName('Agent 4')).toBeVisible();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,229 @@
|
||||
import type { Page } from '@playwright/test';
|
||||
|
||||
import { createFakeVisitor } from '../../mocks/data';
|
||||
import { IS_EE } from '../config/constants';
|
||||
import { createAuxContext } from '../fixtures/createAuxContext';
|
||||
import { Users } from '../fixtures/userStates';
|
||||
import { HomeOmnichannel } from '../page-objects';
|
||||
import { setSettingValueById } from '../utils';
|
||||
import { createAgent } from '../utils/omnichannel/agents';
|
||||
import { addAgentToDepartment, createDepartment } from '../utils/omnichannel/departments';
|
||||
import { createManager } from '../utils/omnichannel/managers';
|
||||
import { createConversation } from '../utils/omnichannel/rooms';
|
||||
import { test, expect } from '../utils/test';
|
||||
|
||||
test.use({ storageState: Users.user1.state });
|
||||
|
||||
test.describe('OC - Forwarding to away departments (EE)', () => {
|
||||
test.skip(!IS_EE, 'Enterprise Edition Only');
|
||||
|
||||
let poHomeOmnichannelOnlineAgent: HomeOmnichannel;
|
||||
let poHomeOmnichannelAwayAgent: HomeOmnichannel;
|
||||
|
||||
let omnichannelPage: Page | undefined;
|
||||
|
||||
let manager: Awaited<ReturnType<typeof createManager>>;
|
||||
let onlineAgent: Awaited<ReturnType<typeof createAgent>>;
|
||||
let awayAgent: Awaited<ReturnType<typeof createAgent>>;
|
||||
let initialDepartment: Awaited<ReturnType<typeof createDepartment>>;
|
||||
let forwardToOfflineDepartment: Awaited<ReturnType<typeof createDepartment>>;
|
||||
let conversation: Awaited<ReturnType<typeof createConversation>>;
|
||||
let visitor: { name: string; email: string };
|
||||
|
||||
test.beforeAll(async ({ api }) => {
|
||||
[manager, onlineAgent, awayAgent, initialDepartment, forwardToOfflineDepartment] = await Promise.all([
|
||||
createManager(api, 'user1'),
|
||||
createAgent(api, 'user1'),
|
||||
createAgent(api, 'user2'),
|
||||
createDepartment(api, { name: 'Initial Dept' }),
|
||||
createDepartment(api, { name: 'Forward Dept', allowReceiveForwardOffline: true }),
|
||||
]);
|
||||
await expect(manager.response).toBeOK();
|
||||
await expect(onlineAgent.response).toBeOK();
|
||||
await expect(awayAgent.response).toBeOK();
|
||||
await expect(initialDepartment.response).toBeOK();
|
||||
await expect(forwardToOfflineDepartment.response).toBeOK();
|
||||
|
||||
const responses = await Promise.all([
|
||||
setSettingValueById(api, 'Accounts_Default_User_Preferences_idleTimeLimit', 300),
|
||||
setSettingValueById(api, 'Omnichannel_enable_department_removal', true),
|
||||
setSettingValueById(api, 'Livechat_enabled_when_agent_idle', false),
|
||||
addAgentToDepartment(api, { department: initialDepartment.data, agentId: 'user1' }),
|
||||
addAgentToDepartment(api, { department: forwardToOfflineDepartment.data, agentId: 'user2' }),
|
||||
]);
|
||||
|
||||
for (const response of responses) {
|
||||
await expect(response).toBeOK();
|
||||
}
|
||||
});
|
||||
|
||||
test.beforeEach(async ({ page, browser, api }) => {
|
||||
visitor = createFakeVisitor();
|
||||
// Online Agent window opens with idleTimeLimit of 300 by default, therefore it will remain online
|
||||
poHomeOmnichannelOnlineAgent = new HomeOmnichannel(page);
|
||||
await poHomeOmnichannelOnlineAgent.goto();
|
||||
|
||||
await expect(await setSettingValueById(api, 'Accounts_Default_User_Preferences_idleTimeLimit', 1)).toBeOK();
|
||||
|
||||
// Away Agent window opens with idleTimeLimit of 1, therefore after a second it will turn away
|
||||
({ page: omnichannelPage } = await createAuxContext(browser, Users.user2, '/', false));
|
||||
poHomeOmnichannelAwayAgent = new HomeOmnichannel(omnichannelPage);
|
||||
await poHomeOmnichannelAwayAgent.waitForHome();
|
||||
await expect(poHomeOmnichannelAwayAgent.navbar.getUserStatusBadge('away')).toBeVisible();
|
||||
});
|
||||
|
||||
test.afterEach(async ({ api }) => {
|
||||
if (omnichannelPage) {
|
||||
await omnichannelPage.context().close();
|
||||
}
|
||||
|
||||
await expect(await setSettingValueById(api, 'Livechat_waiting_queue', false)).toBeOK();
|
||||
await expect(await setSettingValueById(api, 'Accounts_Default_User_Preferences_idleTimeLimit', 300)).toBeOK();
|
||||
});
|
||||
|
||||
test.afterAll(async ({ api }) => {
|
||||
const responses = await Promise.all([
|
||||
initialDepartment.delete(),
|
||||
forwardToOfflineDepartment.delete(),
|
||||
manager.delete(),
|
||||
onlineAgent.delete(),
|
||||
awayAgent.delete(),
|
||||
setSettingValueById(api, 'Livechat_Routing_Method', 'Auto_Selection'),
|
||||
setSettingValueById(api, 'Livechat_enabled_when_agent_idle', true),
|
||||
setSettingValueById(api, 'Omnichannel_enable_department_removal', false),
|
||||
]);
|
||||
for (const response of responses) {
|
||||
await expect(response).toBeOK();
|
||||
}
|
||||
});
|
||||
|
||||
test('when manager forward to offline (agent away, accept when agent idle off) department the inquiry should be set to the queue', async ({
|
||||
api,
|
||||
}) => {
|
||||
await test.step('Setup routing settings', async () => {
|
||||
await expect(await setSettingValueById(api, 'Livechat_Routing_Method', 'Manual_Selection')).toBeOK();
|
||||
});
|
||||
|
||||
await test.step('Visitor initiates chat', async () => {
|
||||
conversation = await createConversation(api, { visitorName: visitor.name, agentId: onlineAgent.data._id });
|
||||
});
|
||||
|
||||
await test.step('Manager forwards chat', async () => {
|
||||
await poHomeOmnichannelOnlineAgent.sidebar.getSidebarItemByName(visitor.name).click();
|
||||
await poHomeOmnichannelOnlineAgent.quickActionsRoomToolbar.forwardChat();
|
||||
await poHomeOmnichannelOnlineAgent.content.forwardChatModal.selectDepartment('Forward Dept');
|
||||
await poHomeOmnichannelOnlineAgent.content.forwardChatModal.btnForward.click();
|
||||
await expect(poHomeOmnichannelOnlineAgent.content.forwardChatModal.btnForward).not.toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('Check inquiry status via API is queued', async () => {
|
||||
const inquiryResp = await api.get(`/livechat/inquiries.getOne?roomId=${conversation.data.room._id}`);
|
||||
await expect(inquiryResp).toBeOK();
|
||||
const inquiryBody = await inquiryResp.json();
|
||||
|
||||
expect(inquiryBody.inquiry.status).toBe('queued');
|
||||
expect(inquiryBody.inquiry.department).toBe(forwardToOfflineDepartment.data._id);
|
||||
});
|
||||
});
|
||||
|
||||
test('when manager forward to a department while waiting_queue is active and allowReceiveForwardOffline is true, chat should end in departments queue', async ({
|
||||
api,
|
||||
}) => {
|
||||
await test.step('Setup routing settings', async () => {
|
||||
await expect(await setSettingValueById(api, 'Livechat_Routing_Method', 'Auto_Selection')).toBeOK();
|
||||
});
|
||||
|
||||
await test.step('Visitor initiates chat', async () => {
|
||||
conversation = await createConversation(api, { visitorName: visitor.name, agentId: onlineAgent.data._id });
|
||||
});
|
||||
|
||||
await test.step('Manager enables queue and forwards chat', async () => {
|
||||
await poHomeOmnichannelOnlineAgent.sidebar.getSidebarItemByName(visitor.name).click();
|
||||
await expect(await setSettingValueById(api, 'Livechat_waiting_queue', true)).toBeOK();
|
||||
|
||||
await poHomeOmnichannelOnlineAgent.quickActionsRoomToolbar.forwardChat();
|
||||
await poHomeOmnichannelOnlineAgent.content.forwardChatModal.selectDepartment('Forward Dept');
|
||||
await poHomeOmnichannelOnlineAgent.content.forwardChatModal.btnForward.click();
|
||||
await expect(poHomeOmnichannelOnlineAgent.content.forwardChatModal.btnForward).not.toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('Check inquiry status via API is queued', async () => {
|
||||
const inquiryResp = await api.get(`/livechat/inquiries.getOne?roomId=${conversation.data.room._id}`);
|
||||
await expect(inquiryResp).toBeOK();
|
||||
const inquiryBody = await inquiryResp.json();
|
||||
|
||||
expect(inquiryBody.inquiry.status).toBe('queued');
|
||||
expect(inquiryBody.inquiry.department).toBe(forwardToOfflineDepartment.data._id);
|
||||
});
|
||||
});
|
||||
|
||||
test('when manager forward to a department while waiting_queue is active and allowReceiveForwardOffline is false, transfer should fail', async ({
|
||||
api,
|
||||
}) => {
|
||||
await test.step('Setup routing and department settings', async () => {
|
||||
await expect(await setSettingValueById(api, 'Livechat_Routing_Method', 'Auto_Selection')).toBeOK();
|
||||
await expect(
|
||||
await api.put(`/livechat/department/${forwardToOfflineDepartment.data._id}`, {
|
||||
department: { ...forwardToOfflineDepartment.data, allowReceiveForwardOffline: false },
|
||||
}),
|
||||
).toBeOK();
|
||||
});
|
||||
|
||||
await test.step('Visitor initiates chat', async () => {
|
||||
conversation = await createConversation(api, { visitorName: visitor.name, agentId: onlineAgent.data._id });
|
||||
});
|
||||
|
||||
await test.step('Manager attempts to forward and sees error', async () => {
|
||||
await poHomeOmnichannelOnlineAgent.sidebar.getSidebarItemByName(visitor.name).click();
|
||||
await expect(await setSettingValueById(api, 'Livechat_waiting_queue', true)).toBeOK();
|
||||
|
||||
await poHomeOmnichannelOnlineAgent.quickActionsRoomToolbar.forwardChat();
|
||||
await poHomeOmnichannelOnlineAgent.content.forwardChatModal.selectDepartment('Forward Dept');
|
||||
await poHomeOmnichannelOnlineAgent.content.forwardChatModal.btnForward.click();
|
||||
await expect(poHomeOmnichannelOnlineAgent.page.locator('role=alert')).toContainText(
|
||||
'No agents are available for service on this department.',
|
||||
);
|
||||
});
|
||||
|
||||
await test.step('Restore department setting', async () => {
|
||||
await expect(
|
||||
await api.put(`/livechat/department/${forwardToOfflineDepartment.data._id}`, {
|
||||
department: { ...forwardToOfflineDepartment.data, allowReceiveForwardOffline: true },
|
||||
}),
|
||||
).toBeOK();
|
||||
});
|
||||
});
|
||||
|
||||
test('when manager forward to online (agent away, accept when agent idle on) department the inquiry should not be set to the queue', async ({
|
||||
api,
|
||||
}) => {
|
||||
await test.step('Setup routing settings', async () => {
|
||||
await expect(await setSettingValueById(api, 'Livechat_Routing_Method', 'Auto_Selection')).toBeOK();
|
||||
});
|
||||
|
||||
await test.step('Visitor initiates chat', async () => {
|
||||
conversation = await createConversation(api, { visitorName: visitor.name, agentId: onlineAgent.data._id });
|
||||
});
|
||||
|
||||
await test.step('Set Livechat_enabled_when_agent_idle to true', async () => {
|
||||
// We set Livechat_enabled_when_agent_idle to true here in order to not assign the away agent in the previous step
|
||||
await expect(await setSettingValueById(api, 'Livechat_enabled_when_agent_idle', true)).toBeOK();
|
||||
});
|
||||
|
||||
await test.step('Manager forwards chat successfully', async () => {
|
||||
await poHomeOmnichannelOnlineAgent.sidebar.getSidebarItemByName(visitor.name).click();
|
||||
await poHomeOmnichannelOnlineAgent.quickActionsRoomToolbar.forwardChat();
|
||||
await poHomeOmnichannelOnlineAgent.content.forwardChatModal.selectDepartment('Forward Dept');
|
||||
await poHomeOmnichannelOnlineAgent.content.forwardChatModal.btnForward.click();
|
||||
await expect(poHomeOmnichannelOnlineAgent.content.forwardChatModal.btnForward).not.toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('Check room routing via API serves to away agent', async () => {
|
||||
const inquiryResp = await api.get(`/livechat/inquiries.getOne?roomId=${conversation.data.room._id}`);
|
||||
await expect(inquiryResp).toBeOK();
|
||||
const inquiryBody = await inquiryResp.json();
|
||||
expect(inquiryBody.inquiry.status).toBe('taken');
|
||||
expect(inquiryBody.inquiry.department).toBe(forwardToOfflineDepartment.data._id);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,84 @@
|
||||
import type { Page } from '@playwright/test';
|
||||
|
||||
import { createFakeVisitor } from '../../mocks/data';
|
||||
import { IS_EE } from '../config/constants';
|
||||
import { createAuxContext } from '../fixtures/createAuxContext';
|
||||
import { Users } from '../fixtures/userStates';
|
||||
import { HomeOmnichannel } from '../page-objects';
|
||||
import { OmnichannelLiveChat } from '../page-objects/omnichannel';
|
||||
import { test, expect } from '../utils/test';
|
||||
|
||||
test.skip(!IS_EE, 'Export transcript as PDF > Enterprie Only');
|
||||
|
||||
test.describe('omnichannel- export chat transcript as PDF', () => {
|
||||
let poLiveChat: OmnichannelLiveChat;
|
||||
let newVisitor: { email: string; name: string };
|
||||
|
||||
let agent: { page: Page; poHomeChannel: HomeOmnichannel };
|
||||
test.beforeAll(async ({ api, browser }) => {
|
||||
newVisitor = createFakeVisitor();
|
||||
|
||||
// Set user user 1 as manager and agent
|
||||
await api.post('/livechat/users/agent', { username: 'user1' });
|
||||
await api.post('/livechat/users/manager', { username: 'user1' });
|
||||
|
||||
const { page } = await createAuxContext(browser, Users.user1);
|
||||
agent = { page, poHomeChannel: new HomeOmnichannel(page) };
|
||||
});
|
||||
test.beforeEach(async ({ page, api }) => {
|
||||
poLiveChat = new OmnichannelLiveChat(page, api);
|
||||
});
|
||||
|
||||
test.afterAll(async ({ api }) => {
|
||||
await api.delete('/livechat/users/agent/user1');
|
||||
await api.delete('/livechat/users/manager/user1');
|
||||
await agent.page.close();
|
||||
});
|
||||
|
||||
test('Export PDF transcript', async ({ page }) => {
|
||||
await test.step('Expect send a message as a visitor', async () => {
|
||||
await poLiveChat.goto();
|
||||
await poLiveChat.openLiveChat();
|
||||
await poLiveChat.sendMessage(newVisitor, false);
|
||||
await poLiveChat.onlineAgentMessage.type('this_a_test_message_from_visitor');
|
||||
await poLiveChat.btnSendMessageToOnlineAgent.click();
|
||||
});
|
||||
|
||||
await test.step('Expect to have 1 omnichannel assigned to agent 1', async () => {
|
||||
await new Promise((resolve) => setTimeout(resolve, 5000));
|
||||
await agent.poHomeChannel.navbar.openChat(newVisitor.name);
|
||||
});
|
||||
|
||||
await test.step('Expect to be not able send transcript as PDF', async () => {
|
||||
await agent.poHomeChannel.content.btnSendTranscript.click();
|
||||
await agent.poHomeChannel.content.btnSendTranscriptAsPDF.hover();
|
||||
await expect(agent.poHomeChannel.content.btnSendTranscriptAsPDF).toHaveAttribute('aria-disabled', 'true');
|
||||
});
|
||||
|
||||
await test.step('Expect chat to be closed', async () => {
|
||||
await agent.poHomeChannel.quickActionsRoomToolbar.closeChat({ downloadPDF: true });
|
||||
});
|
||||
|
||||
// Exported PDF can be downloaded from rocket.cat room
|
||||
await test.step('Expect to have exported PDF in rocket.cat', async () => {
|
||||
await page.waitForTimeout(3000);
|
||||
await agent.poHomeChannel.navbar.openChat('rocket.cat');
|
||||
await expect(agent.poHomeChannel.content.lastUserMessage.getByText('PDF Transcript successfully generated')).toBeVisible();
|
||||
await expect(agent.poHomeChannel.content.lastUserMessage.getByRole('link', { name: 'Transcript' })).toBeVisible();
|
||||
});
|
||||
|
||||
// PDF can be exported from Omnichannel Contact Center
|
||||
await test.step('Expect to have exported PDF in rocket.cat', async () => {
|
||||
await agent.poHomeChannel.navbar.btnContactCenter.click();
|
||||
await agent.poHomeChannel.transcript.contactCenterChats.click();
|
||||
await agent.poHomeChannel.transcript.contactCenterSearch.type(newVisitor.name);
|
||||
await page.waitForTimeout(3000);
|
||||
await agent.poHomeChannel.transcript.firstRow.click();
|
||||
await agent.poHomeChannel.transcript.btnOpenChat.click();
|
||||
await agent.poHomeChannel.content.btnSendTranscript.click();
|
||||
await expect(agent.poHomeChannel.content.btnSendTranscriptAsPDF).toHaveAttribute('aria-disabled', 'false');
|
||||
await agent.poHomeChannel.content.btnSendTranscriptAsPDF.click();
|
||||
await agent.poHomeChannel.toastMessage.waitForDisplay();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,63 @@
|
||||
import type { Page } from '@playwright/test';
|
||||
|
||||
import { createFakeVisitor } from '../../mocks/data';
|
||||
import { IS_EE } from '../config/constants';
|
||||
import { createAuxContext } from '../fixtures/createAuxContext';
|
||||
import { Users } from '../fixtures/userStates';
|
||||
import { HomeChannel } from '../page-objects';
|
||||
import { OmnichannelLiveChat } from '../page-objects/omnichannel';
|
||||
import { test, expect } from '../utils/test';
|
||||
|
||||
test.describe('omnichannel-transcript', () => {
|
||||
let poLiveChat: OmnichannelLiveChat;
|
||||
let newVisitor: { email: string; name: string };
|
||||
|
||||
let agent: { page: Page; poHomeChannel: HomeChannel };
|
||||
test.beforeAll(async ({ api, browser }) => {
|
||||
newVisitor = createFakeVisitor();
|
||||
|
||||
// Set user user 1 as manager and agent
|
||||
await api.post('/livechat/users/agent', { username: 'user1' });
|
||||
await api.post('/livechat/users/manager', { username: 'user1' });
|
||||
|
||||
const { page } = await createAuxContext(browser, Users.user1);
|
||||
agent = { page, poHomeChannel: new HomeChannel(page) };
|
||||
});
|
||||
test.beforeEach(async ({ page, api }) => {
|
||||
poLiveChat = new OmnichannelLiveChat(page, api);
|
||||
});
|
||||
|
||||
test.afterAll(async ({ api }) => {
|
||||
await api.delete('/livechat/users/agent/user1');
|
||||
await api.delete('/livechat/users/manager/user1');
|
||||
await agent.page.close();
|
||||
});
|
||||
|
||||
test('Receiving a message from visitor', async () => {
|
||||
await test.step('Expect send a message as a visitor', async () => {
|
||||
await poLiveChat.goto();
|
||||
await poLiveChat.openLiveChat();
|
||||
await poLiveChat.sendMessage(newVisitor, false);
|
||||
await poLiveChat.onlineAgentMessage.type('this_a_test_message_from_visitor');
|
||||
await poLiveChat.btnSendMessageToOnlineAgent.click();
|
||||
});
|
||||
|
||||
await test.step('Expect to have 1 omnichannel assigned to agent 1', async () => {
|
||||
await agent.poHomeChannel.navbar.openChat(newVisitor.name);
|
||||
});
|
||||
|
||||
await test.step('Expect to be able to send transcript to email', async () => {
|
||||
await agent.poHomeChannel.content.btnSendTranscript.click();
|
||||
await agent.poHomeChannel.content.btnSendTranscriptToEmail.click();
|
||||
await agent.poHomeChannel.content.btnModalConfirm.click();
|
||||
await agent.poHomeChannel.toastMessage.waitForDisplay();
|
||||
});
|
||||
|
||||
await test.step('Expect to be not able send transcript as PDF', async () => {
|
||||
test.skip(!IS_EE, 'Enterprise Only');
|
||||
await agent.poHomeChannel.content.btnSendTranscript.click();
|
||||
await agent.poHomeChannel.content.btnSendTranscriptAsPDF.hover();
|
||||
await expect(agent.poHomeChannel.content.btnSendTranscriptAsPDF).toHaveAttribute('aria-disabled', 'true');
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,148 @@
|
||||
import {
|
||||
OmnichannelSortingMechanismSettingType,
|
||||
type IOmnichannelServiceLevelAgreements,
|
||||
type Serialized,
|
||||
} from '@rocket.chat/core-typings';
|
||||
|
||||
import { createFakeVisitor } from '../../mocks/data';
|
||||
import { IS_EE } from '../config/constants';
|
||||
import { Users } from '../fixtures/userStates';
|
||||
import { HomeOmnichannel } from '../page-objects';
|
||||
import { createConversation } from '../utils/omnichannel/rooms';
|
||||
import { createSLA } from '../utils/omnichannel/sla';
|
||||
import { test, expect } from '../utils/test';
|
||||
|
||||
const visitorA = createFakeVisitor();
|
||||
const visitorB = createFakeVisitor();
|
||||
const visitorC = createFakeVisitor();
|
||||
|
||||
test.skip(!IS_EE, 'Omnichannel SLAs > Enterprise Only');
|
||||
|
||||
test.use({ storageState: Users.user1.state });
|
||||
|
||||
test.describe('OC - SLA Policies [Sidebar]', () => {
|
||||
let poHomeChannel: HomeOmnichannel;
|
||||
let conversations: Awaited<ReturnType<typeof createConversation>>[] = [];
|
||||
let slas: Serialized<Omit<IOmnichannelServiceLevelAgreements, '_updatedAt'>>[] = [];
|
||||
|
||||
test.beforeAll('create SLAs', async ({ api }) => {
|
||||
slas = await Promise.all([
|
||||
createSLA(api, { name: 'Very Urgent', dueTimeInMinutes: 1 }),
|
||||
createSLA(api, { name: 'Urgent', dueTimeInMinutes: 10 }),
|
||||
createSLA(api, { name: 'Not Urgent', dueTimeInMinutes: 30 }),
|
||||
]);
|
||||
});
|
||||
|
||||
test.beforeAll(async ({ api }) => {
|
||||
(
|
||||
await Promise.all([
|
||||
// Create agent and manager
|
||||
api.post('/livechat/users/agent', { username: 'user1' }),
|
||||
api.post('/livechat/users/manager', { username: 'user1' }),
|
||||
// Settings
|
||||
api.post('/settings/Livechat_Routing_Method', { value: 'Manual_Selection' }),
|
||||
api.post('/settings/Omnichannel_sorting_mechanism', { value: OmnichannelSortingMechanismSettingType.SLAs }),
|
||||
])
|
||||
).every((res) => expect(res.status()).toBe(200));
|
||||
});
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
poHomeChannel = new HomeOmnichannel(page);
|
||||
});
|
||||
|
||||
test.beforeEach(async () => {
|
||||
await poHomeChannel.goto();
|
||||
});
|
||||
|
||||
test.beforeEach(async ({ api }) => {
|
||||
conversations = await Promise.all([
|
||||
createConversation(api, { visitorName: visitorA.name, agentId: 'user1' }),
|
||||
createConversation(api, { visitorName: visitorB.name, agentId: 'user1' }),
|
||||
createConversation(api, { visitorName: visitorC.name, agentId: 'user1' }),
|
||||
]);
|
||||
});
|
||||
|
||||
test.afterAll('delete SLAs', async ({ api }) => {
|
||||
const responses = await Promise.all(slas.map((sla) => api.delete(`/livechat/sla/${sla._id}`)));
|
||||
responses.every((res) => expect(res.status()).toBe(200));
|
||||
});
|
||||
|
||||
test.afterAll(async ({ api }) => {
|
||||
// Delete conversations
|
||||
await Promise.all(conversations.map((conversation) => conversation.delete()));
|
||||
|
||||
(
|
||||
await Promise.all([
|
||||
// Delete agent and manager
|
||||
api.delete('/livechat/users/agent/user1'),
|
||||
api.delete('/livechat/users/manager/user1'),
|
||||
// Reset settings
|
||||
api.post('/settings/Livechat_Routing_Method', { value: 'Auto_Selection' }),
|
||||
api.post('/settings/Omnichannel_sorting_mechanism', { value: OmnichannelSortingMechanismSettingType.Timestamp }),
|
||||
])
|
||||
).every((res) => expect(res.status()).toBe(200));
|
||||
});
|
||||
|
||||
test('OC - SLA Policies [Sidebar] - Update conversation SLA Policy', async () => {
|
||||
await test.step('expect to change room SLA policy to "Not urgent"', async () => {
|
||||
await test.step('expect to open room and room info to be visible', async () => {
|
||||
await poHomeChannel.sidebar.getSidebarItemByName(visitorA.name).click();
|
||||
await expect(poHomeChannel.roomInfo.root).toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('expect to update room SLA policy', async () => {
|
||||
await expect(poHomeChannel.roomInfo.getInfoByLabel('SLA Policy')).not.toBeVisible();
|
||||
await poHomeChannel.roomInfo.btnEdit.click();
|
||||
await poHomeChannel.editRoomInfo.selectSLA('Not Urgent');
|
||||
await poHomeChannel.editRoomInfo.btnSave.click();
|
||||
});
|
||||
|
||||
await test.step('expect SLA to have been updated in the room info and queue order to be correct', async () => {
|
||||
await expect(poHomeChannel.roomInfo.getInfoByLabel('SLA Policy')).toHaveText('Not Urgent');
|
||||
await expect(poHomeChannel.sidebar.getSidebarListItem(visitorA.name)).toBeVisible();
|
||||
await expect(poHomeChannel.sidebar.getSidebarListItem(visitorA.name)).toHaveAttribute('data-index', '1');
|
||||
});
|
||||
});
|
||||
|
||||
await test.step('expect to change room SLA policy to "Urgent"', async () => {
|
||||
await test.step('expect to open room and room info to be visible', async () => {
|
||||
await poHomeChannel.sidebar.getSidebarItemByName(visitorB.name).click();
|
||||
await expect(poHomeChannel.roomInfo.root).toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('expect to update room SLA policy', async () => {
|
||||
await expect(poHomeChannel.roomInfo.getInfoByLabel('SLA Policy')).not.toBeVisible();
|
||||
await poHomeChannel.roomInfo.btnEdit.click();
|
||||
await poHomeChannel.editRoomInfo.selectSLA('Urgent');
|
||||
await poHomeChannel.editRoomInfo.btnSave.click();
|
||||
});
|
||||
|
||||
await test.step('expect SLA to have been updated in the room info and queue order to be correct', async () => {
|
||||
await expect(poHomeChannel.roomInfo.getInfoByLabel('SLA Policy')).toHaveText('Urgent');
|
||||
await expect(poHomeChannel.sidebar.getSidebarListItem(visitorB.name)).toHaveAttribute('data-index', '1');
|
||||
await expect(poHomeChannel.sidebar.getSidebarListItem(visitorA.name)).toHaveAttribute('data-index', '2');
|
||||
});
|
||||
});
|
||||
|
||||
await test.step('expect to change room SLA policy to "Very Urgent"', async () => {
|
||||
await test.step('expect to open room and room info to be visible', async () => {
|
||||
await poHomeChannel.sidebar.getSidebarItemByName(visitorC.name).click();
|
||||
await expect(poHomeChannel.roomInfo.root).toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('expect to update room SLA policy', async () => {
|
||||
await expect(poHomeChannel.roomInfo.getInfoByLabel('SLA Policy')).not.toBeVisible();
|
||||
await poHomeChannel.roomInfo.btnEdit.click();
|
||||
await poHomeChannel.editRoomInfo.selectSLA('Very Urgent');
|
||||
await poHomeChannel.editRoomInfo.btnSave.click();
|
||||
});
|
||||
|
||||
await test.step('expect SLA to have been updated in the room info and queue order to be correct', async () => {
|
||||
await expect(poHomeChannel.roomInfo.getInfoByLabel('SLA Policy')).toHaveText('Very Urgent');
|
||||
await expect(poHomeChannel.sidebar.getSidebarListItem(visitorC.name)).toHaveAttribute('data-index', '1');
|
||||
await expect(poHomeChannel.sidebar.getSidebarListItem(visitorB.name)).toHaveAttribute('data-index', '2');
|
||||
await expect(poHomeChannel.sidebar.getSidebarListItem(visitorA.name)).toHaveAttribute('data-index', '3');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,135 @@
|
||||
import { faker } from '@faker-js/faker';
|
||||
|
||||
import { IS_EE } from '../config/constants';
|
||||
import { Users } from '../fixtures/userStates';
|
||||
import { OmnichannelSlaPolicies } from '../page-objects/omnichannel';
|
||||
import { test, expect } from '../utils/test';
|
||||
|
||||
const ERROR = {
|
||||
nameRequired: 'Name required',
|
||||
estimatedWaitTimeRequired: 'Estimated wait time (time in minutes) required',
|
||||
};
|
||||
|
||||
const INITIAL_SLA = {
|
||||
name: faker.person.firstName(),
|
||||
description: faker.lorem.sentence(),
|
||||
estimatedWaitTime: faker.string.numeric({ length: 1, exclude: '0' }),
|
||||
};
|
||||
|
||||
const EDITED_SLA = {
|
||||
name: faker.person.firstName(),
|
||||
description: faker.lorem.sentence(),
|
||||
estimatedWaitTime: faker.string.numeric({ length: 1, exclude: '0' }),
|
||||
};
|
||||
|
||||
test.skip(!IS_EE, 'Omnichannel SLA Policies > Enterprise Only');
|
||||
|
||||
test.use({ storageState: Users.user1.state });
|
||||
|
||||
test.describe('Omnichannel SLA Policies', () => {
|
||||
let poOmnichannelSlaPolicies: OmnichannelSlaPolicies;
|
||||
|
||||
test.beforeAll(async ({ api }) => {
|
||||
await api.post('/livechat/users/agent', { username: 'user1' });
|
||||
await api.post('/livechat/users/manager', { username: 'user1' });
|
||||
});
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
poOmnichannelSlaPolicies = new OmnichannelSlaPolicies(page);
|
||||
await poOmnichannelSlaPolicies.goto();
|
||||
});
|
||||
|
||||
test.afterAll(async ({ api }) => {
|
||||
await api.delete('/livechat/users/agent/user1');
|
||||
await api.delete('/livechat/users/manager/user1');
|
||||
});
|
||||
|
||||
test('Manage SLAs', async () => {
|
||||
await test.step('Add new SLA', async () => {
|
||||
await poOmnichannelSlaPolicies.createNew();
|
||||
|
||||
await test.step('should not submit form with empty required fields: name and estimated wait time', async () => {
|
||||
await poOmnichannelSlaPolicies.manageSlaPolicy.btnSave.click();
|
||||
await expect(poOmnichannelSlaPolicies.manageSlaPolicy.errorMessage(ERROR.nameRequired)).toBeVisible();
|
||||
await expect(poOmnichannelSlaPolicies.manageSlaPolicy.errorMessage(ERROR.estimatedWaitTimeRequired)).toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('input a valid name', async () => {
|
||||
await poOmnichannelSlaPolicies.manageSlaPolicy.inputName.fill(INITIAL_SLA.name);
|
||||
await expect(poOmnichannelSlaPolicies.manageSlaPolicy.errorMessage(ERROR.nameRequired)).not.toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('input a valid description', async () => {
|
||||
await poOmnichannelSlaPolicies.manageSlaPolicy.inputDescription.fill(INITIAL_SLA.description);
|
||||
});
|
||||
|
||||
await test.step('only allow numbers on estimated wait time field', async () => {
|
||||
await poOmnichannelSlaPolicies.manageSlaPolicy.inputEstimatedWaitTime.pressSequentially('a');
|
||||
await expect(poOmnichannelSlaPolicies.manageSlaPolicy.inputEstimatedWaitTime).toHaveValue('0');
|
||||
});
|
||||
|
||||
await test.step('not allow 0 on estimated wait time field', async () => {
|
||||
await poOmnichannelSlaPolicies.manageSlaPolicy.inputEstimatedWaitTime.fill('0');
|
||||
await expect(poOmnichannelSlaPolicies.manageSlaPolicy.errorMessage(ERROR.estimatedWaitTimeRequired)).toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('input a valid estimated wait time', async () => {
|
||||
await poOmnichannelSlaPolicies.manageSlaPolicy.inputEstimatedWaitTime.fill(INITIAL_SLA.estimatedWaitTime);
|
||||
await expect(poOmnichannelSlaPolicies.manageSlaPolicy.errorMessage(ERROR.estimatedWaitTimeRequired)).not.toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('save sla', async () => {
|
||||
await expect(poOmnichannelSlaPolicies.manageSlaPolicy.btnSave).toBeEnabled();
|
||||
await poOmnichannelSlaPolicies.manageSlaPolicy.btnSave.click();
|
||||
|
||||
await expect(poOmnichannelSlaPolicies.manageSlaPolicy.inputName).not.toBeVisible();
|
||||
await expect(poOmnichannelSlaPolicies.table.findRowByName(INITIAL_SLA.name)).toBeVisible();
|
||||
});
|
||||
});
|
||||
|
||||
await test.step('Search SLA', async () => {
|
||||
await poOmnichannelSlaPolicies.inputSearch.fill('random_text_that_should_have_no_match');
|
||||
await expect(poOmnichannelSlaPolicies.table.findRowByName(INITIAL_SLA.name)).not.toBeVisible();
|
||||
await expect(poOmnichannelSlaPolicies.emptyState).toBeVisible();
|
||||
await poOmnichannelSlaPolicies.inputSearch.fill(INITIAL_SLA.name);
|
||||
await expect(poOmnichannelSlaPolicies.table.findRowByName(INITIAL_SLA.name)).toBeVisible();
|
||||
await expect(poOmnichannelSlaPolicies.emptyState).not.toBeVisible();
|
||||
await poOmnichannelSlaPolicies.inputSearch.fill('');
|
||||
});
|
||||
|
||||
await test.step('Edit SLA', async () => {
|
||||
await poOmnichannelSlaPolicies.table.findRowByName(INITIAL_SLA.name).click();
|
||||
|
||||
await expect(poOmnichannelSlaPolicies.manageSlaPolicy.inputName).toHaveValue(INITIAL_SLA.name);
|
||||
await expect(poOmnichannelSlaPolicies.manageSlaPolicy.inputDescription).toHaveValue(INITIAL_SLA.description);
|
||||
await expect(poOmnichannelSlaPolicies.manageSlaPolicy.inputEstimatedWaitTime).toHaveValue(INITIAL_SLA.estimatedWaitTime);
|
||||
|
||||
await test.step('edit name', async () => {
|
||||
await poOmnichannelSlaPolicies.manageSlaPolicy.inputName.fill(EDITED_SLA.name);
|
||||
await expect(poOmnichannelSlaPolicies.manageSlaPolicy.errorMessage(ERROR.nameRequired)).not.toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('edit description', async () => {
|
||||
await poOmnichannelSlaPolicies.manageSlaPolicy.inputDescription.fill(EDITED_SLA.description);
|
||||
});
|
||||
|
||||
await test.step('edit estimated wait time', async () => {
|
||||
await poOmnichannelSlaPolicies.manageSlaPolicy.inputEstimatedWaitTime.fill(EDITED_SLA.estimatedWaitTime);
|
||||
await expect(poOmnichannelSlaPolicies.manageSlaPolicy.errorMessage(ERROR.estimatedWaitTimeRequired)).not.toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('save sla', async () => {
|
||||
await expect(poOmnichannelSlaPolicies.manageSlaPolicy.btnSave).toBeEnabled();
|
||||
await poOmnichannelSlaPolicies.manageSlaPolicy.btnSave.click();
|
||||
|
||||
await expect(poOmnichannelSlaPolicies.manageSlaPolicy.inputName).not.toBeVisible();
|
||||
await expect(poOmnichannelSlaPolicies.table.findRowByName(EDITED_SLA.name)).toBeVisible();
|
||||
});
|
||||
});
|
||||
|
||||
await test.step('Remove SLA', async () => {
|
||||
await poOmnichannelSlaPolicies.removeSLA(EDITED_SLA.name);
|
||||
await expect(poOmnichannelSlaPolicies.table.findRowByName(EDITED_SLA.name)).not.toBeVisible();
|
||||
});
|
||||
});
|
||||
});
|
||||
131
apps/meteor/tests/e2e/omnichannel/omnichannel-tags.spec.ts
Normal file
131
apps/meteor/tests/e2e/omnichannel/omnichannel-tags.spec.ts
Normal file
@@ -0,0 +1,131 @@
|
||||
import { faker } from '@faker-js/faker';
|
||||
import type { Page } from '@playwright/test';
|
||||
|
||||
import { IS_EE } from '../config/constants';
|
||||
import { Users } from '../fixtures/userStates';
|
||||
import { OmnichannelTags } from '../page-objects/omnichannel';
|
||||
import { setSettingValueById } from '../utils';
|
||||
import { createAgent } from '../utils/omnichannel/agents';
|
||||
import { createDepartment } from '../utils/omnichannel/departments';
|
||||
import { createTag } from '../utils/omnichannel/tags';
|
||||
import { test, expect } from '../utils/test';
|
||||
|
||||
test.use({ storageState: Users.admin.state });
|
||||
|
||||
test.describe('OC - Manage Tags', () => {
|
||||
test.skip(!IS_EE, 'OC - Manage Tags > Enterprise Edition Only');
|
||||
|
||||
let poOmnichannelTags: OmnichannelTags;
|
||||
|
||||
let department: Awaited<ReturnType<typeof createDepartment>>;
|
||||
let department2: Awaited<ReturnType<typeof createDepartment>>;
|
||||
let agent: Awaited<ReturnType<typeof createAgent>>;
|
||||
|
||||
test.beforeAll(async ({ api }) => {
|
||||
department = await createDepartment(api);
|
||||
department2 = await createDepartment(api);
|
||||
});
|
||||
|
||||
test.beforeAll(async ({ api }) => {
|
||||
agent = await createAgent(api, 'user2');
|
||||
});
|
||||
|
||||
test.beforeAll(async ({ api }) => {
|
||||
await setSettingValueById(api, 'Omnichannel_enable_department_removal', true);
|
||||
});
|
||||
|
||||
test.afterAll(async ({ api }) => {
|
||||
await department.delete();
|
||||
await department2.delete();
|
||||
await agent.delete();
|
||||
await setSettingValueById(api, 'Omnichannel_enable_department_removal', false);
|
||||
});
|
||||
|
||||
test.beforeEach(async ({ page }: { page: Page }) => {
|
||||
poOmnichannelTags = new OmnichannelTags(page);
|
||||
});
|
||||
|
||||
test('OC - Manage Tags - Create Tag', async () => {
|
||||
const tagName = faker.string.uuid();
|
||||
|
||||
await poOmnichannelTags.goto();
|
||||
|
||||
await test.step('expect correct form default state', async () => {
|
||||
await poOmnichannelTags.createNew();
|
||||
await expect(poOmnichannelTags.editTag.root).toBeVisible();
|
||||
await expect(poOmnichannelTags.editTag.btnSave).toBeEnabled();
|
||||
await expect(poOmnichannelTags.editTag.btnCancel).toBeEnabled();
|
||||
await poOmnichannelTags.editTag.btnCancel.click();
|
||||
await expect(poOmnichannelTags.editTag.root).not.toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('expect to create new tag', async () => {
|
||||
await poOmnichannelTags.createNew();
|
||||
await poOmnichannelTags.editTag.inputName.fill(tagName);
|
||||
await poOmnichannelTags.editTag.selectDepartment(department.data.name);
|
||||
await poOmnichannelTags.editTag.btnSave.click();
|
||||
await expect(poOmnichannelTags.editTag.root).not.toBeVisible();
|
||||
|
||||
await test.step('expect tag to have been created', async () => {
|
||||
await poOmnichannelTags.search(tagName);
|
||||
await expect(poOmnichannelTags.table.findRowByName(tagName)).toBeVisible();
|
||||
});
|
||||
});
|
||||
|
||||
await test.step('should be able to delete tag', async () => {
|
||||
await poOmnichannelTags.deleteTag(tagName);
|
||||
await poOmnichannelTags.waitForEmptyState();
|
||||
});
|
||||
});
|
||||
|
||||
test('OC - Manage Tags - Edit tag departments', async ({ api, page }) => {
|
||||
const tag = await test.step('expect to create new tag', async () => {
|
||||
const { data: tag } = await createTag(api, {
|
||||
name: faker.string.uuid(),
|
||||
departments: [department.data._id],
|
||||
});
|
||||
|
||||
return tag;
|
||||
});
|
||||
|
||||
await poOmnichannelTags.goto();
|
||||
|
||||
await test.step('expect to add tag departments', async () => {
|
||||
await poOmnichannelTags.search(tag.name);
|
||||
await poOmnichannelTags.table.findRowByName(tag.name).click();
|
||||
await expect(poOmnichannelTags.editTag.root).toBeVisible();
|
||||
await poOmnichannelTags.editTag.selectDepartment(department2.data.name);
|
||||
await expect(poOmnichannelTags.editTag.findSelectedDepartment(department2.data.name)).toBeVisible();
|
||||
await poOmnichannelTags.editTag.save();
|
||||
});
|
||||
|
||||
await test.step('expect department to be in the chosen departments list', async () => {
|
||||
await poOmnichannelTags.search(tag.name);
|
||||
await poOmnichannelTags.table.findRowByName(tag.name).click();
|
||||
await expect(poOmnichannelTags.editTag.root).toBeVisible();
|
||||
await expect(poOmnichannelTags.editTag.inputDepartments).toBeVisible();
|
||||
await poOmnichannelTags.editTag.close();
|
||||
});
|
||||
|
||||
await test.step('expect to remove tag departments', async () => {
|
||||
await poOmnichannelTags.search(tag.name);
|
||||
await poOmnichannelTags.table.findRowByName(tag.name).click();
|
||||
await expect(poOmnichannelTags.editTag.root).toBeVisible();
|
||||
await poOmnichannelTags.editTag.selectDepartment(department2.data.name);
|
||||
await expect(poOmnichannelTags.editTag.findSelectedDepartment(department2.data.name)).not.toBeVisible();
|
||||
await poOmnichannelTags.editTag.save();
|
||||
});
|
||||
|
||||
await test.step('expect department to not be in the chosen departments list', async () => {
|
||||
await poOmnichannelTags.search(tag.name);
|
||||
await poOmnichannelTags.table.findRowByName(tag.name).click();
|
||||
await expect(poOmnichannelTags.editTag.root).toBeVisible();
|
||||
await expect(page.getByRole('option', { name: department2.data.name })).toBeHidden();
|
||||
});
|
||||
|
||||
await test.step('expect to delete tag', async () => {
|
||||
await poOmnichannelTags.deleteTag(tag.name);
|
||||
await poOmnichannelTags.waitForEmptyState();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,99 @@
|
||||
import type { Page } from '@playwright/test';
|
||||
|
||||
import { createFakeVisitor } from '../../mocks/data';
|
||||
import { createAuxContext } from '../fixtures/createAuxContext';
|
||||
import { Users } from '../fixtures/userStates';
|
||||
import { HomeOmnichannel } from '../page-objects';
|
||||
import { OmnichannelLiveChat } from '../page-objects/omnichannel';
|
||||
import { expectPollUserStatus } from '../utils/expectPollUserStatus';
|
||||
import { test, expect } from '../utils/test';
|
||||
|
||||
test.describe('omnichannel-takeChat', () => {
|
||||
let poLiveChat: OmnichannelLiveChat;
|
||||
let newVisitor: { email: string; name: string };
|
||||
|
||||
let agent: { page: Page; poHomeChannel: HomeOmnichannel };
|
||||
|
||||
const sendLivechatMessage = async () => {
|
||||
await poLiveChat.openLiveChat();
|
||||
await poLiveChat.sendMessage(newVisitor, false);
|
||||
await poLiveChat.onlineAgentMessage.fill('this_a_test_message_from_user');
|
||||
await poLiveChat.btnSendMessageToOnlineAgent.click();
|
||||
};
|
||||
|
||||
test.beforeAll(async ({ api, browser }) => {
|
||||
await Promise.all([
|
||||
await api.post('/livechat/users/agent', { username: 'user1' }).then((res) => expect(res.status()).toBe(200)),
|
||||
await api.post('/settings/Livechat_Routing_Method', { value: 'Manual_Selection' }).then((res) => expect(res.status()).toBe(200)),
|
||||
await api.post('/settings/Livechat_enabled_when_agent_idle', { value: false }).then((res) => expect(res.status()).toBe(200)),
|
||||
]);
|
||||
|
||||
const { page } = await createAuxContext(browser, Users.user1);
|
||||
agent = { page, poHomeChannel: new HomeOmnichannel(page) };
|
||||
});
|
||||
|
||||
test.afterAll(async ({ api }) => {
|
||||
await agent.poHomeChannel.navbar.switchOmnichannelStatus('online');
|
||||
await agent.poHomeChannel.navbar.changeUserStatus('online');
|
||||
|
||||
await agent.page.close();
|
||||
await Promise.all([
|
||||
await api.delete('/livechat/users/agent/user1'),
|
||||
await api.post('/settings/Livechat_Routing_Method', { value: 'Auto_Selection' }),
|
||||
await api.post('/settings/Livechat_enabled_when_agent_idle', { value: true }),
|
||||
]);
|
||||
});
|
||||
|
||||
test.beforeEach('start a new livechat chat', async ({ page, api }) => {
|
||||
await agent.poHomeChannel.navbar.changeUserStatus('online');
|
||||
await expectPollUserStatus(api, 'user1', 'online');
|
||||
|
||||
newVisitor = createFakeVisitor();
|
||||
|
||||
poLiveChat = new OmnichannelLiveChat(page, api);
|
||||
|
||||
await poLiveChat.goto();
|
||||
});
|
||||
|
||||
test('When agent is online should take the chat', async () => {
|
||||
await sendLivechatMessage();
|
||||
|
||||
await agent.poHomeChannel.sidebar.getSidebarItemByName(newVisitor.name).click();
|
||||
|
||||
await expect(agent.poHomeChannel.content.btnTakeChat).toBeVisible();
|
||||
|
||||
await agent.poHomeChannel.content.btnTakeChat.click();
|
||||
await agent.poHomeChannel.navbar.openChat(newVisitor.name);
|
||||
|
||||
await expect(agent.poHomeChannel.content.btnTakeChat).not.toBeVisible();
|
||||
await expect(agent.poHomeChannel.composer.inputMessage).toBeVisible();
|
||||
});
|
||||
|
||||
test('When agent is offline should not take the chat', async ({ api }) => {
|
||||
await agent.poHomeChannel.navbar.changeUserStatus('offline');
|
||||
await expectPollUserStatus(api, 'user1', 'offline');
|
||||
|
||||
await sendLivechatMessage();
|
||||
|
||||
await expect(poLiveChat.alertMessage('Error starting a new conversation: Sorry, no online agents [no-agent-online]')).toBeVisible();
|
||||
});
|
||||
|
||||
test('When a new livechat conversation is selected and the agent becomes offline or unavailable, they should not be able to take the chat', async ({
|
||||
api,
|
||||
}) => {
|
||||
await sendLivechatMessage();
|
||||
|
||||
await agent.poHomeChannel.sidebar.getSidebarItemByName(newVisitor.name).click();
|
||||
|
||||
await agent.poHomeChannel.navbar.changeUserStatus('offline');
|
||||
await expectPollUserStatus(api, 'user1', 'offline');
|
||||
|
||||
await expect(agent.poHomeChannel.content.btnTakeChat).toBeDisabled();
|
||||
|
||||
await agent.poHomeChannel.navbar.changeUserStatus('online');
|
||||
await expectPollUserStatus(api, 'user1', 'online');
|
||||
await agent.poHomeChannel.navbar.switchOmnichannelStatus('offline');
|
||||
|
||||
await expect(agent.poHomeChannel.content.btnTakeChat).toBeDisabled();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,98 @@
|
||||
import type { Page } from '@playwright/test';
|
||||
|
||||
import { createAuxContext } from '../fixtures/createAuxContext';
|
||||
import { Users } from '../fixtures/userStates';
|
||||
import { HomeOmnichannel } from '../page-objects';
|
||||
import { createAgent } from '../utils/omnichannel/agents';
|
||||
import { createManager } from '../utils/omnichannel/managers';
|
||||
import { createConversation } from '../utils/omnichannel/rooms';
|
||||
import { test, expect } from '../utils/test';
|
||||
|
||||
test.describe('OC - Chat transfers [Agent role]', () => {
|
||||
let sessions: { page: Page; poHomeOmnichannel: HomeOmnichannel }[];
|
||||
let agents: Awaited<ReturnType<typeof createAgent>>[];
|
||||
let managers: Awaited<ReturnType<typeof createManager>>[];
|
||||
let conversations: Awaited<ReturnType<typeof createConversation>>[];
|
||||
|
||||
// Create agents and managers
|
||||
test.beforeAll(async ({ api }) => {
|
||||
agents = await Promise.all([createAgent(api, 'user1'), createAgent(api, 'user2')]);
|
||||
|
||||
managers = await Promise.all([createManager(api, 'user1')]);
|
||||
});
|
||||
|
||||
// Livechat when agent idle
|
||||
test.beforeAll(async ({ api }) => {
|
||||
await api.post('/settings/Livechat_enabled_when_agent_idle', { value: false }).then((res) => expect(res.status()).toBe(200));
|
||||
});
|
||||
|
||||
// Create agent sessions
|
||||
test.beforeAll(async ({ browser }) => {
|
||||
sessions = await Promise.all([
|
||||
createAuxContext(browser, Users.user1).then(({ page }) => ({ page, poHomeOmnichannel: new HomeOmnichannel(page) })),
|
||||
createAuxContext(browser, Users.user2).then(({ page }) => ({ page, poHomeOmnichannel: new HomeOmnichannel(page) })),
|
||||
]);
|
||||
});
|
||||
|
||||
// Delete all data
|
||||
test.afterAll(async ({ api }) => {
|
||||
await Promise.all([
|
||||
...conversations.map((conversation) => conversation.delete()),
|
||||
...agents.map((agent) => agent.delete()),
|
||||
...managers.map((manager) => manager.delete()),
|
||||
api.post('/settings/Livechat_enabled_when_agent_idle', { value: true }).then((res) => expect(res.status()).toBe(200)),
|
||||
]);
|
||||
});
|
||||
|
||||
// Make "user-1" online & "user-2" offline so that chat can be automatically routed to "user-1"
|
||||
test.beforeAll(async () => {
|
||||
const [agentA, agentB] = sessions;
|
||||
await agentA.poHomeOmnichannel.navbar.changeUserStatus('online');
|
||||
await agentB.poHomeOmnichannel.navbar.changeUserStatus('offline');
|
||||
});
|
||||
|
||||
// Close sessions
|
||||
test.afterAll(async () => {
|
||||
await Promise.all(sessions.map(({ page }) => page.close()));
|
||||
});
|
||||
|
||||
// Start a new chat for each test
|
||||
test.beforeAll(async ({ api }) => {
|
||||
conversations = [await createConversation(api)];
|
||||
});
|
||||
|
||||
test('OC - Chat transfers [Agent role] - Transfer omnichannel chat to another agent', async () => {
|
||||
const [agentA, agentB] = sessions;
|
||||
const [{ visitor }] = conversations.map(({ data }) => data);
|
||||
|
||||
await test.step('expect to have 1 omnichannel assigned to agent 1', async () => {
|
||||
await agentA.poHomeOmnichannel.sidebar.getSidebarItemByName(visitor.name).click();
|
||||
});
|
||||
|
||||
await test.step('expect to not be able to transfer chat to "user-2" when that user is offline', async () => {
|
||||
await agentB.poHomeOmnichannel.navbar.changeUserStatus('offline');
|
||||
|
||||
await agentA.poHomeOmnichannel.quickActionsRoomToolbar.forwardChat();
|
||||
await agentA.poHomeOmnichannel.content.forwardChatModal.inputForwardUser.click();
|
||||
await agentA.poHomeOmnichannel.content.forwardChatModal.inputForwardUser.type('user2');
|
||||
await expect(agentA.page.locator('text=Empty')).toBeVisible();
|
||||
|
||||
await agentA.poHomeOmnichannel.goto();
|
||||
});
|
||||
|
||||
await test.step('expect to be able to transfer an omnichannel to conversation to agent 2 as agent 1 when agent 2 is online', async () => {
|
||||
await agentB.poHomeOmnichannel.navbar.changeUserStatus('online');
|
||||
|
||||
await agentA.poHomeOmnichannel.sidebar.getSidebarItemByName(visitor.name).click();
|
||||
await agentA.poHomeOmnichannel.quickActionsRoomToolbar.forwardChat();
|
||||
await agentA.poHomeOmnichannel.content.forwardChatModal.selectUser('user2');
|
||||
await agentA.poHomeOmnichannel.content.forwardChatModal.inputComment.type('any_comment');
|
||||
await agentA.poHomeOmnichannel.content.forwardChatModal.btnForward.click();
|
||||
await agentA.poHomeOmnichannel.toastMessage.waitForDisplay();
|
||||
});
|
||||
|
||||
await test.step('expect to have 1 omnichannel assigned to agent 2', async () => {
|
||||
await agentB.poHomeOmnichannel.sidebar.getSidebarItemByName(visitor.name).click();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,133 @@
|
||||
import { faker } from '@faker-js/faker';
|
||||
import type { Page } from '@playwright/test';
|
||||
|
||||
import { createFakeVisitor } from '../../mocks/data';
|
||||
import { createAuxContext } from '../fixtures/createAuxContext';
|
||||
import { Users } from '../fixtures/userStates';
|
||||
import { HomeOmnichannel } from '../page-objects';
|
||||
import { OmnichannelLiveChat } from '../page-objects/omnichannel';
|
||||
import { test, expect } from '../utils/test';
|
||||
|
||||
test.describe('OC - Livechat New Chat Triggers - After Registration', () => {
|
||||
let triggersName: string;
|
||||
let triggerMessage: string;
|
||||
let poLiveChat: OmnichannelLiveChat;
|
||||
let newVisitor: { email: string; name: string };
|
||||
let agent: { page: Page; poHomeOmnichannel: HomeOmnichannel };
|
||||
|
||||
test.beforeEach(async ({ api, browser, page }) => {
|
||||
newVisitor = createFakeVisitor();
|
||||
triggersName = faker.string.uuid();
|
||||
triggerMessage = 'This is a trigger message after guest registration';
|
||||
|
||||
await api.post('/livechat/triggers', {
|
||||
name: triggersName,
|
||||
description: 'Creating a fresh trigger',
|
||||
enabled: true,
|
||||
runOnce: false,
|
||||
conditions: [
|
||||
{
|
||||
name: 'after-guest-registration',
|
||||
value: '',
|
||||
},
|
||||
],
|
||||
actions: [
|
||||
{
|
||||
name: 'send-message',
|
||||
params: {
|
||||
name: '',
|
||||
msg: triggerMessage,
|
||||
sender: 'queue',
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
await Promise.all([
|
||||
api.post('/livechat/users/agent', { username: 'user1' }),
|
||||
api.post('/livechat/users/manager', { username: 'user1' }),
|
||||
]);
|
||||
|
||||
const { page: agentPage } = await createAuxContext(browser, Users.user1);
|
||||
agent = { page: agentPage, poHomeOmnichannel: new HomeOmnichannel(agentPage) };
|
||||
|
||||
poLiveChat = new OmnichannelLiveChat(page, api);
|
||||
});
|
||||
|
||||
test.afterEach(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}`)));
|
||||
|
||||
await Promise.all([api.delete('/livechat/users/agent/user1'), api.delete('/livechat/users/manager/user1')]);
|
||||
|
||||
await agent.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 () => {
|
||||
test('expect trigger message after registration', async () => {
|
||||
await poLiveChat.goto();
|
||||
await poLiveChat.sendMessageAndCloseChat(newVisitor);
|
||||
|
||||
await poLiveChat.startNewChat();
|
||||
await expect(poLiveChat.txtChatMessage(triggerMessage)).toBeVisible();
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('OC - Livechat Triggers - After Registration - Reload', async () => {
|
||||
test('expect trigger message after registration', async () => {
|
||||
await test.step('expect trigger message after registration to be visible', async () => {
|
||||
await poLiveChat.goto();
|
||||
await poLiveChat.openAnyLiveChat();
|
||||
await poLiveChat.sendMessage(newVisitor, false);
|
||||
await expect(poLiveChat.txtChatMessage(triggerMessage)).toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('expect trigger message after registration to be visible after reload', async () => {
|
||||
await poLiveChat.page.reload();
|
||||
await poLiveChat.openAnyLiveChat();
|
||||
await expect(poLiveChat.txtChatMessage(triggerMessage)).toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('expect to close room and reload', async () => {
|
||||
await poLiveChat.onlineAgentMessage.type('message_after_trigger');
|
||||
await poLiveChat.btnSendMessageToOnlineAgent.click();
|
||||
await expect(poLiveChat.txtChatMessage('message_after_trigger')).toBeVisible();
|
||||
await poLiveChat.closeChat();
|
||||
|
||||
await expect(poLiveChat.btnNewChat).toBeVisible();
|
||||
await poLiveChat.startNewChat();
|
||||
await poLiveChat.page.reload();
|
||||
});
|
||||
|
||||
await test.step('expect trigger message after registration to be visible after reload on new chat', async () => {
|
||||
await poLiveChat.openAnyLiveChat();
|
||||
await expect(poLiveChat.txtChatMessage(triggerMessage)).toBeVisible();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('OC - Livechat New Chat Triggers - After Registration, clear Local storage', async () => {
|
||||
test.beforeAll(async ({ api }) => {
|
||||
await api.post('/settings/Livechat_clear_local_storage_when_chat_ended', { value: true });
|
||||
});
|
||||
|
||||
test('expect trigger message after registration not be visible after local storage clear', async () => {
|
||||
await poLiveChat.goto();
|
||||
await poLiveChat.sendMessageAndCloseChat(newVisitor);
|
||||
|
||||
await expect(poLiveChat.btnNewChat).toBeVisible();
|
||||
await expect(poLiveChat.txtChatMessage(triggerMessage)).not.toBeVisible();
|
||||
|
||||
await poLiveChat.startNewChat();
|
||||
await poLiveChat.sendMessage(newVisitor, false);
|
||||
await expect(poLiveChat.txtChatMessage(triggerMessage)).toBeVisible();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,98 @@
|
||||
import type { Page } from '@playwright/test';
|
||||
|
||||
import { createFakeVisitor } from '../../mocks/data';
|
||||
import { createAuxContext } from '../fixtures/createAuxContext';
|
||||
import { Users } from '../fixtures/userStates';
|
||||
import { HomeOmnichannel } from '../page-objects';
|
||||
import { OmnichannelLiveChat } from '../page-objects/omnichannel';
|
||||
import { test, expect } from '../utils/test';
|
||||
|
||||
test.use({ storageState: Users.admin.state });
|
||||
test.describe('OC - Livechat Triggers - Open by Visitor', () => {
|
||||
let poLiveChat: OmnichannelLiveChat;
|
||||
let newVisitor: { email: string; name: string };
|
||||
let agent: { page: Page; poHomeOmnichannel: HomeOmnichannel };
|
||||
|
||||
test.beforeAll(async ({ api, browser }) => {
|
||||
newVisitor = createFakeVisitor();
|
||||
|
||||
const requests = await Promise.all([
|
||||
api.post('/livechat/users/agent', { username: 'user1' }),
|
||||
api.post('/livechat/users/manager', { username: 'user1' }),
|
||||
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',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
),
|
||||
]);
|
||||
|
||||
requests.every((e) => expect(e.status()).toBe(200));
|
||||
|
||||
const { page } = await createAuxContext(browser, Users.user1, '/');
|
||||
agent = { page, poHomeOmnichannel: new HomeOmnichannel(page) };
|
||||
});
|
||||
|
||||
test.beforeEach(async ({ page, api }) => {
|
||||
poLiveChat = new OmnichannelLiveChat(page, api);
|
||||
await poLiveChat.goto();
|
||||
});
|
||||
|
||||
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}`)));
|
||||
|
||||
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 agent.page.close();
|
||||
});
|
||||
|
||||
test('OC - Livechat Triggers - after the visitor opens the chat the trigger message should not be visible neither after a page reload', async () => {
|
||||
await poLiveChat.openLiveChat();
|
||||
|
||||
await expect(poLiveChat.txtChatMessage('This is a trigger message open by visitor')).toBeVisible();
|
||||
|
||||
await poLiveChat.btnChatNow.click();
|
||||
await poLiveChat.sendMessage(newVisitor, false);
|
||||
|
||||
await poLiveChat.onlineAgentMessage.type('this_a_test_message_from_visitor');
|
||||
await poLiveChat.btnSendMessageToOnlineAgent.click();
|
||||
|
||||
await expect(poLiveChat.txtChatMessage('this_a_test_message_from_visitor')).toBeVisible();
|
||||
|
||||
await poLiveChat.page.reload();
|
||||
|
||||
// if the request took too long, the loadMessage cleans triggers, but if the fetch is fast enough, the trigger message will be visible
|
||||
await poLiveChat.page.waitForRequest(/livechat\/messages.history/);
|
||||
|
||||
await poLiveChat.openLiveChat();
|
||||
await expect(poLiveChat.txtChatMessage('This is a trigger message open by visitor')).not.toBeVisible();
|
||||
await expect(poLiveChat.txtChatMessage('this_a_test_message_from_visitor')).toBeVisible();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,128 @@
|
||||
import { IS_EE } from '../config/constants';
|
||||
import { createAuxContext } from '../fixtures/createAuxContext';
|
||||
import { Users } from '../fixtures/userStates';
|
||||
import { HomeOmnichannel } from '../page-objects';
|
||||
import { OmnichannelLiveChatEmbedded } from '../page-objects/omnichannel';
|
||||
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.goto();
|
||||
|
||||
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.goto();
|
||||
|
||||
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);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,97 @@
|
||||
import type { Page } from '@playwright/test';
|
||||
|
||||
import { createFakeVisitor } from '../../mocks/data';
|
||||
import { createAuxContext } from '../fixtures/createAuxContext';
|
||||
import { Users } from '../fixtures/userStates';
|
||||
import { HomeOmnichannel } from '../page-objects';
|
||||
import { OmnichannelLiveChat } from '../page-objects/omnichannel';
|
||||
import { test, expect } from '../utils/test';
|
||||
|
||||
test.use({ storageState: Users.admin.state });
|
||||
test.describe('OC - Livechat Triggers - Time on site', () => {
|
||||
let poLiveChat: OmnichannelLiveChat;
|
||||
let newVisitor: { email: string; name: string };
|
||||
let agent: { page: Page; poHomeOmnichannel: HomeOmnichannel };
|
||||
|
||||
test.beforeAll(async ({ api, browser }) => {
|
||||
newVisitor = createFakeVisitor();
|
||||
|
||||
const requests = await Promise.all([
|
||||
api.post('/livechat/users/agent', { username: 'user1' }),
|
||||
api.post('/livechat/users/manager', { username: 'user1' }),
|
||||
api.post(
|
||||
'/livechat/triggers',
|
||||
|
||||
{
|
||||
enabled: true,
|
||||
runOnce: false,
|
||||
conditions: [{ name: 'time-on-site', value: '1' }],
|
||||
actions: [{ name: 'send-message', params: { name: '', msg: 'This is a trigger message time on site', sender: 'queue' } }],
|
||||
name: 'test',
|
||||
description: 'test',
|
||||
},
|
||||
),
|
||||
]);
|
||||
|
||||
requests.every((e) => expect(e.status()).toBe(200));
|
||||
|
||||
const { page } = await createAuxContext(browser, Users.user1, '/');
|
||||
agent = { page, poHomeOmnichannel: new HomeOmnichannel(page) };
|
||||
});
|
||||
|
||||
test.beforeEach(async ({ page, api }) => {
|
||||
poLiveChat = new OmnichannelLiveChat(page, api);
|
||||
await poLiveChat.goto();
|
||||
});
|
||||
|
||||
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}`)));
|
||||
|
||||
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 agent.page.close();
|
||||
});
|
||||
|
||||
test('expect to receive trigger message after 1 second', async () => {
|
||||
await expect(poLiveChat.page.locator('role=button[name="Close"]')).toBeVisible();
|
||||
await expect(poLiveChat.page.locator('role=main')).toContainText('This is a trigger message time on site');
|
||||
await expect(poLiveChat.page.locator('role=button[name="Start chat"]')).toBeVisible();
|
||||
await expect(poLiveChat.page.locator('role=button[name="Messages"]')).toBeVisible();
|
||||
});
|
||||
|
||||
test('OC - Livechat Triggers - after the visitor opens the chat the trigger time-on-site should not be triggered after reload', async () => {
|
||||
await expect(poLiveChat.page.locator('role=button[name="Close"]')).toBeVisible();
|
||||
await expect(poLiveChat.page.locator('role=main')).toContainText('This is a trigger message time on site');
|
||||
await expect(poLiveChat.page.locator('role=button[name="Start chat"]')).toBeVisible();
|
||||
await expect(poLiveChat.page.locator('role=button[name="Messages"]')).toBeVisible();
|
||||
|
||||
await poLiveChat.btnOpenOnlineLiveChat('Start chat').click();
|
||||
await poLiveChat.btnOpenOnlineLiveChat('Chat now').click();
|
||||
|
||||
await poLiveChat.sendMessage(newVisitor, false);
|
||||
|
||||
await test.step('expect to not have any trigger message after registration', async () => {
|
||||
await expect(poLiveChat.txtChatMessage('This is a trigger message time on site')).not.toBeVisible();
|
||||
});
|
||||
|
||||
await poLiveChat.onlineAgentMessage.type('this_a_test_message_from_visitor');
|
||||
await poLiveChat.btnSendMessageToOnlineAgent.click();
|
||||
|
||||
await expect(poLiveChat.page.locator('role=main')).toContainText('Chat started');
|
||||
|
||||
await poLiveChat.page.reload();
|
||||
|
||||
await poLiveChat.btnOpenOnlineLiveChat('Rocket.Chat').click();
|
||||
|
||||
await expect(poLiveChat.page.locator('role=main')).toContainText('Chat started');
|
||||
await poLiveChat.page.waitForTimeout(1000);
|
||||
await expect(poLiveChat.txtChatMessage('This is a trigger message time on site')).not.toBeVisible();
|
||||
});
|
||||
});
|
||||
159
apps/meteor/tests/e2e/omnichannel/omnichannel-triggers.spec.ts
Normal file
159
apps/meteor/tests/e2e/omnichannel/omnichannel-triggers.spec.ts
Normal file
@@ -0,0 +1,159 @@
|
||||
import { faker } from '@faker-js/faker';
|
||||
import type { Page } from '@playwright/test';
|
||||
|
||||
import { createFakeVisitor } from '../../mocks/data';
|
||||
import { createAuxContext } from '../fixtures/createAuxContext';
|
||||
import { Users } from '../fixtures/userStates';
|
||||
import { OmnichannelLiveChat, OmnichannelTriggers } from '../page-objects/omnichannel';
|
||||
import { test, expect } from '../utils/test';
|
||||
|
||||
test.describe.serial('OC - Livechat Triggers', () => {
|
||||
let triggersName: string;
|
||||
let triggerMessage: string;
|
||||
let poLiveChat: OmnichannelLiveChat;
|
||||
let newVisitor: { email: string; name: string };
|
||||
let agent: { page: Page; poHomeOmnichannelTriggers: OmnichannelTriggers };
|
||||
|
||||
test.beforeAll(async ({ api, browser }) => {
|
||||
newVisitor = createFakeVisitor();
|
||||
triggersName = faker.string.uuid();
|
||||
triggerMessage = 'This is a trigger message';
|
||||
const requests = await Promise.all([
|
||||
api.post('/livechat/users/agent', { username: 'user1' }),
|
||||
api.post('/livechat/users/manager', { username: 'user1' }),
|
||||
api.post('/settings/Livechat_clear_local_storage_when_chat_ended', { value: true }),
|
||||
]);
|
||||
requests.every((e) => expect(e.status()).toBe(200));
|
||||
|
||||
const { page } = await createAuxContext(browser, Users.user1, '/omnichannel/triggers');
|
||||
agent = { page, poHomeOmnichannelTriggers: new OmnichannelTriggers(page) };
|
||||
await page.emulateMedia({ reducedMotion: 'reduce' });
|
||||
});
|
||||
|
||||
test.beforeEach(async ({ page, api }) => {
|
||||
poLiveChat = new OmnichannelLiveChat(page, api);
|
||||
});
|
||||
|
||||
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}`)));
|
||||
|
||||
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 agent.page.close();
|
||||
});
|
||||
|
||||
test('OC - Livechat Triggers - Baseline', async () => {
|
||||
await poLiveChat.goto();
|
||||
await poLiveChat.openLiveChat();
|
||||
|
||||
await test.step('expect to register visitor', async () => {
|
||||
await expect(poLiveChat.btnChatNow).not.toBeVisible();
|
||||
await poLiveChat.sendMessage(newVisitor, false);
|
||||
});
|
||||
|
||||
await test.step('expect send a message as a visitor', async () => {
|
||||
await poLiveChat.onlineAgentMessage.type('this_a_test_message_from_user');
|
||||
await poLiveChat.btnSendMessageToOnlineAgent.click();
|
||||
await expect(poLiveChat.txtChatMessage('this_a_test_message_from_user')).toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('expect to finish this chat', async () => {
|
||||
await poLiveChat.closeChat();
|
||||
await expect(poLiveChat.txtHeaderTitle).toBeVisible();
|
||||
});
|
||||
});
|
||||
|
||||
test('OC - Livechat Triggers - Create and edit trigger', async () => {
|
||||
triggerMessage = 'This is a trigger message time on site';
|
||||
await test.step('expect create new trigger', async () => {
|
||||
await agent.poHomeOmnichannelTriggers.createTrigger(triggersName, triggerMessage, 'Visitor time on site', 5);
|
||||
});
|
||||
|
||||
triggerMessage = 'This is a trigger message chat opened by visitor';
|
||||
await test.step('expect update trigger', async () => {
|
||||
await agent.poHomeOmnichannelTriggers.table.findRowByName(triggersName).click();
|
||||
await agent.poHomeOmnichannelTriggers.updateTrigger(`edited-${triggersName}`, triggerMessage);
|
||||
});
|
||||
});
|
||||
|
||||
test('OC - Livechat Triggers - Condition: chat opened by visitor', async () => {
|
||||
await test.step('expect to start conversation', async () => {
|
||||
await poLiveChat.goto();
|
||||
await poLiveChat.openLiveChat();
|
||||
});
|
||||
|
||||
await test.step('expect trigger message before registration', async () => {
|
||||
await expect(poLiveChat.txtChatMessage(triggerMessage)).toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('expect to register visitor', async () => {
|
||||
await poLiveChat.btnChatNow.click();
|
||||
await poLiveChat.sendMessage(newVisitor, false);
|
||||
});
|
||||
|
||||
await test.step('expect trigger message after registration', async () => {
|
||||
await expect(poLiveChat.txtChatMessage(triggerMessage)).not.toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('expect send a message as a visitor', async () => {
|
||||
await poLiveChat.onlineAgentMessage.type('this_a_test_message_from_user');
|
||||
await poLiveChat.btnSendMessageToOnlineAgent.click();
|
||||
await expect(poLiveChat.txtChatMessage('this_a_test_message_from_user')).toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('expect to finish this chat', async () => {
|
||||
await poLiveChat.closeChat();
|
||||
await expect(poLiveChat.txtHeaderTitle).toBeVisible();
|
||||
});
|
||||
});
|
||||
|
||||
test('OC - Livechat Triggers - Condition: after guest registration', async () => {
|
||||
triggerMessage = 'This is a trigger message after guest registration';
|
||||
await test.step('expect update trigger to after guest registration', async () => {
|
||||
await agent.poHomeOmnichannelTriggers.table.findRowByName(`edited-${triggersName}`).click();
|
||||
await agent.poHomeOmnichannelTriggers.updateTrigger(`re-edited-${triggersName}`, triggerMessage, 'After guest registration');
|
||||
});
|
||||
|
||||
await test.step('expect to start conversation', async () => {
|
||||
await poLiveChat.goto();
|
||||
await poLiveChat.openLiveChat();
|
||||
});
|
||||
|
||||
await test.step('expect not to have trigger message before registration', async () => {
|
||||
await expect(poLiveChat.txtChatMessage(triggerMessage)).not.toBeVisible();
|
||||
await expect(poLiveChat.btnChatNow).not.toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('expect to register visitor', async () => {
|
||||
await expect(poLiveChat.inputName).toBeVisible();
|
||||
await poLiveChat.sendMessage(newVisitor, false);
|
||||
});
|
||||
|
||||
await test.step('expect trigger message after registration', async () => {
|
||||
await expect(poLiveChat.txtChatMessage(triggerMessage)).toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('expect send a message as a visitor', async () => {
|
||||
await poLiveChat.onlineAgentMessage.type('this_a_test_message_from_user');
|
||||
await poLiveChat.btnSendMessageToOnlineAgent.click();
|
||||
await expect(poLiveChat.txtChatMessage('this_a_test_message_from_user')).toBeVisible();
|
||||
await expect(poLiveChat.txtChatMessage(triggerMessage)).toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('expect to finish this chat', async () => {
|
||||
await poLiveChat.closeChat();
|
||||
await expect(poLiveChat.txtHeaderTitle).toBeVisible();
|
||||
});
|
||||
});
|
||||
|
||||
test('OC - Livechat Triggers - Delete trigger', async () => {
|
||||
await agent.poHomeOmnichannelTriggers.removeTrigger(`re-edited-${triggersName}`);
|
||||
});
|
||||
});
|
||||
214
apps/meteor/tests/e2e/omnichannel/omnichannel-units.spec.ts
Normal file
214
apps/meteor/tests/e2e/omnichannel/omnichannel-units.spec.ts
Normal file
@@ -0,0 +1,214 @@
|
||||
import { faker } from '@faker-js/faker';
|
||||
import type { Page } from '@playwright/test';
|
||||
|
||||
import { IS_EE } from '../config/constants';
|
||||
import { Users } from '../fixtures/userStates';
|
||||
import { OmnichannelUnits } from '../page-objects/omnichannel';
|
||||
import { setSettingValueById } from '../utils';
|
||||
import { createAgent } from '../utils/omnichannel/agents';
|
||||
import { createDepartment } from '../utils/omnichannel/departments';
|
||||
import { createMonitor } from '../utils/omnichannel/monitors';
|
||||
import { createOrUpdateUnit } from '../utils/omnichannel/units';
|
||||
import { test, expect } from '../utils/test';
|
||||
|
||||
test.use({ storageState: Users.admin.state });
|
||||
|
||||
test.describe('OC - Manage Units', () => {
|
||||
test.skip(!IS_EE, 'OC - Manage Units > Enterprise Edition Only');
|
||||
|
||||
let poOmnichannelUnits: OmnichannelUnits;
|
||||
|
||||
let department: Awaited<ReturnType<typeof createDepartment>>;
|
||||
let department2: Awaited<ReturnType<typeof createDepartment>>;
|
||||
|
||||
let agent: Awaited<ReturnType<typeof createAgent>>;
|
||||
|
||||
let monitor: Awaited<ReturnType<typeof createMonitor>>;
|
||||
|
||||
let monitor2: Awaited<ReturnType<typeof createMonitor>>;
|
||||
|
||||
test.beforeAll(async ({ api }) => {
|
||||
department = await createDepartment(api);
|
||||
department2 = await createDepartment(api);
|
||||
});
|
||||
|
||||
test.beforeAll(async ({ api }) => {
|
||||
agent = await createAgent(api, 'user2');
|
||||
});
|
||||
|
||||
test.beforeAll(async ({ api }) => {
|
||||
monitor = await createMonitor(api, 'user2');
|
||||
monitor2 = await createMonitor(api, 'user3');
|
||||
});
|
||||
|
||||
test.beforeAll(async ({ api }) => {
|
||||
await setSettingValueById(api, 'Omnichannel_enable_department_removal', true);
|
||||
});
|
||||
|
||||
test.afterAll(async ({ api }) => {
|
||||
await department.delete();
|
||||
await department2.delete();
|
||||
await monitor.delete();
|
||||
await monitor2.delete();
|
||||
await agent.delete();
|
||||
await setSettingValueById(api, 'Omnichannel_enable_department_removal', false);
|
||||
});
|
||||
|
||||
test.beforeEach(async ({ page }: { page: Page }) => {
|
||||
poOmnichannelUnits = new OmnichannelUnits(page);
|
||||
await poOmnichannelUnits.goto();
|
||||
});
|
||||
|
||||
test('OC - Manage Units - Create Unit', async () => {
|
||||
const unitName = faker.string.uuid();
|
||||
|
||||
await test.step('expect correct form default state', async () => {
|
||||
await poOmnichannelUnits.createNew();
|
||||
await expect(poOmnichannelUnits.manageUnit.root).toBeVisible();
|
||||
await expect(poOmnichannelUnits.manageUnit.btnSave).toBeEnabled();
|
||||
await expect(poOmnichannelUnits.manageUnit.btnCancel).toBeEnabled();
|
||||
await poOmnichannelUnits.manageUnit.btnCancel.click();
|
||||
await expect(poOmnichannelUnits.manageUnit.root).not.toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('expect to create new unit', async () => {
|
||||
await poOmnichannelUnits.createNew();
|
||||
await poOmnichannelUnits.manageUnit.inputName.fill(unitName);
|
||||
await poOmnichannelUnits.manageUnit.selectVisibility('public');
|
||||
await poOmnichannelUnits.manageUnit.selectDepartment(department.data.name);
|
||||
await poOmnichannelUnits.manageUnit.selectMonitor('user2');
|
||||
await expect(poOmnichannelUnits.manageUnit.findMonitorChipOption('user2')).toBeVisible();
|
||||
await poOmnichannelUnits.manageUnit.btnSave.click();
|
||||
await expect(poOmnichannelUnits.manageUnit.root).not.toBeVisible();
|
||||
|
||||
await poOmnichannelUnits.search(unitName);
|
||||
await expect(poOmnichannelUnits.table.findRowByName(unitName)).toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('expect to delete unit', async () => {
|
||||
await poOmnichannelUnits.deleteUnit(unitName);
|
||||
await expect(poOmnichannelUnits.table.findRowByName(unitName)).toHaveCount(0);
|
||||
});
|
||||
});
|
||||
|
||||
test('OC - Manage Units - Edit unit name', async ({ api }) => {
|
||||
const unitName = faker.string.uuid();
|
||||
const editedUnitName = faker.string.uuid();
|
||||
|
||||
const unit = await test.step('expect to create new unit', async () => {
|
||||
const { data: newUnit } = await createOrUpdateUnit(api, {
|
||||
name: unitName,
|
||||
visibility: 'public',
|
||||
monitors: [{ monitorId: monitor.data._id, username: 'user2' }],
|
||||
departments: [{ departmentId: department.data._id }],
|
||||
});
|
||||
|
||||
return newUnit;
|
||||
});
|
||||
|
||||
await poOmnichannelUnits.goto();
|
||||
|
||||
await test.step('expect to edit unit', async () => {
|
||||
await poOmnichannelUnits.search(unit.name);
|
||||
await poOmnichannelUnits.table.findRowByName(unit.name).click();
|
||||
await expect(poOmnichannelUnits.manageUnit.root).toBeVisible();
|
||||
await poOmnichannelUnits.manageUnit.inputName.fill(editedUnitName);
|
||||
await poOmnichannelUnits.manageUnit.btnSave.click();
|
||||
await expect(poOmnichannelUnits.manageUnit.root).not.toBeVisible();
|
||||
await expect(poOmnichannelUnits.inputSearch).toBeVisible();
|
||||
await poOmnichannelUnits.search(editedUnitName);
|
||||
await expect(poOmnichannelUnits.table.findRowByName(editedUnitName)).toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('expect to add another monitor to list', async () => {
|
||||
await poOmnichannelUnits.table.findRowByName(editedUnitName).click();
|
||||
await poOmnichannelUnits.manageUnit.selectMonitor('user3');
|
||||
await poOmnichannelUnits.manageUnit.btnSave.click();
|
||||
await expect(poOmnichannelUnits.manageUnit.root).not.toBeVisible();
|
||||
|
||||
await poOmnichannelUnits.search(editedUnitName);
|
||||
await poOmnichannelUnits.table.findRowByName(editedUnitName).click();
|
||||
|
||||
await expect(poOmnichannelUnits.manageUnit.findMonitorChipOption('user2')).toBeVisible();
|
||||
await expect(poOmnichannelUnits.manageUnit.findMonitorChipOption('user3')).toBeVisible();
|
||||
});
|
||||
|
||||
await test.step('expect unit to remove one of the two monitors', async () => {
|
||||
await poOmnichannelUnits.search(editedUnitName);
|
||||
await poOmnichannelUnits.table.findRowByName(editedUnitName).click();
|
||||
await poOmnichannelUnits.manageUnit.removeMonitor('user2');
|
||||
await poOmnichannelUnits.manageUnit.btnSave.click();
|
||||
await expect(poOmnichannelUnits.manageUnit.root).not.toBeVisible();
|
||||
|
||||
await poOmnichannelUnits.search(editedUnitName);
|
||||
await poOmnichannelUnits.table.findRowByName(editedUnitName).click();
|
||||
await expect(poOmnichannelUnits.manageUnit.findMonitorChipOption('user3')).toBeVisible();
|
||||
await expect(poOmnichannelUnits.manageUnit.findMonitorChipOption('user2')).toBeHidden();
|
||||
});
|
||||
|
||||
await test.step('expect to delete unit', async () => {
|
||||
await poOmnichannelUnits.table.findRowByName(editedUnitName).click();
|
||||
await expect(poOmnichannelUnits.manageUnit.root).toBeVisible();
|
||||
|
||||
await poOmnichannelUnits.deleteUnit(editedUnitName);
|
||||
await expect(poOmnichannelUnits.table.findRowByName(editedUnitName)).not.toBeVisible();
|
||||
});
|
||||
});
|
||||
|
||||
test('OC - Manage Units - Edit unit departments', async ({ api, page }) => {
|
||||
const unit = await test.step('expect to create new unit', async () => {
|
||||
const { data: unit } = await createOrUpdateUnit(api, {
|
||||
name: faker.string.uuid(),
|
||||
visibility: 'public',
|
||||
monitors: [{ monitorId: monitor.data._id, username: 'user2' }],
|
||||
departments: [{ departmentId: department.data._id }],
|
||||
});
|
||||
|
||||
return unit;
|
||||
});
|
||||
|
||||
await page.reload();
|
||||
|
||||
await test.step('expect to add unit departments', async () => {
|
||||
await poOmnichannelUnits.search(unit.name);
|
||||
await poOmnichannelUnits.table.findRowByName(unit.name).click();
|
||||
await expect(poOmnichannelUnits.manageUnit.root).toBeVisible();
|
||||
await poOmnichannelUnits.manageUnit.selectDepartment(department2.data.name);
|
||||
await poOmnichannelUnits.manageUnit.btnSave.click();
|
||||
await expect(poOmnichannelUnits.manageUnit.root).not.toBeVisible();
|
||||
|
||||
await poOmnichannelUnits.search(unit.name);
|
||||
await poOmnichannelUnits.table.findRowByName(unit.name).click();
|
||||
await expect(poOmnichannelUnits.manageUnit.root).toBeVisible();
|
||||
await expect(poOmnichannelUnits.manageUnit.findDepartmentsChipOption(department2.data.name)).toBeVisible();
|
||||
await poOmnichannelUnits.manageUnit.findDepartmentsChipOption(department2.data.name).hover();
|
||||
|
||||
await expect(page.getByRole('tooltip', { name: department2.data.name })).toBeVisible();
|
||||
await poOmnichannelUnits.manageUnit.close();
|
||||
});
|
||||
|
||||
await test.step('expect to remove unit departments', async () => {
|
||||
await poOmnichannelUnits.search(unit.name);
|
||||
await poOmnichannelUnits.table.findRowByName(unit.name).click();
|
||||
await expect(poOmnichannelUnits.manageUnit.root).toBeVisible();
|
||||
await poOmnichannelUnits.manageUnit.selectDepartment(department2.data.name);
|
||||
await poOmnichannelUnits.manageUnit.btnSave.click();
|
||||
await expect(poOmnichannelUnits.manageUnit.root).not.toBeVisible();
|
||||
|
||||
await poOmnichannelUnits.search(unit.name);
|
||||
await poOmnichannelUnits.table.findRowByName(unit.name).click();
|
||||
await expect(poOmnichannelUnits.manageUnit.root).toBeVisible();
|
||||
await expect(poOmnichannelUnits.manageUnit.findDepartmentsChipOption(department2.data.name)).toBeHidden();
|
||||
await poOmnichannelUnits.manageUnit.close();
|
||||
});
|
||||
|
||||
await test.step('expect to delete unit', async () => {
|
||||
await poOmnichannelUnits.search(unit.name);
|
||||
await poOmnichannelUnits.table.findRowByName(unit.name).click();
|
||||
await expect(poOmnichannelUnits.manageUnit.root).toBeVisible();
|
||||
|
||||
await poOmnichannelUnits.deleteUnit(unit.name);
|
||||
await expect(poOmnichannelUnits.table.findRowByName(unit.name)).not.toBeVisible();
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user