fix: update room on the rooms list view after local search and quote showing with leading empty space on the rooms list view (#5064)
* fix: quote showing with leading empty space on the rooms list view * add unit test for previewFormatText * minor tweak * add e2e test to see the msg quote * fix room item re-render after local search * markdown preview testID can be received or default * update storyshot roomheader * minor tweak * minor tweak * fix flaky test * refactor searchRoom to avoid flaky tests
This commit is contained in:
parent
1ee2aa889b
commit
aabbc77479
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -68,7 +68,6 @@ const LastMessage = React.memo(({ lastMessage, type, showLastMessage, username,
|
|||
})}
|
||||
style={[styles.markdownText, { color: alert ? colors.bodyText : colors.auxiliaryText }]}
|
||||
numberOfLines={2}
|
||||
testID='room-item-last-message'
|
||||
/>
|
||||
);
|
||||
}, arePropsEqual);
|
||||
|
|
|
@ -101,7 +101,7 @@ const RoomItem = ({
|
|||
{autoJoin ? <Tag testID='auto-join-tag' name={I18n.t('Auto-join')} /> : null}
|
||||
<UpdatedAt date={date} hideUnreadStatus={hideUnreadStatus} alert={alert} />
|
||||
</View>
|
||||
<View style={styles.row}>
|
||||
<View style={styles.row} testID='room-item-last-message-container'>
|
||||
<LastMessage
|
||||
lastMessage={lastMessage}
|
||||
type={type}
|
||||
|
|
|
@ -1,13 +1,10 @@
|
|||
import React from 'react';
|
||||
import { Text, TextStyle } from 'react-native';
|
||||
import removeMarkdown from 'remove-markdown';
|
||||
|
||||
import shortnameToUnicode from '../../lib/methods/helpers/shortnameToUnicode';
|
||||
import { themes } from '../../lib/constants';
|
||||
import { formatText } from './formatText';
|
||||
import { useTheme } from '../../theme';
|
||||
import styles from './styles';
|
||||
import { formatHyperlink } from './formatHyperlink';
|
||||
import { previewFormatText } from './previewFormatText';
|
||||
|
||||
interface IMarkdownPreview {
|
||||
msg?: string;
|
||||
|
@ -16,27 +13,20 @@ interface IMarkdownPreview {
|
|||
style?: TextStyle[];
|
||||
}
|
||||
|
||||
const MarkdownPreview = ({ msg, numberOfLines = 1, testID, style = [] }: IMarkdownPreview) => {
|
||||
const MarkdownPreview = ({ msg, numberOfLines = 1, style = [], testID }: IMarkdownPreview) => {
|
||||
const { theme } = useTheme();
|
||||
|
||||
if (!msg) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let m = formatText(msg);
|
||||
m = formatHyperlink(m);
|
||||
m = shortnameToUnicode(m);
|
||||
// Removes sequential empty spaces
|
||||
m = m.replace(/\s+/g, ' ');
|
||||
m = removeMarkdown(m);
|
||||
m = m.replace(/\n+/g, ' ');
|
||||
const m = previewFormatText(msg);
|
||||
return (
|
||||
<Text
|
||||
accessibilityLabel={m}
|
||||
style={[styles.text, { color: themes[theme].bodyText }, ...style]}
|
||||
numberOfLines={numberOfLines}
|
||||
testID={testID}
|
||||
>
|
||||
testID={testID || `markdown-preview-${m}`}>
|
||||
{m}
|
||||
</Text>
|
||||
);
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
import { previewFormatText } from './previewFormatText';
|
||||
|
||||
describe('Format preview message', () => {
|
||||
test('empty to be empty', () => {
|
||||
expect(previewFormatText('')).toBe('');
|
||||
});
|
||||
test('A123 to be A123', () => {
|
||||
expect(previewFormatText('A123')).toBe('A123');
|
||||
});
|
||||
test('Format <http://link|Text> to be Text', () => {
|
||||
expect(previewFormatText('<http://link|Text>')).toBe('Text');
|
||||
});
|
||||
test('Format "[ ](https://open.rocket.chat/) Test" to be Test', () => {
|
||||
expect(previewFormatText('[ ](https://open.rocket.chat/) Test')).toEqual('Test');
|
||||
});
|
||||
test('Format "[Open](https://open.rocket.chat/) Test" to be Test', () => {
|
||||
expect(previewFormatText('[Open](https://open.rocket.chat/) Test')).toBe('Open Test');
|
||||
});
|
||||
test('render test (arabic)', () => {
|
||||
expect(previewFormatText('[ ](https://open.rocket.chat/) اختبا')).toBe('اختبا');
|
||||
});
|
||||
test('render test (russian)', () => {
|
||||
expect(previewFormatText('[ ](https://open.rocket.chat/) тест123')).toBe('тест123');
|
||||
});
|
||||
test('Format a quote message as last message "You: [ ](https://open.rocket.chat/group/channel?msg=nrTDSw96IhtF3iN4K) \nTest"', () => {
|
||||
expect(previewFormatText('You: [ ](https://open.rocket.chat/group/channel?msg=nrTDSw96IhtF3iN4K) \nTest')).toBe('You: Test');
|
||||
});
|
||||
});
|
|
@ -0,0 +1,16 @@
|
|||
import removeMarkdown from 'remove-markdown';
|
||||
|
||||
import shortnameToUnicode from '../../lib/methods/helpers/shortnameToUnicode';
|
||||
import { formatText } from './formatText';
|
||||
import { formatHyperlink } from './formatHyperlink';
|
||||
|
||||
export const previewFormatText = (msg: string) => {
|
||||
let m = formatText(msg);
|
||||
m = formatHyperlink(m);
|
||||
m = shortnameToUnicode(m);
|
||||
m = removeMarkdown(m);
|
||||
// Removes sequential empty spaces
|
||||
m = m.replace(/\s+/g, ' ');
|
||||
m = m.replace(/\n+/g, ' ');
|
||||
return m;
|
||||
};
|
|
@ -154,7 +154,8 @@ const getItemLayout = (data: ISubscription[] | null | undefined, index: number,
|
|||
offset: height * index,
|
||||
index
|
||||
});
|
||||
const keyExtractor = (item: ISubscription) => item.rid;
|
||||
// isSearching is needed to trigger RoomItem's useEffect properly after searching
|
||||
const keyExtractor = (item: ISubscription, isSearching = false) => `${item.rid}-${isSearching}`;
|
||||
|
||||
class RoomsListView extends React.Component<IRoomsListViewProps, IRoomsListViewState> {
|
||||
private animated: boolean;
|
||||
|
@ -899,7 +900,7 @@ class RoomsListView extends React.Component<IRoomsListViewProps, IRoomsListViewS
|
|||
ref={this.getScrollRef}
|
||||
data={searching ? search : chats}
|
||||
extraData={searching ? search : chats}
|
||||
keyExtractor={keyExtractor}
|
||||
keyExtractor={item => keyExtractor(item, searching)}
|
||||
style={[styles.list, { backgroundColor: themes[theme].backgroundColor }]}
|
||||
renderItem={this.renderItem}
|
||||
ListHeaderComponent={this.renderListHeader}
|
||||
|
|
|
@ -118,16 +118,21 @@ async function tapBack() {
|
|||
await sleep(300); // Wait for animation to finish
|
||||
}
|
||||
|
||||
async function searchRoom(room: string, roomTestID?: string) {
|
||||
async function searchRoom(
|
||||
room: string,
|
||||
nativeElementAction: keyof Pick<Detox.NativeElementActions, 'typeText' | 'replaceText'> = 'typeText',
|
||||
roomTestID?: string
|
||||
) {
|
||||
await waitFor(element(by.id('rooms-list-view')))
|
||||
.toBeVisible()
|
||||
.withTimeout(30000);
|
||||
await tapAndWaitFor(element(by.id('rooms-list-view-search')), element(by.id('rooms-list-view-search-input')), 5000);
|
||||
// to fix the replace text for iOS and type non-ASCII on Android
|
||||
const roomFirstSlice = room.slice(0, room.length - 2);
|
||||
await element(by.id('rooms-list-view-search-input')).replaceText(roomFirstSlice);
|
||||
if (nativeElementAction === 'replaceText') {
|
||||
// trigger the input's onChangeText
|
||||
await element(by.id('rooms-list-view-search-input')).typeText(' ');
|
||||
}
|
||||
await element(by.id('rooms-list-view-search-input'))[nativeElementAction](room);
|
||||
await sleep(500);
|
||||
await element(by.id('rooms-list-view-search-input')).replaceText(room);
|
||||
await sleep(500);
|
||||
await waitFor(element(by.id(roomTestID || `rooms-list-view-item-${room}`)))
|
||||
.toBeVisible()
|
||||
|
|
|
@ -73,14 +73,14 @@ describe('Display prefs', () => {
|
|||
it('should appear the last message in RoomList when is Expanded', async () => {
|
||||
await element(by.id('display-pref-view-expanded')).tap();
|
||||
await goToRoomList();
|
||||
await expect(element(by.id('room-item-last-message')).atIndex(0)).toBeVisible();
|
||||
await expect(element(by.id('room-item-last-message-container')).atIndex(0)).toBeVisible();
|
||||
});
|
||||
|
||||
it('should not appear the last message in RoomList when is Condensed', async () => {
|
||||
await goToDisplayPref();
|
||||
await element(by.id('display-pref-view-condensed')).tap();
|
||||
await goToRoomList();
|
||||
await expect(element(by.id('room-item-last-message'))).not.toBeVisible();
|
||||
await expect(element(by.id('room-item-last-message-container'))).not.toBeVisible();
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -313,7 +313,7 @@ describe('Create room screen', () => {
|
|||
.toExist()
|
||||
.withTimeout(60000);
|
||||
await expect(element(by.id(`rooms-list-view-item-${roomName}`))).toExist();
|
||||
await searchRoom(roomNameLower, `rooms-list-view-item-${roomName}`);
|
||||
await searchRoom(roomNameLower, 'replaceText', `rooms-list-view-item-${roomName}`);
|
||||
await element(by.id(`rooms-list-view-item-${roomName}`)).tap();
|
||||
await waitFor(element(by.id('room-view')))
|
||||
.toBeVisible()
|
||||
|
|
|
@ -438,9 +438,10 @@ describe('Room screen', () => {
|
|||
.toExist()
|
||||
.withTimeout(60000);
|
||||
});
|
||||
let quotedMessage = '';
|
||||
it('should quote message', async () => {
|
||||
const quoteMessage = await mockMessage('quote');
|
||||
const quotedMessage = `${quoteMessage}d`;
|
||||
quotedMessage = `${quoteMessage}d`;
|
||||
await tryTapping(element(by[textMatcher](quoteMessage)).atIndex(0), 2000, true);
|
||||
await waitFor(element(by.id('action-sheet')))
|
||||
.toExist()
|
||||
|
@ -460,6 +461,15 @@ describe('Room screen', () => {
|
|||
.toBeVisible()
|
||||
.withTimeout(3000);
|
||||
});
|
||||
it('should back to rooms list view and see the last message correctly and navigate again to room', async () => {
|
||||
const expectedLastMessage = `You: ${quotedMessage}`;
|
||||
await sleep(300);
|
||||
await tapBack();
|
||||
await waitFor(element(by.id(`markdown-preview-${expectedLastMessage}`)))
|
||||
.toBeVisible()
|
||||
.withTimeout(5000);
|
||||
await element(by.id(`markdown-preview-${expectedLastMessage}`)).tap();
|
||||
});
|
||||
|
||||
it('should delete message', async () => {
|
||||
const deleteMessage = await mockMessage('delete');
|
||||
|
|
Loading…
Reference in New Issue