Files
upstream-mirror 30810eecd7
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
snapshot of https://github.com/RocketChat/Rocket.Chat.git (develop, 2026-09-16; blobs > 131072B omitted)
2026-09-16 01:21:02 +05:00

244 lines
6.8 KiB
TypeScript

import fs from 'fs/promises';
import type { Page, Locator, APIResponse } from '@playwright/test';
import { expect } from '../../utils/test';
import { RoutedPage } from '../routed-page';
export class OmnichannelLiveChat extends RoutedPage {
protected readonly route = '/livechat';
constructor(
page: Page,
private readonly api: { get(url: string): Promise<APIResponse> },
) {
super(page);
}
async waitForReady(): Promise<void> {
await this.btnOpenLiveChat.waitFor({ state: 'visible' });
}
btnOpenOnlineLiveChat(label: string): Locator {
return this.page.locator(`role=button[name="${label}"]`);
}
get btnOpenLiveChat(): Locator {
return this.page.locator(`[data-qa-id="chat-button"]`);
}
get btnNewChat(): Locator {
return this.page.locator(`role=button[name="New Chat"]`);
}
get btnOptions(): Locator {
return this.page.locator(`button >> text="Options"`);
}
get btnCloseChat(): Locator {
return this.page.locator(`button >> text="Finish this chat"`);
}
get btnChangeDepartment(): Locator {
return this.page.locator(`button >> text="Change department"`);
}
get btnCloseChatConfirm(): Locator {
return this.page.locator(`button >> text="Yes"`);
}
get btnExpandChat(): Locator {
return this.page.getByRole('button', { name: 'Expand chat' });
}
get txtHeaderTitle(): Locator {
return this.page.locator('div >> text="Chat Finished"');
}
get btnChatNow(): Locator {
return this.page.locator('[type="button"] >> text="Chat now"');
}
get headerTitle(): Locator {
return this.page.locator('[data-qa="header-title"]');
}
get txtWatermark(): Locator {
return this.page.locator('[data-qa="livechat-watermark"]');
}
get imgLogo(): Locator {
return this.btnOpenLiveChat.locator('img[alt="Livechat"]');
}
alertMessage(message: string): Locator {
return this.page.getByRole('alert').locator(`text="${message}"`);
}
txtChatMessage(message: string): Locator {
return this.page.locator(`[data-qa="message-bubble"] >> text="${message}"`);
}
async closeChat(): Promise<void> {
await this.btnOptions.click();
await this.btnCloseChat.click();
await this.btnCloseChatConfirm.click();
}
async openLiveChat(): Promise<void> {
const { value: siteName } = await (await this.api.get('/settings/Livechat_title')).json();
await this.btnOpenOnlineLiveChat(siteName).click();
}
// TODO: replace openLivechat with this method and create a new method for openOnlineLivechat
// as openLivechat only opens a chat that is in the 'online' state
async openAnyLiveChat(): Promise<void> {
await this.btnOpenLiveChat.click();
}
async startNewChat(): Promise<void> {
await this.btnNewChat.click();
}
async openAnyLiveChatAndSendMessage(params: {
liveChatUser: { name: string; email: string };
message: string;
isOffline?: boolean;
department?: string;
}): Promise<void> {
const { liveChatUser, message, isOffline, department } = params;
await this.openAnyLiveChat();
await this.sendMessage(liveChatUser, isOffline, department);
await this.onlineAgentMessage.fill(message);
await this.btnSendMessageToOnlineAgent.click();
}
unreadMessagesBadge(count: number): Locator {
const name = count === 1 ? `${count} unread message` : `${count} unread messages`;
return this.page.locator(`role=status[name="${name}"]`);
}
get inputName(): Locator {
return this.page.locator('[name="name"]');
}
get inputEmail(): Locator {
return this.page.locator('[name="email"]');
}
get selectDepartment(): Locator {
return this.page.locator('[name="department"]');
}
get textAreaMessage(): Locator {
return this.page.locator('[name="message"]');
}
btnSendMessage(btnText: string): Locator {
return this.page.locator(`role=button[name="${btnText}"]`);
}
get btnOk(): Locator {
return this.page.locator('role=button[name="OK"]');
}
get btnYes(): Locator {
return this.page.locator('role=button[name="Yes"]');
}
get onlineAgentMessage(): Locator {
return this.page.locator('[contenteditable="true"]');
}
get btnSendMessageToOnlineAgent(): Locator {
return this.page.locator('footer div div div:nth-child(3) button');
}
get livechatModal(): Locator {
return this.page.locator('[data-qa-type="modal-overlay"]');
}
livechatModalText(text: string): Locator {
return this.page.locator(`[data-qa-type="modal-overlay"] >> text=${text}`);
}
get fileUploadTarget(): Locator {
return this.page.locator('#files-drop-target');
}
findUploadedFileLink(fileName: string): Locator {
return this.page.getByRole('link', { name: fileName });
}
get typingIndicatorForVisitor(): Locator {
return this.page.getByRole('status', { name: /typing/i });
}
public async sendMessage(liveChatUser: { name: string; email: string }, isOffline = true, department?: string): Promise<void> {
const buttonLabel = isOffline ? 'Send' : 'Start chat';
await this.inputName.fill(liveChatUser.name);
await this.inputEmail.fill(liveChatUser.email);
if (department) {
await this.selectDepartment.selectOption({ label: department });
}
if (isOffline) {
await this.textAreaMessage.type('any_message');
}
await this.btnSendMessage(buttonLabel).click();
await this.page.waitForSelector('[data-qa="livechat-composer"]');
}
public async sendMessageAndCloseChat(
liveChatUser: { name: string; email: string },
message = 'this_a_test_message_from_user',
): Promise<void> {
await this.openAnyLiveChat();
await this.sendMessage(liveChatUser, false);
await this.onlineAgentMessage.fill(message);
await this.btnSendMessageToOnlineAgent.click();
await expect(this.txtChatMessage(message)).toBeVisible();
await expect(this.page.locator('[data-qa="message-bubble"] >> text="Chat started"')).toBeVisible();
await this.closeChat();
}
async dragAndDropTxtFile(): Promise<void> {
const contract = await fs.readFile('./tests/e2e/fixtures/files/any_file.txt', 'utf-8');
const dataTransfer = await this.page.evaluateHandle((contract) => {
const data = new DataTransfer();
const file = new File([`${contract}`], 'any_file.txt', {
type: 'text/plain',
});
data.items.add(file);
return data;
}, contract);
await this.fileUploadTarget.dispatchEvent('dragenter', { dataTransfer });
await this.fileUploadTarget.dispatchEvent('drop', { dataTransfer });
}
async dragAndDropLstFile(): Promise<void> {
const contract = await fs.readFile('./tests/e2e/fixtures/files/lst-test.lst', 'utf-8');
const dataTransfer = await this.page.evaluateHandle((contract) => {
const data = new DataTransfer();
const file = new File([`${contract}`], 'lst-test.lst', {
type: 'text/plain',
});
data.items.add(file);
return data;
}, contract);
await this.fileUploadTarget.dispatchEvent('dragenter', { dataTransfer });
await this.fileUploadTarget.dispatchEvent('drop', { dataTransfer });
}
queuePosition(position: number): Locator {
return this.page.locator(`div[role='alert'] >> text=Your spot is #${position}`);
}
}