mirror of
https://github.com/RocketChat/Rocket.Chat.git
synced 2025-12-28 06:47:25 +00:00
fix: User custom status text being overwritten (#36601)
Co-authored-by: Diego Sampaio <chinello@gmail.com>
This commit is contained in:
parent
fbf6c08c3c
commit
a27efe9da9
5
.changeset/seven-donuts-confess.md
Normal file
5
.changeset/seven-donuts-confess.md
Normal file
@ -0,0 +1,5 @@
|
||||
---
|
||||
'@rocket.chat/meteor': patch
|
||||
---
|
||||
|
||||
Fixes an issue where user custom status text is being overwritten, causing it not being updated in real time
|
||||
@ -1317,10 +1317,14 @@ API.v1.addRoute(
|
||||
return API.v1.forbidden();
|
||||
}
|
||||
|
||||
const { _id, username, roles, name } = user;
|
||||
let { statusText } = user;
|
||||
|
||||
// TODO refactor to not update the user twice (one inside of `setStatusText` and then later just the status + statusDefault)
|
||||
|
||||
if (this.bodyParams.message || this.bodyParams.message === '') {
|
||||
await setStatusText(user._id, this.bodyParams.message);
|
||||
statusText = this.bodyParams.message;
|
||||
}
|
||||
if (this.bodyParams.status) {
|
||||
const validStatus = ['online', 'away', 'offline', 'busy'];
|
||||
@ -1343,7 +1347,6 @@ API.v1.addRoute(
|
||||
},
|
||||
);
|
||||
|
||||
const { _id, username, statusText, roles, name } = user;
|
||||
void api.broadcast('presence.status', {
|
||||
user: { status, _id, username, statusText, roles, name },
|
||||
previousStatus: user.status,
|
||||
|
||||
@ -21,7 +21,7 @@ import {
|
||||
import { useLocalStorage, useEffectEvent } from '@rocket.chat/fuselage-hooks';
|
||||
import { useToastMessageDispatch, useSetting, useTranslation, useEndpoint } from '@rocket.chat/ui-contexts';
|
||||
import type { ReactElement, ChangeEvent, ComponentProps, FormEvent } from 'react';
|
||||
import { useState, useCallback } from 'react';
|
||||
import { useState, useCallback, useId } from 'react';
|
||||
|
||||
import UserStatusMenu from '../../components/UserStatusMenu';
|
||||
import { USER_STATUS_TEXT_MAX_LENGTH } from '../../lib/constants';
|
||||
@ -39,6 +39,7 @@ const EditStatusModal = ({ onClose, userStatus, userStatusText }: EditStatusModa
|
||||
const initialStatusText = customStatus || userStatusText;
|
||||
|
||||
const t = useTranslation();
|
||||
const modalId = useId();
|
||||
const [statusText, setStatusText] = useState(initialStatusText);
|
||||
const [statusType, setStatusType] = useState(userStatus);
|
||||
const [statusTextError, setStatusTextError] = useState<string | undefined>();
|
||||
@ -71,6 +72,7 @@ const EditStatusModal = ({ onClose, userStatus, userStatusText }: EditStatusModa
|
||||
|
||||
return (
|
||||
<Modal
|
||||
aria-labelledby={`${modalId}-title`}
|
||||
wrapperFunction={(props: ComponentProps<typeof Box>) => (
|
||||
<Box
|
||||
is='form'
|
||||
@ -84,15 +86,17 @@ const EditStatusModal = ({ onClose, userStatus, userStatusText }: EditStatusModa
|
||||
>
|
||||
<ModalHeader>
|
||||
<ModalIcon name='info' />
|
||||
<ModalTitle>{t('Edit_Status')}</ModalTitle>
|
||||
<ModalTitle id={`${modalId}-title`}>{t('Edit_Status')}</ModalTitle>
|
||||
<ModalClose onClick={onClose} />
|
||||
</ModalHeader>
|
||||
<ModalContent fontScale='p2'>
|
||||
<FieldGroup>
|
||||
<Field>
|
||||
<FieldLabel>{t('StatusMessage')}</FieldLabel>
|
||||
<FieldLabel htmlFor={`${modalId}-status-message`}>{t('StatusMessage')}</FieldLabel>
|
||||
<FieldRow>
|
||||
<TextInput
|
||||
id={`${modalId}-status-message`}
|
||||
aria-label={t('StatusMessage')}
|
||||
error={statusTextError}
|
||||
disabled={!allowUserStatusMessageChange}
|
||||
flexGrow={1}
|
||||
|
||||
@ -21,7 +21,11 @@ const UserMenuHeader = ({ user }: { user: IUser }) => {
|
||||
<Box mis={4} display='flex' overflow='hidden' flexDirection='column' fontScale='p2' mb='neg-x4' flexGrow={1} flexShrink={1}>
|
||||
<Box withTruncatedText w='full' display='flex' alignItems='center' flexDirection='row'>
|
||||
<Margins inline={4}>
|
||||
<UserStatus status={presenceDisabled ? 'disabled' : user.status} />
|
||||
<UserStatus
|
||||
role='status'
|
||||
aria-label={presenceDisabled ? t('user_status_disabled') : t(user?.status ?? 'offline')}
|
||||
status={presenceDisabled ? 'disabled' : user.status}
|
||||
/>
|
||||
<Box is='span' withTruncatedText display='inline-block' fontWeight='700'>
|
||||
{displayName}
|
||||
</Box>
|
||||
|
||||
@ -1056,7 +1056,7 @@ test.describe.serial('e2ee room setup', () => {
|
||||
await expect(poHomeChannel.content.lastUserMessageBody).toHaveText('hello world');
|
||||
await expect(poHomeChannel.content.lastUserMessage.locator('.rcx-icon--name-key')).toBeVisible();
|
||||
|
||||
await poHomeChannel.sidenav.userProfileMenu.click();
|
||||
await poHomeChannel.sidenav.btnUserProfileMenu.click();
|
||||
await poHomeChannel.sidenav.accountProfileOption.click();
|
||||
|
||||
await page.locator('role=navigation >> a:has-text("Security")').click();
|
||||
|
||||
@ -46,10 +46,18 @@ export class HomeSidenav {
|
||||
return this.page.locator('role=search >> role=searchbox').first();
|
||||
}
|
||||
|
||||
get userProfileMenu(): Locator {
|
||||
get btnUserProfileMenu(): Locator {
|
||||
return this.page.getByRole('button', { name: 'User menu', exact: true });
|
||||
}
|
||||
|
||||
get userProfileMenu(): Locator {
|
||||
return this.page.getByRole('menu', { name: 'User menu' });
|
||||
}
|
||||
|
||||
getUserProfileMenuOption(name: string): Locator {
|
||||
return this.userProfileMenu.getByRole('menuitemcheckbox', { name });
|
||||
}
|
||||
|
||||
get sidebarChannelsList(): Locator {
|
||||
return this.page.getByRole('list', { name: 'Channels' });
|
||||
}
|
||||
@ -152,12 +160,12 @@ export class HomeSidenav {
|
||||
}
|
||||
|
||||
async logout(): Promise<void> {
|
||||
await this.userProfileMenu.click();
|
||||
await this.btnUserProfileMenu.click();
|
||||
await this.page.locator('//*[contains(@class, "rcx-option__content") and contains(text(), "Logout")]').click();
|
||||
}
|
||||
|
||||
async switchStatus(status: 'offline' | 'online'): Promise<void> {
|
||||
await this.userProfileMenu.click();
|
||||
await this.btnUserProfileMenu.click();
|
||||
await this.page.locator(`role=menuitemcheckbox[name="${status}"]`).click();
|
||||
}
|
||||
|
||||
|
||||
@ -19,4 +19,5 @@ export * from './omnichannel-settings';
|
||||
export * from './omnichannel-business-hours';
|
||||
export * from './omnichannel-tags';
|
||||
export * from './utils';
|
||||
export * from './modal';
|
||||
export * from './marketplace';
|
||||
|
||||
@ -7,6 +7,10 @@ export class Modal {
|
||||
this.page = page;
|
||||
}
|
||||
|
||||
getModalByName(name: string): Locator {
|
||||
return this.page.getByRole('dialog', { name });
|
||||
}
|
||||
|
||||
get textInput(): Locator {
|
||||
return this.page.locator('[name="modal_input"]');
|
||||
}
|
||||
|
||||
@ -1,14 +1,17 @@
|
||||
import { DEFAULT_USER_CREDENTIALS, IS_EE } from './config/constants';
|
||||
import { Users } from './fixtures/userStates';
|
||||
import { Registration } from './page-objects';
|
||||
import { Registration, HomeChannel } from './page-objects';
|
||||
import { Modal } from './page-objects/modal';
|
||||
import { setSettingValueById } from './utils/setSettingValueById';
|
||||
import { test, expect } from './utils/test';
|
||||
|
||||
test.describe.serial('Presence', () => {
|
||||
let poRegistration: Registration;
|
||||
let poHomeChannel: HomeChannel;
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
poRegistration = new Registration(page);
|
||||
poHomeChannel = new HomeChannel(page);
|
||||
|
||||
await page.goto('/home');
|
||||
});
|
||||
@ -22,12 +25,44 @@ test.describe.serial('Presence', () => {
|
||||
});
|
||||
|
||||
test.describe('Login using default settings', () => {
|
||||
test('expect user to be online after log in', async ({ page }) => {
|
||||
await poRegistration.username.type('user1');
|
||||
await poRegistration.inputPassword.type(DEFAULT_USER_CREDENTIALS.password);
|
||||
test('should user be online after log in', async () => {
|
||||
await poRegistration.username.fill('user1');
|
||||
await poRegistration.inputPassword.fill(DEFAULT_USER_CREDENTIALS.password);
|
||||
await poRegistration.btnLogin.click();
|
||||
|
||||
await expect(page.getByRole('button', { name: 'User menu' }).locator('.rcx-status-bullet--online')).toBeVisible();
|
||||
await expect(poHomeChannel.sidenav.btnUserProfileMenu).toBeVisible();
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('Custom status', () => {
|
||||
test.use({ storageState: Users.admin.state });
|
||||
|
||||
test('should user custom status be reactive', async ({ browser }) => {
|
||||
await test.step('user1 custom status should be empty', async () => {
|
||||
await poHomeChannel.sidenav.openChat('user1');
|
||||
|
||||
await expect(poHomeChannel.content.channelHeader).not.toContainText('new status');
|
||||
});
|
||||
|
||||
await test.step('update user1 custom status', async () => {
|
||||
const user1Page = await browser.newPage({ storageState: Users.user1.state });
|
||||
await user1Page.goto('/home');
|
||||
const user1Channel = new HomeChannel(user1Page);
|
||||
const user1Modal = new Modal(user1Page);
|
||||
|
||||
await user1Channel.sidenav.btnUserProfileMenu.click();
|
||||
await user1Channel.sidenav.getUserProfileMenuOption('Custom Status').click();
|
||||
await user1Modal.getModalByName('Edit Status').getByRole('textbox', { name: 'Status message' }).fill('new status');
|
||||
await user1Modal.getModalByName('Edit Status').getByRole('button', { name: 'Save' }).click();
|
||||
|
||||
await user1Page.close();
|
||||
});
|
||||
|
||||
await test.step('should user1 custom status be updated', async () => {
|
||||
await poHomeChannel.sidenav.openChat('user1');
|
||||
|
||||
await expect(poHomeChannel.content.channelHeader).toContainText('new status');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@ -23,7 +23,7 @@ test.describe.serial('sidebar', () => {
|
||||
});
|
||||
|
||||
test('should navigate on sidebar toolbar using arrow keys', async ({ page }) => {
|
||||
await poHomeChannel.sidenav.userProfileMenu.focus();
|
||||
await poHomeChannel.sidenav.btnUserProfileMenu.focus();
|
||||
await page.keyboard.press('Tab');
|
||||
await page.keyboard.press('ArrowRight');
|
||||
|
||||
|
||||
@ -68,7 +68,7 @@ test.describe('User - Password change required', () => {
|
||||
});
|
||||
|
||||
await test.step('verify user is properly logged in', async () => {
|
||||
await expect(poSidenav.userProfileMenu).toBeVisible();
|
||||
await expect(poSidenav.btnUserProfileMenu).toBeVisible();
|
||||
await expect(poSidenav.sidebarChannelsList).toBeVisible();
|
||||
});
|
||||
});
|
||||
@ -159,7 +159,7 @@ test.describe('User - Password change not required', () => {
|
||||
|
||||
await test.step('verify user is properly logged in', async () => {
|
||||
await page.waitForURL('/home');
|
||||
await expect(poSidenav.userProfileMenu).toBeVisible();
|
||||
await expect(poSidenav.btnUserProfileMenu).toBeVisible();
|
||||
await expect(poSidenav.sidebarChannelsList).toBeVisible();
|
||||
});
|
||||
});
|
||||
|
||||
Loading…
Reference in New Issue
Block a user