Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
5 changes: 5 additions & 0 deletions .changeset/grumpy-lemons-drum.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@rocket.chat/meteor': patch
---

Fixes prune messages contextual bar not resetting form after submitting.
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ type PruneMessagesProps = {

const PruneMessages = ({ callOutText, validateText, onClickClose, onClickPrune }: PruneMessagesProps): ReactElement => {
const { t } = useTranslation();
const { control, register } = useFormContext();
const { control } = useFormContext();

const inclusiveCheckboxId = useId();
const pinnedCheckboxId = useId();
Expand Down Expand Up @@ -55,31 +55,51 @@ const PruneMessages = ({ callOutText, validateText, onClickClose, onClickPrune }
<Field>
<FieldRow>
<FieldLabel htmlFor={inclusiveCheckboxId}>{t('Inclusive')}</FieldLabel>
<CheckBox id={inclusiveCheckboxId} {...register('inclusive')} />
<Controller
control={control}
name='inclusive'
render={({ field: { value, ...field } }) => <CheckBox id={inclusiveCheckboxId} {...field} checked={value} />}
/>
</FieldRow>
</Field>
<Field>
<FieldRow>
<FieldLabel htmlFor={pinnedCheckboxId}>{t('RetentionPolicy_DoNotPrunePinned')}</FieldLabel>
<CheckBox id={pinnedCheckboxId} {...register('pinned')} />
<Controller
control={control}
name='pinned'
render={({ field: { value, ...field } }) => <CheckBox id={pinnedCheckboxId} {...field} checked={value} />}
/>
</FieldRow>
</Field>
<Field>
<FieldRow>
<FieldLabel htmlFor={discussionCheckboxId}>{t('RetentionPolicy_DoNotPruneDiscussion')}</FieldLabel>
<CheckBox id={discussionCheckboxId} {...register('discussion')} />
<Controller
control={control}
name='discussion'
render={({ field: { value, ...field } }) => <CheckBox id={discussionCheckboxId} {...field} checked={value} />}
/>
</FieldRow>
</Field>
<Field>
<FieldRow>
<FieldLabel htmlFor={threadsCheckboxId}>{t('RetentionPolicy_DoNotPruneThreads')}</FieldLabel>
<CheckBox id={threadsCheckboxId} {...register('threads')} />
<Controller
control={control}
name='threads'
render={({ field: { value, ...field } }) => <CheckBox id={threadsCheckboxId} {...field} checked={value} />}
/>
</FieldRow>
</Field>
<Field>
<FieldRow>
<FieldLabel htmlFor={attachedCheckboxId}>{t('Files_only')}</FieldLabel>
<CheckBox id={attachedCheckboxId} {...register('attached')} />
<Controller
control={control}
name='attached'
render={({ field: { value, ...field } }) => <CheckBox id={attachedCheckboxId} {...field} checked={value} />}
/>
</FieldRow>
</Field>
{callOutText && !validateText && <Callout type='warning'>{callOutText}</Callout>}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import type { Locator, Page } from '@playwright/test';

export class HomeFlextabPruneMessages {
private readonly page: Page;

constructor(page: Page) {
this.page = page;
}

private get form(): Locator {
return this.page.getByRole('dialog', { name: 'Prune Messages' });
}

get doNotPrunePinned(): Locator {
return this.form.getByRole('checkbox', { name: 'Do not prune pinned messages', exact: true });
}

get filesOnly(): Locator {
return this.form.getByRole('checkbox', { name: 'Only remove the attached files, keep messages', exact: true });
}

async prune(): Promise<void> {
await this.form.getByRole('button', { name: 'Prune' }).click();
return this.page
.getByRole('dialog', { name: 'Are you sure?', exact: true })
.getByRole('button', { name: 'Yes, prune them!', exact: true })
.click();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { HomeFlextabExportMessages } from './home-flextab-exportMessages';
import { HomeFlextabMembers } from './home-flextab-members';
import { HomeFlextabNotificationPreferences } from './home-flextab-notificationPreferences';
import { HomeFlextabOtr } from './home-flextab-otr';
import { HomeFlextabPruneMessages } from './home-flextab-pruneMessages';
import { HomeFlextabRoom } from './home-flextab-room';

export class HomeFlextab {
Expand All @@ -22,6 +23,8 @@ export class HomeFlextab {

readonly exportMessages: HomeFlextabExportMessages;

readonly pruneMessages: HomeFlextabPruneMessages;

constructor(page: Page) {
this.page = page;
this.members = new HomeFlextabMembers(page);
Expand All @@ -30,6 +33,7 @@ export class HomeFlextab {
this.notificationPreferences = new HomeFlextabNotificationPreferences(page);
this.otr = new HomeFlextabOtr(page);
this.exportMessages = new HomeFlextabExportMessages(page);
this.pruneMessages = new HomeFlextabPruneMessages(page);
}

get btnTabMembers(): Locator {
Expand Down Expand Up @@ -60,6 +64,10 @@ export class HomeFlextab {
return this.page.locator('role=menuitem[name="Export messages"]');
}

get btnPruneMessages(): Locator {
return this.page.getByRole('menuitem', { name: 'Prune Messages' });
}

get btnE2EERoomSetupDisableE2E(): Locator {
return this.page.locator('[data-qa-id=ToolBoxAction-key]');
}
Expand Down
21 changes: 21 additions & 0 deletions apps/meteor/tests/e2e/page-objects/toastBar.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import type { Locator, Page } from '@playwright/test';

export class ToastBar {
private readonly page: Page;

constructor(page: Page) {
this.page = page;
}

get content(): Locator {
return this.page.locator('.rcx-toastbar');
}

get alert(): Locator {
return this.content.getByRole('alert');
}

get dismiss(): Locator {
return this.content.getByRole('button', { name: 'Dismiss alert', exact: true });
}
}
96 changes: 96 additions & 0 deletions apps/meteor/tests/e2e/prune-messages.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import { Users } from './fixtures/userStates';
import { HomeChannel } from './page-objects/home-channel';
import { ToastBar } from './page-objects/toastBar';
import { createTargetChannel, sendTargetChannelMessage } from './utils';
import { test, expect } from './utils/test';

test.use({ storageState: Users.admin.state });

test.describe('prune-messages', () => {
let poHomeChannel: HomeChannel;
let poToastBar: ToastBar;
let targetChannel: string;

test.beforeAll('create target channel', async ({ api }) => {
targetChannel = await createTargetChannel(api, { members: [Users.admin.data.username] });
});

test.afterAll('delete target channel', async ({ api }) => {
expect((await api.post('/channels.delete', { roomName: targetChannel })).status()).toBe(200);
});

test.beforeEach(async ({ page }) => {
poToastBar = new ToastBar(page);
poHomeChannel = new HomeChannel(page);

await page.goto(`/channel/${targetChannel}/clean-history`);
});

test(
'should reset form after pruning messages',
{
tag: '@channel',
annotation: {
type: 'issue',
description: 'https://rocketchat.atlassian.net/browse/CORE-1146',
},
},
async ({ api }) => {
const {
content,
tabs: { pruneMessages },
} = poHomeChannel;
const { alert, dismiss } = poToastBar;

await content.sendFileMessage('any_file.txt');
await content.descriptionInput.fill('a message with a file');
await content.btnModalConfirm.click();
await expect(content.lastMessageFileName).toHaveText('any_file.txt');

await sendTargetChannelMessage(api, targetChannel, {
msg: 'a message without files',
});

await sendTargetChannelMessage(api, targetChannel, {
msg: 'a pinned message without files',
pinned: true,
});

await test.step('prune files only not pinned', async () => {
await pruneMessages.doNotPrunePinned.check({ force: true });
await pruneMessages.filesOnly.check({ force: true });
await pruneMessages.prune();
await expect(alert).toHaveText('1 message pruned');
await dismiss.click();
await expect(pruneMessages.filesOnly, 'Checkbox is reset after success').not.toBeChecked();
await expect(pruneMessages.doNotPrunePinned, 'Checkbox is reset after success').not.toBeChecked();
});

await test.step('prune files only again', async () => {
await pruneMessages.doNotPrunePinned.check({ force: true });
await pruneMessages.filesOnly.check({ force: true });
await pruneMessages.prune();
await expect(alert).toHaveText('No messages found to prune');
await dismiss.click();
await expect(pruneMessages.filesOnly, 'Checkbox retains value after error').toBeChecked();
await expect(pruneMessages.doNotPrunePinned, 'Checkbox retains value after error').toBeChecked();
});

await test.step('uncheck files only', async () => {
await pruneMessages.filesOnly.uncheck({ force: true });
await pruneMessages.prune();
await expect(alert).toHaveText('2 messages pruned');
await dismiss.click();
await expect(pruneMessages.filesOnly, 'Checkbox is reset after success').not.toBeChecked();
});

await test.step('uncheck do not prune pinned', async () => {
await pruneMessages.doNotPrunePinned.uncheck({ force: true });
await pruneMessages.prune();
await expect(alert).toHaveText('1 message pruned');
await dismiss.click();
await expect(content.lastUserMessage).not.toBeVisible();
});
},
);
});
Loading