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:
@@ -0,0 +1,17 @@
|
||||
import type { Locator, Page } from '@playwright/test';
|
||||
|
||||
export class FederationAccountProfile {
|
||||
private readonly page: Page;
|
||||
|
||||
constructor(page: Page) {
|
||||
this.page = page;
|
||||
}
|
||||
|
||||
get inputName(): Locator {
|
||||
return this.page.locator('//label[contains(text(), "Name")]/..//input');
|
||||
}
|
||||
|
||||
get btnSubmit(): Locator {
|
||||
return this.page.getByRole('button', { name: 'Save changes', exact: true });
|
||||
}
|
||||
}
|
||||
78
apps/meteor/tests/e2e/federation/page-objects/admin.ts
Normal file
78
apps/meteor/tests/e2e/federation/page-objects/admin.ts
Normal file
@@ -0,0 +1,78 @@
|
||||
import type { Locator, Page } from '@playwright/test';
|
||||
|
||||
import { FederationAdminFlextab } from './fragments/admin-flextab';
|
||||
|
||||
export class FederationAdmin {
|
||||
private readonly page: Page;
|
||||
|
||||
readonly tabs: FederationAdminFlextab;
|
||||
|
||||
constructor(page: Page) {
|
||||
this.page = page;
|
||||
this.tabs = new FederationAdminFlextab(page);
|
||||
}
|
||||
|
||||
get inputSearchRooms(): Locator {
|
||||
return this.page.locator('input[placeholder ="Search rooms"]');
|
||||
}
|
||||
|
||||
get inputSearchUsers(): Locator {
|
||||
return this.page.locator('input[placeholder="Search Users"]');
|
||||
}
|
||||
|
||||
get inputSearchSettings(): Locator {
|
||||
return this.page.locator('input[type=search]');
|
||||
}
|
||||
|
||||
get roomsInputName(): Locator {
|
||||
return this.page.locator('//label[text()="Name"]/following-sibling::span//input');
|
||||
}
|
||||
|
||||
get roomsInputDescription(): Locator {
|
||||
return this.page.locator('//label[text()="Description"]/following-sibling::span//textarea');
|
||||
}
|
||||
|
||||
get roomsInputAnnouncement(): Locator {
|
||||
return this.page.locator('//label[text()="Announcement"]/following-sibling::span//textarea');
|
||||
}
|
||||
|
||||
get roomsInputTopic(): Locator {
|
||||
return this.page.locator('//label[text()="Topic"]/following-sibling::span//textarea');
|
||||
}
|
||||
|
||||
get roomsInputFavorite(): Locator {
|
||||
return this.page.locator('//label[text()="Favorite"]/following-sibling::span//input/following-sibling::i');
|
||||
}
|
||||
|
||||
get roomsInputPrivate(): Locator {
|
||||
return this.page.locator('//label[text()="Private"]/following-sibling::span//input/following-sibling::i');
|
||||
}
|
||||
|
||||
get roomsInputReadOnly(): Locator {
|
||||
return this.page.locator('//label[text()="Read Only"]/following-sibling::span//input/following-sibling::i');
|
||||
}
|
||||
|
||||
get roomsInputArchived(): Locator {
|
||||
return this.page.locator('//label[text()="Archived"]/following-sibling::span//input/following-sibling::i');
|
||||
}
|
||||
|
||||
get roomsInputDefault(): Locator {
|
||||
return this.page.locator('//label[text()="Default"]/following-sibling::span//input/following-sibling::i');
|
||||
}
|
||||
|
||||
get roomsInputFeatured(): Locator {
|
||||
return this.page.locator('//label[text()="Featured"]/following-sibling::span//input/following-sibling::i');
|
||||
}
|
||||
|
||||
get roomsBtnDelete(): Locator {
|
||||
return this.page.locator('role=button[name="Delete"]');
|
||||
}
|
||||
|
||||
get roomsBtnUploadAvatar(): Locator {
|
||||
return this.page.locator('role=button[name="Upload"]');
|
||||
}
|
||||
|
||||
get roomsBtnDefaultAvatar(): Locator {
|
||||
return this.page.locator('button[title="Set Default Avatar"]');
|
||||
}
|
||||
}
|
||||
94
apps/meteor/tests/e2e/federation/page-objects/channel.ts
Normal file
94
apps/meteor/tests/e2e/federation/page-objects/channel.ts
Normal file
@@ -0,0 +1,94 @@
|
||||
import type { Locator, Page } from '@playwright/test';
|
||||
|
||||
import { FederationHomeContent } from './fragments/home-content';
|
||||
import { FederationHomeFlextab } from './fragments/home-flextab';
|
||||
import { FederationSidenav } from './fragments/home-sidenav';
|
||||
import { Navbar, RoomToolbar, ToastMessages } from '../../page-objects/fragments';
|
||||
import { CreateNewChannelModal, CreateNewDMModal } from '../../page-objects/fragments/modals';
|
||||
|
||||
export class FederationChannel {
|
||||
private readonly page: Page;
|
||||
|
||||
readonly content: FederationHomeContent;
|
||||
|
||||
readonly sidenav: FederationSidenav;
|
||||
|
||||
readonly navbar: Navbar;
|
||||
|
||||
readonly tabs: FederationHomeFlextab;
|
||||
|
||||
readonly roomToolbar: RoomToolbar;
|
||||
|
||||
readonly toastMessage: ToastMessages;
|
||||
|
||||
readonly newChannelModal: CreateNewChannelModal;
|
||||
|
||||
readonly newDMModal: CreateNewDMModal;
|
||||
|
||||
constructor(page: Page) {
|
||||
this.page = page;
|
||||
this.content = new FederationHomeContent(page);
|
||||
this.sidenav = new FederationSidenav(page);
|
||||
this.navbar = new Navbar(page);
|
||||
this.tabs = new FederationHomeFlextab(page);
|
||||
this.roomToolbar = new RoomToolbar(page);
|
||||
this.toastMessage = new ToastMessages(page);
|
||||
this.newChannelModal = new CreateNewChannelModal(page);
|
||||
this.newDMModal = new CreateNewDMModal(page);
|
||||
}
|
||||
|
||||
get btnContextualbarClose(): Locator {
|
||||
return this.page.locator('[data-qa="ContextualbarActionClose"]');
|
||||
}
|
||||
|
||||
async getFederationServerName(): Promise<string> {
|
||||
return (await this.page.locator('[data-qa="federated-origin-server-name"]').locator('span').innerText()).substring(1).trim();
|
||||
}
|
||||
|
||||
async createPublicChannelAndInviteUsersUsingCreationModal(channelName: string, usernamesToInvite: string[]) {
|
||||
await this.navbar.createNew('Channel', channelName, {
|
||||
private: false,
|
||||
federated: true,
|
||||
members: usernamesToInvite,
|
||||
});
|
||||
}
|
||||
|
||||
async createDiscussionSearchingForChannel(channelName: string) {
|
||||
await this.navbar.openCreate('Discussion');
|
||||
await this.page.locator('//label[text()="Parent channel or group"]/following-sibling::span//input').waitFor();
|
||||
await this.page.locator('//label[text()="Parent channel or group"]/following-sibling::span//input').focus();
|
||||
await this.page.locator('//label[text()="Parent channel or group"]/following-sibling::span//input').type(channelName, { delay: 100 });
|
||||
}
|
||||
|
||||
async createTeam(teamName: string) {
|
||||
await this.navbar.createNew('Team', teamName);
|
||||
}
|
||||
|
||||
async createPrivateGroupAndInviteUsersUsingCreationModal(channelName: string, usernamesToInvite: string[]) {
|
||||
await this.navbar.createNew('Channel', channelName, {
|
||||
private: true,
|
||||
federated: true,
|
||||
members: usernamesToInvite,
|
||||
});
|
||||
}
|
||||
|
||||
async createDirectMessagesUsingModal(usernamesToInvite: string[]) {
|
||||
await this.navbar.openCreate('Direct message');
|
||||
|
||||
for await (const username of usernamesToInvite) {
|
||||
await this.newDMModal.inviteUserToDM(username);
|
||||
}
|
||||
await this.newDMModal.btnCreate.click();
|
||||
}
|
||||
|
||||
async createNonFederatedPublicChannelAndInviteUsersUsingCreationModal(channelName: string, usernamesToInvite: string[]) {
|
||||
await this.navbar.openCreate('Channel');
|
||||
await this.newChannelModal.checkboxPrivate.click();
|
||||
await this.newChannelModal.inputName.fill(channelName);
|
||||
for await (const username of usernamesToInvite) {
|
||||
await this.newChannelModal.inviteUserToChannel(username);
|
||||
}
|
||||
|
||||
await this.newChannelModal.btnCreate.click();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
import type { Locator, Page } from '@playwright/test';
|
||||
|
||||
export class FederationAdminFlextabUsers {
|
||||
private readonly page: Page;
|
||||
|
||||
constructor(page: Page) {
|
||||
this.page = page;
|
||||
}
|
||||
|
||||
get btnNew(): Locator {
|
||||
return this.page.locator('role=button[name="New"]');
|
||||
}
|
||||
|
||||
get btnEdit(): Locator {
|
||||
return this.page.locator('role=button[name="Edit"]');
|
||||
}
|
||||
|
||||
get btnSave(): Locator {
|
||||
return this.page.locator('role=button[name="Save"]');
|
||||
}
|
||||
|
||||
get inputName(): Locator {
|
||||
return this.page.locator('//label[text()="Name"]/following-sibling::span//input');
|
||||
}
|
||||
|
||||
get inputUserName(): Locator {
|
||||
return this.page.locator('//label[text()="Username"]/following-sibling::span//input');
|
||||
}
|
||||
|
||||
get inputEmail(): Locator {
|
||||
return this.page.locator('//label[text()="Email"]/following-sibling::span//input').first();
|
||||
}
|
||||
|
||||
get inputPassword(): Locator {
|
||||
return this.page.locator('//label[text()="Password"]/following-sibling::span//input');
|
||||
}
|
||||
|
||||
get checkboxVerified(): Locator {
|
||||
return this.page.locator('//label[text()="Email"]/following-sibling::span//input/following-sibling::i');
|
||||
}
|
||||
|
||||
async addRole(role: string): Promise<void> {
|
||||
await this.page.locator('//label[text()="Roles"]/following-sibling::span//input').click();
|
||||
await this.page.locator(`li[value=${role}]`).click();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
import type { Page } from '@playwright/test';
|
||||
|
||||
import { FederationAdminFlextabUsers } from './admin-flextab-users';
|
||||
|
||||
export class FederationAdminFlextab {
|
||||
readonly users: FederationAdminFlextabUsers;
|
||||
|
||||
constructor(page: Page) {
|
||||
this.users = new FederationAdminFlextabUsers(page);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,244 @@
|
||||
import type { Locator, Page } from '@playwright/test';
|
||||
|
||||
export class FederationHomeContent {
|
||||
protected readonly page: Page;
|
||||
|
||||
constructor(page: Page) {
|
||||
this.page = page;
|
||||
}
|
||||
|
||||
get inputMessage(): Locator {
|
||||
return this.page.locator('[name="msg"]');
|
||||
}
|
||||
|
||||
get messagePopUpItems(): Locator {
|
||||
return this.page.locator('role=menu[name="People"]');
|
||||
}
|
||||
|
||||
get messageListItems(): Locator {
|
||||
return this.page.locator('[role="listitem"][aria-roledescription="message"]');
|
||||
}
|
||||
|
||||
get lastUserMessage(): Locator {
|
||||
return this.messageListItems.last();
|
||||
}
|
||||
|
||||
get lastUserMessageBody(): Locator {
|
||||
return this.lastUserMessage.locator('[role="document"][aria-roledescription="message body"]');
|
||||
}
|
||||
|
||||
async sendMessage(text: string): Promise<void> {
|
||||
await this.page.locator('[name="msg"]').type(text);
|
||||
await this.page.locator('button[aria-label="Send"]').click();
|
||||
}
|
||||
|
||||
async sendMessageUsingEnter(text: string): Promise<void> {
|
||||
await this.page.locator('[name="msg"]').type(text);
|
||||
await this.page.keyboard.press('Enter');
|
||||
}
|
||||
|
||||
async editLastMessage(message: string): Promise<void> {
|
||||
await this.openLastMessageMenu();
|
||||
await this.btnOptionEditMessage.click();
|
||||
await this.page.locator('[name="msg"]').fill(message);
|
||||
await this.page.keyboard.press('Enter');
|
||||
}
|
||||
|
||||
async deleteLastMessage(): Promise<void> {
|
||||
await this.openLastMessageMenu();
|
||||
await this.btnOptionDeleteMessage.click();
|
||||
await this.page.locator('#modal-root dialog .rcx-modal__inner .rcx-modal__footer .rcx-button--danger').click();
|
||||
}
|
||||
|
||||
async starLastMessage(): Promise<void> {
|
||||
await this.openLastMessageMenu();
|
||||
await this.btnOptionStarMessage.waitFor();
|
||||
await this.btnOptionStarMessage.click();
|
||||
}
|
||||
|
||||
async replyInDm(message: string): Promise<void> {
|
||||
await this.openLastMessageMenu();
|
||||
await this.btnOptionReplyDirectly.click();
|
||||
await this.page.waitForTimeout(2000);
|
||||
await this.page.locator('[name="msg"]').type(message, { delay: 100 });
|
||||
await this.page.waitForTimeout(2000);
|
||||
await this.page.keyboard.press('Enter');
|
||||
}
|
||||
|
||||
async sendAudioRecordedMessage(): Promise<void> {
|
||||
await this.btnRecordAudio.click();
|
||||
await this.page.waitForTimeout(3000);
|
||||
await this.page.locator('.rc-message-box__icon.rc-message-box__audio-message-done').click();
|
||||
await this.btnModalConfirm.click();
|
||||
}
|
||||
|
||||
async sendAudioRecordedInThreadMessage(): Promise<void> {
|
||||
await this.btnRecordAudio.nth(1).click();
|
||||
await this.page.waitForTimeout(3000);
|
||||
await this.page.locator('.rc-message-box__icon.rc-message-box__audio-message-done').click();
|
||||
await this.btnModalConfirm.click();
|
||||
}
|
||||
|
||||
async sendVideoRecordedMessage(): Promise<void> {
|
||||
await this.btnVideoMessage.click();
|
||||
await this.page.locator('.rcx-box.rcx-box--full.rcx-icon--name-video').click();
|
||||
await this.page.waitForTimeout(3000);
|
||||
await this.page.locator('.rcx-box.rcx-box--full.rcx-icon--name-stop-unfilled').click();
|
||||
await this.page.locator('button >> text="Send"').click();
|
||||
await this.page.waitForTimeout(3000);
|
||||
await this.btnModalConfirm.click();
|
||||
}
|
||||
|
||||
async dispatchSlashCommand(text: string): Promise<void> {
|
||||
await this.page.locator('[name="msg"]').fill(text);
|
||||
await this.page.locator('button[aria-label="Send"]').waitFor();
|
||||
await this.page.locator('button[aria-label="Send"]').click();
|
||||
}
|
||||
|
||||
get btnModalConfirm(): Locator {
|
||||
return this.page.locator('#modal-root .rcx-button-group--align-end .rcx-button--primary');
|
||||
}
|
||||
|
||||
get lastMessageFileName(): Locator {
|
||||
return this.page.locator('[role="listitem"][aria-roledescription="message"]:last-child');
|
||||
}
|
||||
|
||||
async getLastFileMessageByFileName(filename: string): Promise<Locator> {
|
||||
return this.page
|
||||
.locator('[role="listitem"][aria-roledescription="message"]:last-child .rcx-message-container')
|
||||
.last()
|
||||
.locator(`div[title="${filename}"]`);
|
||||
}
|
||||
|
||||
async getLastFileThreadMessageByFileName(filename: string): Promise<Locator> {
|
||||
return this.page
|
||||
.locator('div.thread-list ul.thread [role="listitem"][aria-roledescription="message"]:last-child .rcx-message-container')
|
||||
.last()
|
||||
.locator(`div[title="${filename}"]`);
|
||||
}
|
||||
|
||||
get lastFileMessage(): Locator {
|
||||
return this.page.locator('[role="listitem"][aria-roledescription="message"]:last-child .rcx-message-container').last();
|
||||
}
|
||||
|
||||
get waitForLastMessageTextAttachmentEqualsText(): Locator {
|
||||
return this.page.locator('[role="listitem"][aria-roledescription="message"]:last-child .rcx-attachment__details .rcx-message-body');
|
||||
}
|
||||
|
||||
get waitForLastThreadMessageTextAttachmentEqualsText(): Locator {
|
||||
return this.page
|
||||
.locator('div.thread-list ul.thread [role="listitem"][aria-roledescription="message"]')
|
||||
.last()
|
||||
.locator('.rcx-attachment__details');
|
||||
}
|
||||
|
||||
get btnOptionEditMessage(): Locator {
|
||||
return this.page.locator('[data-qa-id="edit-message"]');
|
||||
}
|
||||
|
||||
get btnOptionDeleteMessage(): Locator {
|
||||
return this.page.locator('[data-qa-id="delete-message"]');
|
||||
}
|
||||
|
||||
get btnOptionPinMessage(): Locator {
|
||||
return this.page.locator('[data-qa-id="pin-message"]');
|
||||
}
|
||||
|
||||
get btnOptionStarMessage(): Locator {
|
||||
return this.page.locator('[data-qa-id="star-message"]');
|
||||
}
|
||||
|
||||
get btnVideoMessage(): Locator {
|
||||
return this.page.locator('[data-qa-id="video-message"]');
|
||||
}
|
||||
|
||||
get btnRecordAudio(): Locator {
|
||||
return this.page.locator('[data-qa-id="audio-record"]');
|
||||
}
|
||||
|
||||
get btnMenuMoreActions() {
|
||||
return this.page.locator('[data-qa-id="menu-more-actions"]');
|
||||
}
|
||||
|
||||
get btnContactEdit(): Locator {
|
||||
return this.page.locator('.rcx-vertical-bar button:has-text("Edit")');
|
||||
}
|
||||
|
||||
get btnOptionReplyInThread(): Locator {
|
||||
return this.page.locator('[data-qa-id="reply-in-thread"]');
|
||||
}
|
||||
|
||||
get btnOptionStartDiscussion(): Locator {
|
||||
return this.page.locator('[data-qa-id="start-discussion"]');
|
||||
}
|
||||
|
||||
get btnOptionReplyDirectly(): Locator {
|
||||
return this.page.locator('[data-qa-id="reply-directly"]');
|
||||
}
|
||||
|
||||
get lastThreadMessageText(): Locator {
|
||||
return this.page.locator('div.thread-list ul.thread [role="listitem"][aria-roledescription="message"]').last();
|
||||
}
|
||||
|
||||
async sendFileMessage(fileName: string): Promise<void> {
|
||||
await this.page.locator('input[type=file]').setInputFiles(`./tests/e2e/federation/files/${fileName}`);
|
||||
}
|
||||
|
||||
async sendThreadMessage(message: string): Promise<void> {
|
||||
await this.page.getByRole('dialog').locator('[name="msg"]').last().fill(message);
|
||||
await this.page.keyboard.press('Enter');
|
||||
}
|
||||
|
||||
async openLastMessageMenu(): Promise<void> {
|
||||
await this.lastUserMessage.hover();
|
||||
await this.lastUserMessage.getByRole('button', { name: 'More', exact: true }).waitFor();
|
||||
await this.lastUserMessage.getByRole('button', { name: 'More', exact: true }).click();
|
||||
}
|
||||
|
||||
threadSendToChannelAlso(): Locator {
|
||||
return this.page.getByRole('dialog').locator('label', { hasText: 'Also send to channel' });
|
||||
}
|
||||
|
||||
async quoteMessage(message: string): Promise<void> {
|
||||
await this.openLastMessageMenu();
|
||||
await this.page.locator('[data-qa-id="quote-message"]').click();
|
||||
await this.page.locator('[name="msg"]').fill(message);
|
||||
await this.page.keyboard.press('Enter');
|
||||
}
|
||||
|
||||
async openLastThreadMessageMenu(): Promise<void> {
|
||||
await this.lastThreadMessageText.hover();
|
||||
await this.lastThreadMessageText.getByRole('button', { name: 'More', exact: true }).waitFor();
|
||||
await this.lastThreadMessageText.getByRole('button', { name: 'More', exact: true }).click();
|
||||
}
|
||||
|
||||
async quoteMessageInsideThread(message: string): Promise<void> {
|
||||
await this.openLastThreadMessageMenu();
|
||||
await this.page.locator('[data-qa-id="quote-message"]').click();
|
||||
await this.sendThreadMessage(message);
|
||||
}
|
||||
|
||||
async reactToMessage(emoji: string): Promise<void> {
|
||||
await this.openLastMessageMenu();
|
||||
await this.page.locator('[data-qa-id="reaction-message"]').click();
|
||||
await this.page.locator('input.js-emojipicker-search').type(emoji);
|
||||
await this.page.locator(`[data-emoji="${emoji}"]`).last().click();
|
||||
}
|
||||
|
||||
async unreactLastMessage(): Promise<void> {
|
||||
await this.lastUserMessage.locator('.rcx-message-reactions__reaction').nth(1).waitFor();
|
||||
await this.lastUserMessage.locator('.rcx-message-reactions__reaction').nth(1).click();
|
||||
}
|
||||
|
||||
async getSystemMessageByText(text: string): Promise<Locator> {
|
||||
return this.page.locator('[role="document"][aria-roledescription="system message body"]', { hasText: text });
|
||||
}
|
||||
|
||||
async getLastSystemMessageName(): Promise<Locator> {
|
||||
return this.page.locator('[role="listitem"][aria-roledescription="system message"]').last().getByRole('button');
|
||||
}
|
||||
|
||||
async getAllReactions(): Promise<Locator> {
|
||||
return this.lastUserMessage.locator('.rcx-message-reactions__reaction');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
import type { Locator, Page } from '@playwright/test';
|
||||
|
||||
export class FederationHomeFlextabChannels {
|
||||
private readonly page: Page;
|
||||
|
||||
constructor(page: Page) {
|
||||
this.page = page;
|
||||
}
|
||||
|
||||
get btnAddExisting(): Locator {
|
||||
return this.page.locator('button >> text="Add Existing"');
|
||||
}
|
||||
|
||||
get inputChannels(): Locator {
|
||||
return this.page.locator('#modal-root input').first();
|
||||
}
|
||||
|
||||
get btnAdd(): Locator {
|
||||
return this.page.locator('#modal-root button:has-text("Add")');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
import type { Locator, Page } from '@playwright/test';
|
||||
|
||||
export class FederationHomeFlextabDirectMessageMember {
|
||||
private readonly page: Page;
|
||||
|
||||
constructor(page: Page) {
|
||||
this.page = page;
|
||||
}
|
||||
|
||||
getUserInfoUsername(username: string): Locator {
|
||||
return this.page.locator(`//div[contains(@class, "rcx-box--full") and contains(@title, "${username}")]`);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
import type { Locator, Page } from '@playwright/test';
|
||||
|
||||
export class FederationHomeFlextabMembers {
|
||||
private readonly page: Page;
|
||||
|
||||
constructor(page: Page) {
|
||||
this.page = page;
|
||||
}
|
||||
|
||||
getUserInList(username: string): Locator {
|
||||
return this.page.locator(`[data-qa="MemberItem-${username}"]`);
|
||||
}
|
||||
|
||||
get addUsersButton(): Locator {
|
||||
return this.page.locator('role=button[name="Add"]');
|
||||
}
|
||||
|
||||
get btnRemoveUserFromRoom(): Locator {
|
||||
return this.page.locator('[value="removeUser"]');
|
||||
}
|
||||
|
||||
get btnMenuUserInfo(): Locator {
|
||||
return this.page.getByRole('dialog', { name: 'User Info', exact: true }).getByRole('button', { name: 'More', exact: true });
|
||||
}
|
||||
|
||||
getKebabMenuForUser(username: string): Locator {
|
||||
return this.page.locator(`[data-username="${username}"] [data-testid="menu"]`);
|
||||
}
|
||||
|
||||
async getOptionFromKebabMenuForUser(optionName: string): Promise<Locator> {
|
||||
return this.page.locator(`ol li[value="${optionName}"].rcx-option`);
|
||||
}
|
||||
|
||||
async removeUserFromRoom(username: string): Promise<void> {
|
||||
await this.getUserInList(username).hover();
|
||||
await this.getKebabMenuForUser(username).click();
|
||||
await (await this.getOptionFromKebabMenuForUser('removeUser')).click();
|
||||
await this.page.locator('#modal-root dialog .rcx-modal__inner .rcx-modal__footer .rcx-button--danger').click();
|
||||
}
|
||||
|
||||
async addMultipleUsers(usernames: string[]) {
|
||||
await this.addUsersButton.click();
|
||||
for await (const username of usernames) {
|
||||
await this.page.getByRole('textbox', { name: 'Choose users' }).click();
|
||||
await this.page.getByRole('textbox', { name: 'Choose users' }).fill(username);
|
||||
|
||||
await this.page.getByRole('listbox').waitFor();
|
||||
await this.page.getByRole('listbox').selectOption(username);
|
||||
}
|
||||
await this.addUsersButton.click();
|
||||
}
|
||||
|
||||
async showAllUsers() {
|
||||
await this.page.locator('.rcx-select >> text=Online').first().click();
|
||||
await this.page.locator('.rcx-option:has-text("All")').first().click();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
import type { Locator, Page } from '@playwright/test';
|
||||
|
||||
export class FederationHomeFlextabNotificationPreferences {
|
||||
private readonly page: Page;
|
||||
|
||||
constructor(page: Page) {
|
||||
this.page = page;
|
||||
}
|
||||
|
||||
get btnSave(): Locator {
|
||||
return this.page.locator('role=button[name="Save"]');
|
||||
}
|
||||
|
||||
getPreferenceByDevice(device: string): Locator {
|
||||
return this.page.locator(`//div[@id="${device}Alert"]`);
|
||||
}
|
||||
|
||||
async selectDropdownById(text: string): Promise<void> {
|
||||
await this.page.locator(`//div[@id="${text}"]`).click();
|
||||
}
|
||||
|
||||
async selectOptionByLabel(text: string): Promise<void> {
|
||||
await this.page.locator(`li.rcx-option >> text="${text}"`).click();
|
||||
}
|
||||
|
||||
async selectDevice(text: string): Promise<void> {
|
||||
await this.page.locator(`[data-qa-id="${text}-notifications"]`).click();
|
||||
}
|
||||
|
||||
async updateDevicePreference(device: string): Promise<void> {
|
||||
await this.selectDevice(device);
|
||||
await this.selectDropdownById(`${device}Alert`);
|
||||
await this.selectOptionByLabel('Mentions');
|
||||
}
|
||||
|
||||
async updateAllNotificationPreferences(): Promise<void> {
|
||||
await this.updateDevicePreference('Desktop');
|
||||
await this.updateDevicePreference('Mobile');
|
||||
await this.updateDevicePreference('Email');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
import type { Locator, Page } from '@playwright/test';
|
||||
|
||||
export class FederationHomeFlextabRoom {
|
||||
private readonly page: Page;
|
||||
|
||||
constructor(page: Page) {
|
||||
this.page = page;
|
||||
}
|
||||
|
||||
get btnEdit(): Locator {
|
||||
return this.page.locator('role=button[name="Edit"]');
|
||||
}
|
||||
|
||||
get btnLeave(): Locator {
|
||||
return this.page.locator('role=button[name="Leave"]');
|
||||
}
|
||||
|
||||
get btnDelete(): Locator {
|
||||
return this.page.locator('role=button[name="Delete"]');
|
||||
}
|
||||
|
||||
get inputName(): Locator {
|
||||
return this.page.getByRole('dialog').getByRole('textbox', { name: 'Name' });
|
||||
}
|
||||
|
||||
get inputTopic(): Locator {
|
||||
return this.page.getByRole('dialog').getByRole('textbox', { name: 'Topic' });
|
||||
}
|
||||
|
||||
get inputAnnouncement(): Locator {
|
||||
return this.page.getByRole('dialog').getByRole('textbox', { name: 'Announcement' });
|
||||
}
|
||||
|
||||
get inputDescription(): Locator {
|
||||
return this.page.getByRole('dialog').getByRole('textbox', { name: 'Description' });
|
||||
}
|
||||
|
||||
get checkboxReadOnly(): Locator {
|
||||
return this.page.locator('text=Read OnlyOnly authorized users can write new messages >> i');
|
||||
}
|
||||
|
||||
get btnSave(): Locator {
|
||||
return this.page.locator('role=button[name="Save"]');
|
||||
}
|
||||
|
||||
get btnModalConfirm(): Locator {
|
||||
return this.page.locator('#modal-root dialog .rcx-modal__inner .rcx-modal__footer .rcx-button--danger');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
import type { Locator, Page } from '@playwright/test';
|
||||
|
||||
import { FederationHomeFlextabChannels } from './home-flextab-channels';
|
||||
import { FederationHomeFlextabDirectMessageMember } from './home-flextab-dm-member';
|
||||
import { FederationHomeFlextabMembers } from './home-flextab-members';
|
||||
import { FederationHomeFlextabNotificationPreferences } from './home-flextab-notificationPreferences';
|
||||
import { FederationHomeFlextabRoom } from './home-flextab-room';
|
||||
|
||||
export class FederationHomeFlextab {
|
||||
private readonly page: Page;
|
||||
|
||||
readonly members: FederationHomeFlextabMembers;
|
||||
|
||||
readonly dmUserMember: FederationHomeFlextabDirectMessageMember;
|
||||
|
||||
readonly room: FederationHomeFlextabRoom;
|
||||
|
||||
readonly channels: FederationHomeFlextabChannels;
|
||||
|
||||
readonly notificationPreferences: FederationHomeFlextabNotificationPreferences;
|
||||
|
||||
constructor(page: Page) {
|
||||
this.page = page;
|
||||
this.members = new FederationHomeFlextabMembers(page);
|
||||
this.room = new FederationHomeFlextabRoom(page);
|
||||
this.channels = new FederationHomeFlextabChannels(page);
|
||||
this.notificationPreferences = new FederationHomeFlextabNotificationPreferences(page);
|
||||
this.dmUserMember = new FederationHomeFlextabDirectMessageMember(page);
|
||||
}
|
||||
|
||||
get btnAddExistingChannelToTeam(): Locator {
|
||||
return this.page.locator('role=button[name="Add Existing"]');
|
||||
}
|
||||
|
||||
async searchForChannelOnAddChannelToTeam(channelName: string): Promise<void> {
|
||||
await this.page.locator('//label[contains(text(), "Channels")]/..//input').focus();
|
||||
await this.page.waitForTimeout(2000);
|
||||
await this.page.locator('//label[contains(text(), "Channels")]/..//input').type(channelName);
|
||||
}
|
||||
|
||||
get userInfoUsername(): Locator {
|
||||
return this.page.locator('[data-qa="UserInfoUserName"]');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
import type { Locator, Page } from '@playwright/test';
|
||||
|
||||
export class FederationSidenav {
|
||||
private readonly page: Page;
|
||||
|
||||
constructor(page: Page) {
|
||||
this.page = page;
|
||||
}
|
||||
|
||||
get checkboxFederatedChannel(): Locator {
|
||||
return this.page.locator(
|
||||
'//*[@id="modal-root"]//*[contains(@class, "rcx-field") and contains(text(), "Federated")]/../following-sibling::label/i',
|
||||
);
|
||||
}
|
||||
|
||||
async countFilteredChannelsOnDirectory(name: string): Promise<number> {
|
||||
await this.page.locator('button[title="Directory"]').click();
|
||||
await this.page.locator('button:has-text("Channels")').click();
|
||||
await this.page.locator('input[placeholder ="Search Channels"]').focus();
|
||||
await this.page.locator('input[placeholder ="Search Channels"]').type(name, { delay: 100 });
|
||||
await this.page.waitForTimeout(5000);
|
||||
|
||||
return this.page.locator('table tbody tr').count();
|
||||
}
|
||||
|
||||
async openChatWhenHaveMultipleWithTheSameName(name: string, item: number): Promise<void> {
|
||||
await this.page.locator('role=navigation >> role=button[name=Search]').click();
|
||||
await this.page.locator('role=search >> role=searchbox').focus();
|
||||
await this.page.locator('role=search >> role=searchbox').type(name);
|
||||
await this.page.waitForTimeout(2000);
|
||||
await this.page.locator(`role=search >> role=listbox >> role=link >> text="${name}"`).nth(item).click({ force: true });
|
||||
}
|
||||
|
||||
async countRoomsByNameOnSearch(name: string): Promise<number> {
|
||||
await this.page.locator('role=navigation >> role=button[name=Search]').click();
|
||||
await this.page.locator('role=search >> role=searchbox').focus();
|
||||
await this.page.locator('role=search >> role=searchbox').type(name);
|
||||
await this.page.locator(`role=search >> role=listbox >> role=link >> text="${name}"`).waitFor();
|
||||
await this.page.waitForTimeout(2000);
|
||||
|
||||
return this.page.locator(`role=search >> role=listbox >> role=link >> text="${name}"`).count();
|
||||
}
|
||||
|
||||
async openDMMultipleChat(name: string): Promise<void> {
|
||||
await this.page.locator('role=navigation >> role=button[name=Search]').click();
|
||||
await this.page.locator('role=search >> role=searchbox').focus();
|
||||
await this.page.locator('role=search >> role=searchbox').type(name);
|
||||
await this.page.locator(`role=search >> role=listbox >> role=link >> text="${name}"`).waitFor();
|
||||
await this.page.locator(`.rcx-sidebar-item`).nth(1).click({ force: true });
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user