The communications platform that puts data protection first.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
Rocket.Chat/apps/meteor/tests/e2e/threads.spec.ts

212 lines
10 KiB

import { Users } from './fixtures/userStates';
import { HomeChannel } from './page-objects';
import { createTargetChannel, deleteChannel } from './utils';
import { expect, test } from './utils/test';
test.use({ storageState: Users.admin.state });
test.describe.serial('Threads', () => {
let poHomeChannel: HomeChannel;
let targetChannel: string;
test.beforeAll(async ({ api }) => {
targetChannel = await createTargetChannel(api);
});
test.beforeEach(async ({ page }) => {
poHomeChannel = new HomeChannel(page);
await page.goto('/home');
await poHomeChannel.navbar.openChat(targetChannel);
});
test.afterAll(async ({ api }) => deleteChannel(api, targetChannel));
test('expect no unread banner when replying to a thread in a fresh channel', async ({ page }) => {
await poHomeChannel.content.sendMessage('parent for unread-banner test');
await poHomeChannel.content.openReplyInThread();
await poHomeChannel.content.sendMessageInThread('first thread reply');
await page.waitForTimeout(200);
await expect(page.getByTitle('Mark as read')).not.toBeVisible();
});
test('expect thread message preview if alsoSendToChannel checkbox is checked', async ({ page }) => {
await poHomeChannel.content.sendMessage('this is a message for reply');
await page.locator('[data-qa-type="message"]').last().hover();
await page.locator('role=button[name="Reply in thread"]').click();
await expect(page).toHaveURL(/.*thread/);
await poHomeChannel.content.toggleAlsoSendThreadToChannel(true);
await page.getByRole('dialog').locator('[name="msg"]').last().fill('This is a thread message also sent in channel');
await page.keyboard.press('Enter');
await expect(poHomeChannel.content.lastThreadMessageText).toContainText('This is a thread message also sent in channel');
await expect(poHomeChannel.content.lastUserMessage).toContainText('This is a thread message also sent in channel');
});
test('expect open threads contextual bar when clicked on thread preview', async ({ page }) => {
await poHomeChannel.content.lastThreadMessagePreviewText.click();
await expect(page).toHaveURL(/.*thread/);
await expect(poHomeChannel.content.lastThreadMessageText).toContainText('This is a thread message also sent in channel');
});
test.describe('hideFlexTab Preference enabled for threads', () => {
test.beforeAll(async ({ api }) => {
await expect(
(await api.post('/users.setPreferences', { userId: 'rocketchat.internal.admin.test', data: { hideFlexTab: true } })).status(),
).toBe(200);
});
test.afterAll(async ({ api }) => {
await expect(
(await api.post('/users.setPreferences', { userId: 'rocketchat.internal.admin.test', data: { hideFlexTab: false } })).status(),
).toBe(200);
});
test('expect to close thread contextual bar on clicking outside', async ({ page }) => {
await poHomeChannel.content.lastThreadMessagePreviewText.click();
await expect(page).toHaveURL(/.*thread/);
await poHomeChannel.content.lastUserMessageNotThread.click();
await expect(page).not.toHaveURL(/.*thread/);
});
test('expect open threads contextual bar when clicked on thread preview', async ({ page }) => {
await poHomeChannel.content.lastThreadMessagePreviewText.click();
await expect(page).toHaveURL(/.*thread/);
await expect(poHomeChannel.content.lastThreadMessageText).toContainText('This is a thread message also sent in channel');
});
test('expect not to close thread contextual bar when performing some action', async ({ page }) => {
await poHomeChannel.content.lastThreadMessagePreviewText.click();
await expect(page).toHaveURL(/.*thread/);
await expect(poHomeChannel.content.lastThreadMessageText).toContainText('This is a thread message also sent in channel');
await poHomeChannel.content.openLastThreadMessageMenu();
await page.locator('role=menuitem[name="Copy text"]').click();
await expect(page).toHaveURL(/.*thread/);
await expect(poHomeChannel.content.lastThreadMessageText).toContainText('This is a thread message also sent in channel');
});
});
test('expect upload a file attachment in thread with description', async ({ page }) => {
await poHomeChannel.content.lastThreadMessagePreviewText.click();
await expect(page).toHaveURL(/.*thread/);
await poHomeChannel.content.dragAndDropTxtFileToThread();
await poHomeChannel.content.descriptionInput.fill('any_description');
await poHomeChannel.content.fileNameInput.fill('any_file1.txt');
await poHomeChannel.content.btnModalConfirm.click();
await expect(poHomeChannel.content.lastThreadMessageFileDescription).toHaveText('any_description');
await expect(poHomeChannel.content.lastThreadMessageFileName).toContainText('any_file1.txt');
});
test.describe('thread message actions', () => {
test.beforeEach(async ({ page }) => {
poHomeChannel = new HomeChannel(page);
await page.goto('/home');
await poHomeChannel.navbar.openChat(targetChannel);
await poHomeChannel.content.sendMessage('this is a message for reply');
await page.locator('[data-qa-type="message"]').last().hover();
await page.locator('role=button[name="Reply in thread"]').click();
});
test('expect delete the thread message and close thread if has only one message', async ({ page }) => {
await poHomeChannel.content.openLastThreadMessageMenu();
await expect(page).toHaveURL(/.*thread/);
await page.locator('role=menuitem[name="Delete"]').click();
await page.locator('#modal-root .rcx-button-group--align-end .rcx-button--danger').click();
await expect(page).not.toHaveURL(/.*thread/);
});
test('expect delete the thread message and keep thread open if has more than one message', async ({ page }) => {
await page.locator('.rcx-vertical-bar').locator(`role=textbox[name="Message #${targetChannel}"]`).type('another reply message');
await page.keyboard.press('Enter');
await poHomeChannel.content.openLastThreadMessageMenu();
await expect(page).toHaveURL(/.*thread/);
await page.locator('role=menuitem[name="Delete"]').click();
await page.locator('#modal-root .rcx-button-group--align-end .rcx-button--danger').click();
await expect(page).toHaveURL(/.*thread/);
});
test('expect edit the thread message', async ({ page }) => {
await poHomeChannel.content.openLastThreadMessageMenu();
await page.locator('role=menuitem[name="Edit"]').click();
await page.locator('[name="msg"]').last().fill('this message was edited');
await page.keyboard.press('Enter');
await expect(poHomeChannel.content.lastUserMessageBody).toHaveText('this message was edited');
});
test('expect quote the thread message', async ({ page }) => {
await page.getByRole('dialog').locator('[data-qa-type="message"]').last().hover();
await page.locator('role=button[name="Quote"]').click();
await page.locator('[name="msg"]').last().fill('this is a quote message');
await page.keyboard.press('Enter');
await expect(poHomeChannel.content.lastThreadMessageTextAttachmentEqualsText).toContainText('this is a message for reply');
});
test('expect star the thread message', async () => {
await poHomeChannel.content.openLastThreadMessageMenu();
await poHomeChannel.content.btnOptionStarMessage.click();
await poHomeChannel.content.btnToolbarOptions.click();
await poHomeChannel.content.starredMessagesMenuOption.click();
await expect(poHomeChannel.content.lastUserMessageBody).toHaveText('this is a message for reply');
});
test('expect copy the thread message content to clipboard', async ({ page, context }) => {
await context.grantPermissions(['clipboard-read', 'clipboard-write']);
await poHomeChannel.content.openLastThreadMessageMenu();
await page.locator('role=menuitem[name="Copy text"]').click();
const clipboardText = await page.evaluate('navigator.clipboard.readText()');
expect(clipboardText).toBe('this is a message for reply');
});
test('expect copy the thread message link to clipboard', async ({ page, context }) => {
await context.grantPermissions(['clipboard-read', 'clipboard-write']);
await poHomeChannel.content.openLastThreadMessageMenu();
await page.locator('role=menuitem[name="Copy link"]').click();
const clipboardText = await page.evaluate('navigator.clipboard.readText()');
expect(clipboardText).toContain('http');
});
test('expect close thread if has only one message and user press escape', async ({ page }) => {
await expect(page).toHaveURL(/.*thread/);
await expect(page.getByRole('dialog').locator('[data-qa-type="message"]')).toBeVisible();
await expect(page.locator('[name="msg"]').last()).toBeFocused();
await page.keyboard.press('Escape');
await expect(page).not.toHaveURL(/.*thread/);
});
test('expect reset the thread composer to original message if user presses escape', async ({ page }) => {
await expect(page).toHaveURL(/.*thread/);
await expect(page.getByRole('dialog').locator('[data-qa-type="message"]')).toBeVisible();
await expect(page.locator('[name="msg"]').last()).toBeFocused();
await page.locator('[name="msg"]').last().fill('message to be edited');
await page.keyboard.press('Enter');
await page.keyboard.press('ArrowUp');
await expect(page.locator('[name="msg"]').last()).toHaveValue('message to be edited');
await page.locator('[name="msg"]').last().fill('this message was edited');
await page.keyboard.press('Escape');
await expect(page.locator('[name="msg"]').last()).toHaveValue('message to be edited');
await expect(page).toHaveURL(/.*thread/);
});
test('expect clean composer and keep the thread open if user is editing message and presses escape', async ({ page }) => {
await expect(page).toHaveURL(/.*thread/);
await expect(page.getByRole('dialog').locator('[data-qa-type="message"]')).toBeVisible();
await expect(page.locator('[name="msg"]').last()).toBeFocused();
await page.locator('[name="msg"]').last().fill('message to be edited');
await page.keyboard.press('Enter');
await page.keyboard.press('ArrowUp');
await expect(page.locator('[name="msg"]').last()).toHaveValue('message to be edited');
await page.keyboard.press('Escape');
await expect(page.locator('[name="msg"]').last()).toHaveValue('');
await expect(page).toHaveURL(/.*thread/);
});
});
});