Skip to content
Closed
Show file tree
Hide file tree
Changes from 17 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
120 changes: 120 additions & 0 deletions apps/meteor/tests/e2e/e2e-encryption/e2ee-channel.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
import { faker } from '@faker-js/faker';

import { Users } from '../fixtures/userStates';
import { HomeChannel } from '../page-objects';
import { EncryptedRoomPage } from '../page-objects/encrypted-room';
import { DisableRoomEncryptionModal, EnableRoomEncryptionModal, CreateE2EEChannel } from '../page-objects/fragments/e2ee';
import { deleteRoom } from '../utils/create-target-channel';
import { preserveSettings } from '../utils/preserveSettings';
import { resolvePrivateRoomId } from '../utils/resolve-room-id';
import { test, expect } from '../utils/test';

const settingsList = ['E2E_Enable', 'E2E_Allow_Unencrypted_Messages'];

preserveSettings(settingsList);

test.describe('E2EE Channel Basic Functionality', () => {
const createdChannels: { name: string; id?: string | null }[] = [];
let poHomeChannel: HomeChannel;
let encryptedRoomPage: EncryptedRoomPage;
let enableEncryptionModal: EnableRoomEncryptionModal;
let disableEncryptionModal: DisableRoomEncryptionModal;
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 });
});

test.beforeEach(async ({ page }) => {
poHomeChannel = new HomeChannel(page);
enableEncryptionModal = new EnableRoomEncryptionModal(page);
disableEncryptionModal = new DisableRoomEncryptionModal(page);
encryptedRoomPage = new EncryptedRoomPage(page);
createE2EEChannel = new CreateE2EEChannel(page);
await poHomeChannel.goto();
});

test.afterAll(async ({ api }) => {
await Promise.all(createdChannels.map(({ id }) => (id ? deleteRoom(api, id) : Promise.resolve())));
});
Comment on lines +16 to +42

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Run this describe serially to protect shared E2E settings.

