Files
upstream-rocketchat/apps/meteor/tests/e2e/e2e-encryption/e2ee-encrypted-channels.spec.ts
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

408 lines
17 KiB
TypeScript

import { faker } from '@faker-js/faker';
import { DEFAULT_USER_CREDENTIALS } from '../config/constants';
import { Users } from '../fixtures/userStates';
import { HomeChannel } from '../page-objects';
import { ToastMessages } from '../page-objects/fragments';
import { CreateE2EEChannel } from '../page-objects/fragments/e2ee';
import { deletePrivateRoomsByName } from '../utils';
import { preserveSettings } from '../utils/preserveSettings';
import { test, expect } from '../utils/test';
const settingsList = [
'E2E_Enable',
'E2E_Allow_Unencrypted_Messages',
'E2E_Enabled_Default_DirectRooms',
'E2E_Enabled_Default_PrivateRooms',
];
preserveSettings(settingsList);
test.describe('E2EE Encrypted Channels', () => {
const createdChannels: string[] = [];
let poHomeChannel: HomeChannel;
let toastMessages: ToastMessages;
let createE2EEChannel: CreateE2EEChannel;
test.use({ storageState: Users.userE2EE.state });
test.beforeAll(async ({ api }) => {
await api.post('/settings/E2E_Enable', { value: true });
await api.post('/settings/E2E_Allow_Unencrypted_Messages', { value: true });
await api.post('/settings/E2E_Enabled_Default_DirectRooms', { value: false });
await api.post('/settings/E2E_Enabled_Default_PrivateRooms', { value: false });
await api.post('/im.delete', { username: 'user2' });
});
test.beforeEach(async ({ page }) => {
poHomeChannel = new HomeChannel(page);
createE2EEChannel = new CreateE2EEChannel(page);
await poHomeChannel.goto();
});
test.afterAll(async () => {
await deletePrivateRoomsByName(
{ username: Users.userE2EE.data.username, password: DEFAULT_USER_CREDENTIALS.password },
createdChannels,
);
});
test('expect create a private channel encrypted and send an encrypted message', async ({ page }) => {
toastMessages = new ToastMessages(page);
const channelName = faker.string.uuid();
await createE2EEChannel.createAndStore(channelName, createdChannels);
await expect(page).toHaveURL(`/group/${channelName}`);
await expect(poHomeChannel.content.encryptedRoomHeaderIcon).toBeVisible();
await poHomeChannel.content.sendMessage('hello world');
await expect(poHomeChannel.content.lastUserMessageBody).toHaveText('hello world');
await expect(poHomeChannel.content.lastUserMessage.locator('.rcx-icon--name-key')).toBeVisible();
await toastMessages.dismissToast();
await poHomeChannel.roomToolbar.openMoreOptions();
await poHomeChannel.roomToolbar.menuItemDisableE2EEncryption.click();
await expect(page.getByRole('dialog', { name: 'Disable encryption' })).toBeVisible();
await page.getByRole('button', { name: 'Disable encryption' }).click();
await poHomeChannel.toastMessage.dismissToast();
await page.waitForTimeout(1000);
await poHomeChannel.content.sendMessage('hello world not encrypted');
await expect(poHomeChannel.content.lastUserMessageBody).toHaveText('hello world not encrypted');
await expect(poHomeChannel.content.lastUserMessage.locator('.rcx-icon--name-key')).not.toBeVisible();
await poHomeChannel.roomToolbar.openMoreOptions();
await expect(poHomeChannel.roomToolbar.menuItemEnableE2EEncryption).toBeVisible();
await poHomeChannel.roomToolbar.menuItemEnableE2EEncryption.click();
await expect(page.getByRole('dialog', { name: 'Enable encryption' })).toBeVisible();
await page.getByRole('button', { name: 'Enable encryption' }).click();
await poHomeChannel.toastMessage.dismissToast();
await page.waitForTimeout(1000);
await poHomeChannel.content.sendMessage('hello world encrypted again');
await expect(poHomeChannel.content.lastUserMessageBody).toHaveText('hello world encrypted again');
await expect(poHomeChannel.content.lastUserMessage.locator('.rcx-icon--name-key')).toBeVisible();
});
test('expect create a private encrypted channel and send a encrypted thread message', async ({ page }) => {
const channelName = faker.string.uuid();
await createE2EEChannel.createAndStore(channelName, createdChannels);
await expect(page).toHaveURL(`/group/${channelName}`);
await expect(poHomeChannel.content.encryptedRoomHeaderIcon).toBeVisible();
await poHomeChannel.content.sendMessage('This is the thread main message.');
await expect(poHomeChannel.content.lastUserMessageBody).toHaveText('This is the thread main message.');
await expect(poHomeChannel.content.lastUserMessage.locator('.rcx-icon--name-key')).toBeVisible();
await poHomeChannel.content.openReplyInThread();
await expect(page).toHaveURL(/.*thread/);
await expect(poHomeChannel.content.mainThreadMessageText).toContainText('This is the thread main message.');
await expect(poHomeChannel.content.mainThreadMessageText.locator('.rcx-icon--name-key')).toBeVisible();
await poHomeChannel.content.toggleAlsoSendThreadToChannel(true);
await page.getByRole('dialog').locator('[name="msg"]').last().fill('This is an encrypted thread message also sent in channel');
await page.keyboard.press('Enter');
await expect(poHomeChannel.content.lastUserThreadMessage).toContainText('This is an encrypted thread message also sent in channel');
await expect(poHomeChannel.content.lastUserThreadMessage.locator('.rcx-icon--name-key')).toBeVisible();
await expect(poHomeChannel.content.lastThreadMessagePreview).toContainText('This is an encrypted thread message also sent in channel');
await expect(poHomeChannel.content.mainThreadMessageText).toContainText('This is the thread main message.');
await expect(poHomeChannel.content.mainThreadMessageText.locator('.rcx-icon--name-key')).toBeVisible();
});
test('expect create a private encrypted channel and check disabled message menu actions on an encrypted message', async ({ page }) => {
const channelName = faker.string.uuid();
await createE2EEChannel.createAndStore(channelName, createdChannels);
await expect(page).toHaveURL(`/group/${channelName}`);
await expect(poHomeChannel.content.encryptedRoomHeaderIcon).toBeVisible();
await poHomeChannel.content.sendMessage('This is an encrypted message.');
await expect(poHomeChannel.content.lastUserMessageBody).toHaveText('This is an encrypted message.');
await expect(poHomeChannel.content.lastUserMessage.locator('.rcx-icon--name-key')).toBeVisible();
await poHomeChannel.content.lastUserMessage.hover();
await expect(page.locator('role=button[name="Forward message not available on encrypted content"]')).toBeDisabled();
await poHomeChannel.content.openLastMessageMenu();
await expect(page.locator('role=menuitem[name="Reply in direct message"]')).toHaveClass(/disabled/);
await expect(page.locator('role=menuitem[name="Copy link"]')).toHaveClass(/disabled/);
});
test('expect create a private channel, encrypt it and send an encrypted message', async ({ page }) => {
const channelName = faker.string.uuid();
await poHomeChannel.navbar.createNew('Channel', channelName);
createE2EEChannel.store(channelName, createdChannels);
await expect(page).toHaveURL(`/group/${channelName}`);
await poHomeChannel.toastMessage.waitForDisplay();
await poHomeChannel.toastMessage.dismissToast();
await poHomeChannel.roomToolbar.openMoreOptions();
// TODO(@jessicaschelly/@dougfabris): fix this flaky behavior
if (!(await poHomeChannel.roomToolbar.menuItemEnableE2EEncryption.isVisible())) {
await poHomeChannel.roomToolbar.openMoreOptions();
}
await poHomeChannel.roomToolbar.menuItemEnableE2EEncryption.click();
await expect(page.getByRole('dialog', { name: 'Enable encryption' })).toBeVisible();
await page.getByRole('button', { name: 'Enable encryption' }).click();
await page.waitForTimeout(1000);
await expect(poHomeChannel.content.encryptedRoomHeaderIcon).toBeVisible();
await poHomeChannel.content.sendMessage('hello world');
await expect(poHomeChannel.content.lastUserMessageBody).toHaveText('hello world');
await expect(poHomeChannel.content.lastUserMessage.locator('.rcx-icon--name-key')).toBeVisible();
});
test('expect create a encrypted private channel and mention user', async ({ page }) => {
const channelName = faker.string.uuid();
await createE2EEChannel.createAndStore(channelName, createdChannels);
await expect(page).toHaveURL(`/group/${channelName}`);
await expect(poHomeChannel.content.encryptedRoomHeaderIcon).toBeVisible();
await poHomeChannel.content.sendMessage('hello @user1');
const userMention = page.getByRole('button', {
name: 'user1',
});
await expect(userMention).toBeVisible();
});
test('expect create a encrypted private channel, mention a channel and navigate to it', async ({ page }) => {
const channelName = faker.string.uuid();
await createE2EEChannel.createAndStore(channelName, createdChannels);
await expect(page).toHaveURL(`/group/${channelName}`);
await expect(poHomeChannel.content.encryptedRoomHeaderIcon).toBeVisible();
await poHomeChannel.content.sendMessage('Are you in the #general channel?');
const channelMention = page.getByRole('button', {
name: 'general',
});
await expect(channelMention).toBeVisible();
await channelMention.click();
await expect(page).toHaveURL(`/channel/general`);
});
test('expect create a encrypted private channel, mention a channel and user', async ({ page }) => {
const channelName = faker.string.uuid();
await createE2EEChannel.createAndStore(channelName, createdChannels);
await expect(page).toHaveURL(`/group/${channelName}`);
await expect(poHomeChannel.content.encryptedRoomHeaderIcon).toBeVisible();
await poHomeChannel.content.sendMessage('Are you in the #general channel, @user1 ?');
const channelMention = page.getByRole('button', {
name: 'general',
});
const userMention = page.getByRole('button', {
name: 'user1',
});
await expect(userMention).toBeVisible();
await expect(channelMention).toBeVisible();
});
test('expect create a private channel, send unecrypted messages, encrypt the channel and delete the last message and check the last message in the sidebar', async ({
page,
}) => {
const channelName = faker.string.uuid();
// Enable Sidebar Extended display mode
await poHomeChannel.navbar.setDisplayMode('Extended');
// Create private channel
await poHomeChannel.navbar.createNew('Channel', channelName, { private: true });
createE2EEChannel.store(channelName, createdChannels);
await expect(page).toHaveURL(`/group/${channelName}`);
await poHomeChannel.toastMessage.waitForDisplay();
await poHomeChannel.toastMessage.dismissToast();
// Send Unencrypted Messages
await poHomeChannel.content.sendMessage('first unencrypted message');
await poHomeChannel.content.sendMessage('second unencrypted message');
// Encrypt channel
await poHomeChannel.roomToolbar.openMoreOptions();
await expect(poHomeChannel.roomToolbar.menuItemEnableE2EEncryption).toBeVisible();
await poHomeChannel.roomToolbar.menuItemEnableE2EEncryption.click();
await expect(page.getByRole('dialog', { name: 'Enable encryption' })).toBeVisible();
await page.getByRole('button', { name: 'Enable encryption' }).click();
await page.waitForTimeout(1000);
await expect(poHomeChannel.content.encryptedRoomHeaderIcon).toBeVisible();
// Send Encrypted Messages
const encriptedMessage1 = 'first ENCRYPTED message';
const encriptedMessage2 = 'second ENCRYPTED message';
await poHomeChannel.content.sendMessage(encriptedMessage1);
await poHomeChannel.content.sendMessage(encriptedMessage2);
// Delete last message
await expect(poHomeChannel.content.lastUserMessageBody).toHaveText(encriptedMessage2);
await poHomeChannel.content.openLastMessageMenu();
// TODO(@jessicaschelly/@dougfabris): fix this flaky behavior
if (!(await page.locator('role=menuitem[name="Delete"]').isVisible())) {
await poHomeChannel.content.openLastMessageMenu();
}
await page.locator('role=menuitem[name="Delete"]').click();
await page.locator('#modal-root .rcx-button-group--align-end .rcx-button--danger').click();
// Check last message in the sidebar
const sidebarChannel = poHomeChannel.sidebar.getSidebarItemByName(channelName);
await expect(sidebarChannel).toBeVisible();
await expect(sidebarChannel.getByText(`You: ${encriptedMessage2}`, { exact: true })).not.toBeVisible();
await expect(sidebarChannel.getByText(`You: ${encriptedMessage1}`, { exact: true })).toBeVisible();
});
test('expect create a private encrypted channel and pin/star an encrypted message', async ({ page }) => {
const channelName = faker.string.uuid();
await createE2EEChannel.createAndStore(channelName, createdChannels);
await expect(page).toHaveURL(`/group/${channelName}`);
await expect(poHomeChannel.content.encryptedRoomHeaderIcon).toBeVisible();
await poHomeChannel.content.sendMessage('This message should be pinned and stared.');
await expect(poHomeChannel.content.lastUserMessageBody).toHaveText('This message should be pinned and stared.');
await expect(poHomeChannel.content.lastUserMessage.locator('.rcx-icon--name-key')).toBeVisible();
await poHomeChannel.content.openLastMessageMenu();
await page.locator('role=menuitem[name="Star"]').click();
await poHomeChannel.toastMessage.waitForDisplay();
await poHomeChannel.toastMessage.dismissToast();
await poHomeChannel.content.openLastMessageMenu();
await page.locator('role=menuitem[name="Pin"]').click();
await page.locator('#modal-root >> button:has-text("Yes, pin message")').click();
await poHomeChannel.toastMessage.waitForDisplay();
await poHomeChannel.toastMessage.dismissToast();
await poHomeChannel.roomToolbar.openMoreOptions();
await poHomeChannel.roomToolbar.menuItemPinnedMessages.click();
await expect(page.getByRole('dialog', { name: 'Pinned Messages' })).toBeVisible();
const lastPinnedMessage = page
.getByRole('dialog', { name: 'Pinned Messages' })
.locator('[role="listitem"][aria-roledescription="message"]')
.last();
await expect(lastPinnedMessage).toContainText('This message should be pinned and stared.');
await lastPinnedMessage.hover();
await lastPinnedMessage.locator('role=button[name="More"]').waitFor();
await lastPinnedMessage.locator('role=button[name="More"]').click();
await expect(page.locator('role=menuitem[name="Copy link"]')).toHaveClass(/disabled/);
await poHomeChannel.btnContextualbarClose.click();
await poHomeChannel.roomToolbar.openMoreOptions();
await poHomeChannel.roomToolbar.menuItemStarredMessages.click();
const lastStarredMessage = page
.getByRole('dialog', { name: 'Starred Messages' })
.locator('[role="listitem"][aria-roledescription="message"]')
.last();
await expect(page.getByRole('dialog', { name: 'Starred Messages' })).toBeVisible();
await expect(lastStarredMessage).toContainText('This message should be pinned and stared.');
await lastStarredMessage.hover();
await lastStarredMessage.locator('role=button[name="More"]').waitFor();
await lastStarredMessage.locator('role=button[name="More"]').click();
await expect(page.locator('role=menuitem[name="Copy link"]')).toHaveClass(/disabled/);
});
test('expect to edit encrypted message', async ({ page }) => {
const channelName = faker.string.uuid();
const originalMessage = 'This is the original encrypted message';
const editedMessage = 'This is the edited encrypted message';
await createE2EEChannel.createAndStore(channelName, createdChannels);
await expect(page).toHaveURL(`/group/${channelName}`);
await expect(poHomeChannel.content.encryptedRoomHeaderIcon).toBeVisible();
await poHomeChannel.content.sendMessage(originalMessage);
await expect(poHomeChannel.content.lastUserMessageBody).toHaveText(originalMessage);
await expect(poHomeChannel.content.lastUserMessage.locator('.rcx-icon--name-key')).toBeVisible();
await poHomeChannel.content.openLastMessageMenu();
await poHomeChannel.content.btnOptionEditMessage.click();
await poHomeChannel.composer.inputMessage.fill(editedMessage);
await page.keyboard.press('Enter');
await expect(poHomeChannel.content.lastUserMessageBody).toHaveText(editedMessage);
await expect(poHomeChannel.content.lastUserMessage.locator('.rcx-icon--name-key')).toBeVisible();
});
test('expect to edit encrypted message to include mention', async ({ page }) => {
const channelName = faker.string.uuid();
const originalMessage = 'This is the original encrypted message';
const editedMessage = 'This is the edited encrypted message with a mention to @user1 and #general';
const displayedMessage = 'This is the edited encrypted message with a mention to user1 and general';
await createE2EEChannel.createAndStore(channelName, createdChannels);
await expect(page).toHaveURL(`/group/${channelName}`);
await expect(poHomeChannel.content.encryptedRoomHeaderIcon).toBeVisible();
await poHomeChannel.content.sendMessage(originalMessage);
await expect(poHomeChannel.content.lastUserMessageBody).toHaveText(originalMessage);
await expect(poHomeChannel.content.lastUserMessage.locator('.rcx-icon--name-key')).toBeVisible();
await poHomeChannel.content.openLastMessageMenu();
await poHomeChannel.content.btnOptionEditMessage.click();
await poHomeChannel.composer.inputMessage.fill(editedMessage);
await poHomeChannel.composer.btnSend.click();
await expect(poHomeChannel.content.lastUserMessageBody).toHaveText(displayedMessage);
await expect(poHomeChannel.content.lastUserMessage.locator('.rcx-icon--name-key')).toBeVisible();
const userMention = page.getByRole('button', {
name: 'user1',
});
await expect(userMention).toBeVisible();
const channelMention = page.getByRole('button', {
name: 'general',
});
await expect(channelMention).toBeVisible();
});
});