Skip to content

Commit 0d45149

Browse files
regression: Remove pdf option in export messages as file (RocketChat#36319)
Co-authored-by: Tasso Evangelista <2263066+tassoevan@users.noreply.github.com>
1 parent 9f3c11c commit 0d45149

7 files changed

Lines changed: 174 additions & 84 deletions

File tree

apps/meteor/client/views/room/contextualBar/ExportMessages/ExportMessages.tsx

Lines changed: 39 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,14 @@ const ExportMessages = () => {
109109
}, [t, pfdExportPermission]);
110110

111111
// Remove HTML from download options
112-
const downloadOutputOptions = outputOptions.slice(1);
112+
const downloadOutputOptions = useMemo<SelectOption[]>(() => {
113+
return outputOptions.filter((option) => option[0] !== 'html');
114+
}, [outputOptions]);
115+
116+
// Remove PDF from file options
117+
const fileOutputOptions = useMemo<SelectOption[]>(() => {
118+
return outputOptions.filter((option) => option[0] !== 'pdf');
119+
}, [outputOptions]);
113120

114121
const { mutateAsync: exportRoom } = useRoomExportMutation();
115122
const { mutateAsync: exportAndDownload } = useDownloadExportMutation();
@@ -201,7 +208,7 @@ const ExportMessages = () => {
201208
const subjectField = useId();
202209

203210
return (
204-
<ContextualbarDialog>
211+
<ContextualbarDialog aria-labelledby={`${formId}-title`}>
205212
<ContextualbarHeader>
206213
<ContextualbarIcon name='mail' />
207214
<ContextualbarTitle id={`${formId}-title`}>{t('Export_Messages')}</ContextualbarTitle>
@@ -224,7 +231,14 @@ const ExportMessages = () => {
224231
name='type'
225232
control={control}
226233
render={({ field }) => (
227-
<Select id={methodField} {...field} placeholder={t('Type')} disabled={isE2ERoom} options={exportOptions} />
234+
<Select
235+
id={methodField}
236+
data-testid='export-messages-method'
237+
{...field}
238+
placeholder={t('Type')}
239+
disabled={isE2ERoom}
240+
options={exportOptions}
241+
/>
228242
)}
229243
/>
230244
</FieldRow>
@@ -235,15 +249,28 @@ const ExportMessages = () => {
235249
<Controller
236250
name='format'
237251
control={control}
238-
render={({ field }) => (
239-
<Select
240-
{...field}
241-
id={formatField}
242-
disabled={type === 'email'}
243-
placeholder={t('Format')}
244-
options={type === 'download' ? downloadOutputOptions : outputOptions}
245-
/>
246-
)}
252+
render={({ field }) => {
253+
let options: SelectOption[];
254+
255+
if (type === 'download') {
256+
options = downloadOutputOptions;
257+
} else if (type === 'file') {
258+
options = fileOutputOptions;
259+
} else {
260+
options = outputOptions;
261+
}
262+
263+
return (
264+
<Select
265+
{...field}
266+
id={formatField}
267+
data-testid='export-messages-output-format'
268+
disabled={type === 'email'}
269+
placeholder={t('Format')}
270+
options={options}
271+
/>
272+
);
273+
}}
247274
/>
248275
</FieldRow>
249276
</Field>

apps/meteor/tests/e2e/e2e-encryption.spec.ts

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ import {
1616
SaveE2EEPasswordBanner,
1717
SaveE2EEPasswordModal,
1818
} from './page-objects/fragments/e2ee';
19+
import { ExportMessagesTab } from './page-objects/fragments/export-messages-tab';
1920
import { FileUploadModal } from './page-objects/fragments/file-upload-modal';
20-
import { HomeFlextabExportMessages } from './page-objects/fragments/home-flextab-exportMessages';
2121
import { LoginPage } from './page-objects/login';
2222
import { test, expect } from './utils/test';
2323

@@ -272,7 +272,7 @@ test.describe('basic features', () => {
272272
test('should display only the download file method when exporting messages in an e2ee room', async ({ page }) => {
273273
const sidenav = new HomeSidenav(page);
274274
const encryptedRoomPage = new EncryptedRoomPage(page);
275-
const exportMessagesTab = new HomeFlextabExportMessages(page);
275+
const exportMessagesTab = new ExportMessagesTab(page);
276276

277277
const channelName = faker.string.uuid();
278278

@@ -281,14 +281,14 @@ test.describe('basic features', () => {
281281
await expect(encryptedRoomPage.encryptedRoomHeaderIcon).toBeVisible();
282282

283283
await encryptedRoomPage.showExportMessagesTab();
284-
await expect(exportMessagesTab.downloadFileMethod).toBeVisible();
285-
await expect(exportMessagesTab.sendEmailMethod).not.toBeVisible();
284+
await expect(exportMessagesTab.method).toContainClass('disabled'); // FIXME: looks like the component have an a11y issue
285+
await expect(exportMessagesTab.method).toHaveAccessibleName('Download file');
286286
});
287287

288288
test('should allow exporting messages as PDF in an encrypted room', async ({ page }) => {
289289
const sidenav = new HomeSidenav(page);
290290
const encryptedRoomPage = new EncryptedRoomPage(page);
291-
const exportMessagesTab = new HomeFlextabExportMessages(page);
291+
const exportMessagesTab = new ExportMessagesTab(page);
292292

293293
const channelName = faker.string.uuid();
294294

@@ -298,19 +298,17 @@ test.describe('basic features', () => {
298298

299299
await encryptedRoomPage.sendMessage('This is a message to export as PDF.');
300300
await encryptedRoomPage.showExportMessagesTab();
301-
await expect(exportMessagesTab.downloadFileMethod).toBeVisible();
301+
await expect(exportMessagesTab.method).toHaveAccessibleName('Download file');
302302

303303
// Select Output format as PDF
304-
await exportMessagesTab.outputFormat.click();
305-
await exportMessagesTab.getMethodByName('PDF').click();
304+
await exportMessagesTab.setOutputFormat('PDF');
306305

307306
// select messages to be exported
308-
await exportMessagesTab.btnSelectMessages.click();
307+
await exportMessagesTab.selectAllMessages();
309308

310309
// Wait for download event and match format
311-
const [download] = await Promise.all([page.waitForEvent('download'), exportMessagesTab.btnDownloadExportMessages.click()]);
312-
const suggestedFilename = download.suggestedFilename();
313-
expect(suggestedFilename).toMatch(/\.pdf$/);
310+
const download = await exportMessagesTab.downloadMessages();
311+
expect(download.suggestedFilename()).toMatch(/\.pdf$/);
314312
});
315313
});
316314

apps/meteor/tests/e2e/export-messages.spec.ts

Lines changed: 46 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { Users } from './fixtures/userStates';
22
import { HomeChannel, Utils } from './page-objects';
3+
import { ExportMessagesTab } from './page-objects/fragments/export-messages-tab';
34
import { createTargetChannel } from './utils';
45
import { test, expect } from './utils/test';
56

@@ -21,19 +22,51 @@ test.describe.serial('export-messages', () => {
2122
await page.goto('/home');
2223
});
2324

24-
test('should all export methods be available in targetChannel', async () => {
25+
test('should all export methods be available in targetChannel', async ({ page }) => {
26+
const exportMessagesTab = new ExportMessagesTab(page);
27+
2528
await poHomeChannel.sidenav.openChat(targetChannel);
2629
await poHomeChannel.tabs.kebab.click({ force: true });
2730
await poHomeChannel.tabs.btnExportMessages.click();
28-
await expect(poHomeChannel.tabs.exportMessages.sendEmailMethod).not.toBeDisabled();
2931

30-
await poHomeChannel.tabs.exportMessages.sendEmailMethod.click();
31-
await expect(poHomeChannel.tabs.exportMessages.getMethodByName('Send email')).toBeVisible();
32-
await expect(poHomeChannel.tabs.exportMessages.getMethodByName('Send file via email')).toBeVisible();
33-
await expect(poHomeChannel.tabs.exportMessages.getMethodByName('Download file')).toBeVisible();
32+
await exportMessagesTab.exposeMethods();
33+
await expect(exportMessagesTab.getMethodOptionByName('Send email')).toBeVisible();
34+
await expect(exportMessagesTab.getMethodOptionByName('Send file via email')).toBeVisible();
35+
await expect(exportMessagesTab.getMethodOptionByName('Download file')).toBeVisible();
3436
});
3537

36-
test('should display an error when trying to send email without filling to users or to additional emails', async () => {
38+
test('should display export output format correctly depending on the selected method', async ({ page }) => {
39+
const exportMessagesTab = new ExportMessagesTab(page);
40+
41+
await poHomeChannel.sidenav.openChat(targetChannel);
42+
await poHomeChannel.tabs.kebab.click({ force: true });
43+
await poHomeChannel.tabs.btnExportMessages.click();
44+
45+
// TODO: Fix the base component to have a disabled statement and not only a class attribute
46+
// Here we are checking for a button because the internal select element is not accessible
47+
// and the higher component that is a button doesn't appear as disabled.
48+
await expect(exportMessagesTab.outputFormat).toContainClass('disabled');
49+
50+
await exportMessagesTab.setMethod('Send file via email');
51+
52+
await exportMessagesTab.exposeOutputFormats();
53+
await expect(exportMessagesTab.getOutputFormatOptionByName('html')).toBeVisible();
54+
await expect(exportMessagesTab.getOutputFormatOptionByName('json')).toBeVisible();
55+
await expect(exportMessagesTab.getOutputFormatOptionByName('pdf')).not.toBeVisible();
56+
57+
await exportMessagesTab.setOutputFormat('html');
58+
59+
await exportMessagesTab.setMethod('Download file');
60+
61+
await exportMessagesTab.exposeOutputFormats();
62+
await expect(exportMessagesTab.getOutputFormatOptionByName('html')).not.toBeVisible();
63+
await expect(exportMessagesTab.getOutputFormatOptionByName('json')).toBeVisible();
64+
await expect(exportMessagesTab.getOutputFormatOptionByName('pdf')).toBeVisible();
65+
});
66+
67+
test('should display an error when trying to send email without filling to users or to additional emails', async ({ page }) => {
68+
const exportMessagesTab = new ExportMessagesTab(page);
69+
3770
await poHomeChannel.sidenav.openChat(targetChannel);
3871
await poHomeChannel.content.sendMessage('hello world');
3972
await poHomeChannel.tabs.kebab.click({ force: true });
@@ -42,20 +75,22 @@ test.describe.serial('export-messages', () => {
4275
await expect(poHomeChannel.btnContextualbarClose).toBeVisible();
4376

4477
await poHomeChannel.content.getMessageByText('hello world').click();
45-
await poHomeChannel.tabs.exportMessages.btnSend.click();
78+
await exportMessagesTab.send();
4679

4780
await expect(
4881
poUtils.getAlertByText('You must select one or more users or provide one or more email addresses, separated by commas'),
4982
).toBeVisible();
5083
});
5184

52-
test('should display an error when trying to send email without selecting any message', async () => {
85+
test('should display an error when trying to send email without selecting any message', async ({ page }) => {
86+
const exportMessagesTab = new ExportMessagesTab(page);
87+
5388
await poHomeChannel.sidenav.openChat(targetChannel);
5489
await poHomeChannel.tabs.kebab.click({ force: true });
5590
await poHomeChannel.tabs.btnExportMessages.click();
5691

57-
await poHomeChannel.tabs.exportMessages.textboxAdditionalEmails.fill('mail@mail.com');
58-
await poHomeChannel.tabs.exportMessages.btnSend.click();
92+
await exportMessagesTab.setAdditionalEmail('mail@mail.com');
93+
await exportMessagesTab.send();
5994

6095
await expect(poUtils.getAlertByText(`You haven't selected any messages`)).toBeVisible();
6196
});
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
import type { Locator, Page } from '@playwright/test';
2+
3+
export class ExportMessagesTab {
4+
private readonly root: Locator;
5+
6+
constructor(page: Page) {
7+
this.root = page.getByRole('dialog', { name: 'Export Messages' });
8+
}
9+
10+
async exposeMethods() {
11+
await this.method.click();
12+
}
13+
14+
async setMethod(optionName: string) {
15+
await this.exposeMethods();
16+
await this.root.page().getByRole('option', { name: optionName }).click();
17+
}
18+
19+
async exposeOutputFormats() {
20+
await this.outputFormat.click();
21+
}
22+
23+
async setOutputFormat(optionName: string) {
24+
await this.exposeOutputFormats();
25+
await this.root.page().getByRole('option', { name: optionName }).click();
26+
}
27+
28+
getMethodOptionByName(name: string) {
29+
return this.root.page().getByRole('option', { name });
30+
}
31+
32+
getOutputFormatOptionByName(name: string) {
33+
return this.root.page().getByRole('option', { name });
34+
}
35+
36+
async selectAllMessages() {
37+
await this.root
38+
.page()
39+
.getByRole('button', { name: /Select \d+ messages/ })
40+
.click();
41+
}
42+
43+
async downloadMessages() {
44+
const [download] = await Promise.all([this.root.page().waitForEvent('download'), this.downloadButton.click()]);
45+
return download;
46+
}
47+
48+
async send() {
49+
await this.sendButton.click();
50+
}
51+
52+
async setAdditionalEmail(email: string) {
53+
await this.toAdditionalEmailsInput.fill(email);
54+
}
55+
56+
get method() {
57+
return this.root.getByTestId('export-messages-method');
58+
}
59+
60+
get outputFormat() {
61+
return this.root.page().getByTestId('export-messages-output-format');
62+
}
63+
64+
get toAdditionalEmailsInput() {
65+
return this.root.getByRole('textbox', { name: 'To additional emails' });
66+
}
67+
68+
get downloadButton() {
69+
return this.root.getByRole('button', { name: 'Download', exact: true });
70+
}
71+
72+
get sendButton() {
73+
return this.root.getByRole('button', { name: 'Send', exact: true });
74+
}
75+
}

apps/meteor/tests/e2e/page-objects/fragments/home-flextab-exportMessages.ts

Lines changed: 0 additions & 45 deletions
This file was deleted.

apps/meteor/tests/e2e/page-objects/fragments/home-flextab.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import type { Locator, Page } from '@playwright/test';
22

3+
import { ExportMessagesTab } from './export-messages-tab';
34
import { HomeFlextabChannels } from './home-flextab-channels';
4-
import { HomeFlextabExportMessages } from './home-flextab-exportMessages';
55
import { HomeFlextabMembers } from './home-flextab-members';
66
import { HomeFlextabNotificationPreferences } from './home-flextab-notificationPreferences';
77
import { HomeFlextabOtr } from './home-flextab-otr';
@@ -21,7 +21,7 @@ export class HomeFlextab {
2121

2222
readonly otr: HomeFlextabOtr;
2323

24-
readonly exportMessages: HomeFlextabExportMessages;
24+
readonly exportMessages: ExportMessagesTab;
2525

2626
readonly pruneMessages: HomeFlextabPruneMessages;
2727

@@ -32,7 +32,7 @@ export class HomeFlextab {
3232
this.channels = new HomeFlextabChannels(page);
3333
this.notificationPreferences = new HomeFlextabNotificationPreferences(page);
3434
this.otr = new HomeFlextabOtr(page);
35-
this.exportMessages = new HomeFlextabExportMessages(page);
35+
this.exportMessages = new ExportMessagesTab(page);
3636
this.pruneMessages = new HomeFlextabPruneMessages(page);
3737
}
3838

apps/meteor/tests/e2e/page-objects/login.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ export class LoginPage {
1010
constructor(protected readonly page: Page) {}
1111

1212
get loginButton() {
13-
return this.page.getByRole('button', { name: 'Login' });
13+
return this.page.getByRole('button', { name: 'Login', exact: true });
1414
}
1515

1616
/** @deprecated ideally the previous action should ensure the user is logged out and we should just assume to be at the login page */

0 commit comments

Comments
 (0)