beforeAll sets /settings/E2E_Enable and friends, afterAll (via preserveSettings) restores them. When multiple specs now execute in parallel, one suite can finish and revert the settings while another is still using them—classic flake territory. Please mark the describe as serial (or otherwise coordinate) so the toggled settings stay consistent for the duration of the suite.

 test.describe('E2EE Channel Basic Functionality', () => {
+	test.describe.configure({ mode: 'serial' });
🤖 Prompt for AI Agents
In apps/meteor/tests/e2e/e2e-encryption/e2ee-channel.spec.ts around lines 16 to
40, the test.describe block must be run serially to avoid races that flip shared
E2E settings between suites; change the describe invocation to a serial describe
(e.g., test.describe.serial(...)) so the beforeAll/afterAll setting toggles
remain consistent for the suite duration and prevent parallel suites from
reverting settings mid-run.


test('expect create a private channel encrypted and send an encrypted message', async ({ page }) => {
const channelName = faker.string.uuid();

await test.step('create encrypted channel', async () => {
await createE2EEChannel.createAndStore(channelName, createdChannels);
await poHomeChannel.content.waitForChannel();
await expect(page).toHaveURL(`/group/${channelName}`);
await expect(poHomeChannel.content.encryptedRoomHeaderIcon).toBeVisible();
});

await test.step('send encrypted message and verify encryption', async () => {
await poHomeChannel.content.sendMessage('hello world');
await expect(poHomeChannel.content.lastUserMessageBody).toHaveText('hello world');
await expect(encryptedRoomPage.lastMessage.encryptedIcon).toBeVisible();
});

await test.step('disable encryption', async () => {
await poHomeChannel.tabs.kebab.click({ force: true });
await expect(poHomeChannel.tabs.btnDisableE2E).toBeVisible();
await poHomeChannel.tabs.btnDisableE2E.click({ force: true });
await disableEncryptionModal.disable();
await expect(poHomeChannel.content.encryptedRoomHeaderIcon).toBeHidden();
});

await test.step('send unencrypted message and verify no encryption', async () => {
await poHomeChannel.content.sendMessage('hello world not encrypted');
await expect(poHomeChannel.content.lastUserMessageBody).toHaveText('hello world not encrypted');
await expect(encryptedRoomPage.lastMessage.encryptedIcon).not.toBeVisible();
});

await test.step('re-enable encryption', async () => {
await poHomeChannel.tabs.kebab.click({ force: true });
await expect(poHomeChannel.tabs.btnEnableE2E).toBeVisible();
await poHomeChannel.tabs.btnEnableE2E.click({ force: true });
await enableEncryptionModal.enable();
await expect(poHomeChannel.content.encryptedRoomHeaderIcon).toBeVisible();
});

await test.step('send encrypted message again and verify encryption restored', async () => {
await poHomeChannel.content.sendMessage('hello world encrypted again');
await expect(poHomeChannel.content.lastUserMessageBody).toHaveText('hello world encrypted again');
await expect(encryptedRoomPage.lastMessage.encryptedIcon).toBeVisible();
});
});

test('expect create a private channel, encrypt it and send an encrypted message', async ({ page }) => {
const channelName = faker.string.uuid();

await test.step('create private channel', async () => {
await poHomeChannel.sidenav.openNewByLabel('Channel');
await poHomeChannel.sidenav.inputChannelName.fill(channelName);
await poHomeChannel.sidenav.btnCreate.click();

await poHomeChannel.content.waitForChannel();
const roomId = await resolvePrivateRoomId(page, channelName);

createdChannels.push({ name: channelName, id: roomId ?? undefined });
await expect(page).toHaveURL(`/group/${channelName}`);
await expect(poHomeChannel.toastSuccess).toBeVisible();
await poHomeChannel.dismissToast();
});
Comment on lines +98 to +104

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Assert roomId resolution to ensure cleanup and fail fast

If resolvePrivateRoomId returns null, you silently skip cleanup. Assert and store a non-null id.

Apply this diff:

-      const roomId = await resolvePrivateRoomId(page, channelName);
-
-      createdChannels.push({ name: channelName, id: roomId ?? undefined });
+      const roomId = await resolvePrivateRoomId(page, channelName);
+      await expect(roomId, 'Failed to resolve roomId for cleanup').toBeTruthy();
+      createdChannels.push({ name: channelName, id: roomId! });

Based on learnings

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const roomId = await resolvePrivateRoomId(page, channelName);
createdChannels.push({ name: channelName, id: roomId ?? undefined });
await expect(page).toHaveURL(`/group/${channelName}`);
await expect(poHomeChannel.toastSuccess).toBeVisible();
await poHomeChannel.dismissToast();
});
const roomId = await resolvePrivateRoomId(page, channelName);
-
await expect(roomId, 'Failed to resolve roomId for cleanup').toBeTruthy();
createdChannels.push({ name: channelName, id: roomId! });
await expect(page).toHaveURL(`/group/${channelName}`);
await expect(poHomeChannel.toastSuccess).toBeVisible();
await poHomeChannel.dismissToast();
🤖 Prompt for AI Agents
In apps/meteor/tests/e2e/e2e-encryption/e2ee-channel.spec.ts around lines
98-104, the test stores roomId which may be null from resolvePrivateRoomId and
silently skips proper cleanup; update the test to assert that roomId is non-null
(e.g., expect(roomId).not.toBeNull() or throw if null) immediately after
resolution, then push the non-null id into createdChannels (use the asserted
value or a non-null assertion) so cleanup runs and the test fails fast on
resolution failure.


await test.step('enable encryption', async () => {
await poHomeChannel.tabs.kebab.click();
await expect(poHomeChannel.tabs.btnEnableE2E).toBeVisible();
await poHomeChannel.tabs.btnEnableE2E.click();
await enableEncryptionModal.enable();
await expect(poHomeChannel.content.encryptedRoomHeaderIcon).toBeVisible();
});

await test.step('send encrypted message and verify', async () => {
await poHomeChannel.content.sendMessage('hello world');
await expect(poHomeChannel.content.lastUserMessageBody).toHaveText('hello world');
await expect(encryptedRoomPage.lastMessage.encryptedIcon).toBeVisible();
});
});
});
Loading
Loading