tests: add draft e2e tests (#5553)

* chore: update detox

* chore: improve mocks

* chore: add testId

* chore: add e2e tests

* add more time

* Fix tests

* fxi tests

* update yarn lock

* fix import

* wip

* test

* Fix deep linking tests

---------

Co-authored-by: Diego Mello <diegolmello@gmail.com>
This commit is contained in:
Gleidson Daniel Silva 2024-02-15 16:41:03 -03:00 committed by GitHub
parent b189f59950
commit 2a1b59cd57
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 237 additions and 23 deletions

View File

@ -340,7 +340,8 @@ export const ComposerInput = memo(
defaultValue=''
multiline
keyboardAppearance={theme === 'light' ? 'light' : 'dark'}
testID={`message-composer-input${tmid ? '-thread' : ''}`}
// eslint-disable-next-line no-nested-ternary
testID={`message-composer-input${tmid ? '-thread' : sharing ? '-share' : ''}`}
/>
);
})

View File

@ -1,6 +1,5 @@
import { Alert } from 'react-native';
import DocumentPicker from 'react-native-document-picker';
import ImagePicker, { ImageOrVideo } from 'react-native-image-crop-picker';
import { IMAGE_PICKER_CONFIG, LIBRARY_PICKER_CONFIG, VIDEO_PICKER_CONFIG } from '../constants';
import { forceJpgExtension } from '../helpers';
@ -12,6 +11,7 @@ import { getThreadById } from '../../../lib/database/services/Thread';
import Navigation from '../../../lib/navigation/appNavigation';
import { useAppSelector } from '../../../lib/hooks';
import { useRoomContext } from '../../../views/RoomView/context';
import ImagePicker, { ImageOrVideo } from '../../../lib/methods/helpers/ImagePicker/ImagePicker';
export const useChooseMedia = ({
rid,

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,5 @@
import ImagePicker, { Image as ImageInterface, ImageOrVideo as ImageOrVideoType } from 'react-native-image-crop-picker';
export type Image = ImageInterface;
export type ImageOrVideo = ImageOrVideoType;
export default ImagePicker;

View File

@ -25,7 +25,7 @@ import { IAvatar } from '../../definitions';
import AvatarSuggestion from './AvatarSuggestion';
import log from '../../lib/methods/helpers/log';
import { changeRoomsAvatar, changeUserAvatar, resetUserAvatar } from './submitServices';
import ImagePicker, { Image } from './ImagePicker';
import ImagePicker, { Image } from '../../lib/methods/helpers/ImagePicker/ImagePicker';
enum AvatarStateActions {
CHANGE_AVATAR = 'CHANGE_AVATAR',

View File

@ -126,7 +126,7 @@ class ShareView extends Component<IShareViewProps, IShareViewState> {
// if is share extension show default back button
if (!this.isShareExtension) {
options.headerLeft = () => <HeaderButton.CloseModal navigation={navigation} color={themes[theme].previewTintColor} />;
options.headerLeft = () => <HeaderButton.CloseModal navigation={navigation} color={themes[theme].previewTintColor} testID='share-view-close' />;
}
if (!attachments.length && !readOnly) {

View File

@ -143,6 +143,20 @@ async function navigateToRoom(room: string) {
await checkRoomTitle(room);
}
async function navigateToRecentRoom(room: string) {
await waitFor(element(by.id('rooms-list-view')))
.toExist()
.withTimeout(10000);
await tapAndWaitFor(element(by.id('rooms-list-view-search')), element(by.id('rooms-list-view-search-input')), 5000);
await waitFor(element(by.id(`rooms-list-view-item-${room}`)))
.toBeVisible()
.withTimeout(10000);
await element(by.id(`rooms-list-view-item-${room}`)).tap();
await waitFor(element(by.id(`room-view-title-${room}`)))
.toBeVisible()
.withTimeout(10000);
}
async function tryTapping(
theElement: Detox.IndexableNativeElement | Detox.NativeElement,
timeout: number,
@ -261,5 +275,6 @@ export {
checkServer,
platformTypes,
expectValidRegisterOrRetry,
jumpToQuotedMessage
jumpToQuotedMessage,
navigateToRecentRoom
};

View File

@ -22,7 +22,7 @@ import random from '../../helpers/random';
const DEEPLINK_METHODS = { AUTH: 'auth', ROOM: 'room' };
let amp = '&';
const amp = '&';
const getDeepLink = (method: string, server: string, params?: string) => {
const deeplink = `rocketchat://${method}?host=${server.replace(/^(http:\/\/|https:\/\/)/, '')}${amp}${params}`;
@ -47,7 +47,6 @@ describe('Deep linking', () => {
const loginResult = await login(user.username, user.password);
({ userId, authToken } = loginResult);
const deviceType = device.getPlatform();
amp = deviceType === 'android' ? '\\&' : '&';
({ textMatcher } = platformTypes[deviceType]);
// create a thread with api
const result = await sendMessage(user, room, threadMessage);

View File

@ -5,22 +5,15 @@ import {
login,
tapBack,
sleep,
searchRoom,
tryTapping,
platformTypes,
TTextMatcher,
mockMessage
mockMessage,
navigateToRoom,
navigateToRecentRoom
} from '../../helpers/app';
import { createRandomRoom, createRandomUser, ITestUser, sendMessage } from '../../helpers/data_setup';
async function navigateToRoom(roomName: string) {
await searchRoom(`${roomName}`);
await element(by.id(`rooms-list-view-item-${roomName}`)).tap();
await waitFor(element(by.id('room-view')))
.toBeVisible()
.withTimeout(5000);
}
describe('Room screen', () => {
let room: string;
let alertButtonType: string;
@ -371,6 +364,103 @@ describe('Room screen', () => {
.toExist()
.withTimeout(60000);
await element(by[textMatcher](replyMessage)).atIndex(0).tap();
await tapBack();
});
it('should save message and quote draft correctly', async () => {
const newUser = await createRandomUser();
const { name: draftRoom } = await createRandomRoom(newUser, 'c');
const draftMessage = 'draft';
const originalMessage = '123';
const quoteMessage = '123456';
await sendMessage(newUser, draftRoom, originalMessage);
await waitFor(element(by.id('rooms-list-view')))
.toBeVisible()
.withTimeout(5000);
await navigateToRoom(draftRoom);
await waitFor(element(by[textMatcher](originalMessage)).atIndex(0))
.toBeVisible()
.withTimeout(10000);
await element(by.id('room-view-join-button')).tap();
await waitFor(element(by.id('room-view-join-button')))
.not.toBeVisible()
.withTimeout(10000);
// add draft
await element(by.id('message-composer-input')).typeText(draftMessage);
await tapBack();
await navigateToRecentRoom(draftRoom);
await sleep(500); // wait for animation
await expect(element(by.id('message-composer-input'))).toHaveText(draftMessage);
// add quote to draft
await tryTapping(element(by[textMatcher](originalMessage)).atIndex(0), 2000, true);
await waitFor(element(by.id('action-sheet')))
.toExist()
.withTimeout(5000);
await expect(element(by.id('action-sheet-handle'))).toBeVisible();
await element(by.id('action-sheet-handle')).swipe('up', 'fast', 0.5);
await element(by[textMatcher]('Quote')).atIndex(0).tap();
await waitFor(element(by.id(`markdown-preview-${originalMessage}`)))
.toBeVisible()
.withTimeout(10000);
await tapBack();
await navigateToRecentRoom(draftRoom);
await sleep(500); // wait for animation
await waitFor(element(by.id(`markdown-preview-${originalMessage}`)))
.toBeVisible()
.withTimeout(10000);
// edit draft with quote
await element(by.id('message-composer-input')).replaceText(quoteMessage);
await tapBack();
await navigateToRecentRoom(draftRoom);
await sleep(500); // wait for animation
await expect(element(by.id('message-composer-input'))).toHaveText(quoteMessage);
// send message
await waitFor(element(by.id('message-composer-send')))
.toExist()
.withTimeout(5000);
await element(by.id('message-composer-send')).tap();
await waitFor(element(by.id(`reply-${newUser.name}-${originalMessage}`).withDescendant(by[textMatcher](originalMessage))))
.toBeVisible()
.withTimeout(5000);
await expect(element(by.id('message-composer-input'))).toHaveText('');
});
it('should edit message on shareview and after close the text needs to be changed on roomView', async () => {
const draftShareMessage = 'draftShare';
const originalMessage = '123';
await element(by.id('message-composer-input')).typeText(draftShareMessage);
await element(by.id('message-composer-actions')).tap();
await waitFor(element(by.id('action-sheet')))
.toExist()
.withTimeout(2000);
await element(by[textMatcher]('Choose from library')).atIndex(0).tap();
await sleep(300); // wait for animation
await waitFor(element(by.id('message-composer-input-share')))
.toHaveText(draftShareMessage)
.withTimeout(2000);
await element(by.id('message-composer-input-share')).replaceText(draftShareMessage + originalMessage);
await element(by.id('share-view-close')).tap();
await sleep(500); // wait for animation
await waitFor(element(by.id('message-composer-input')))
.toHaveText(draftShareMessage + originalMessage)
.withTimeout(2000);
// add quote to draft
await tryTapping(element(by[textMatcher](originalMessage)).atIndex(0), 2000, true);
await waitFor(element(by.id('action-sheet')))
.toExist()
.withTimeout(2000);
await expect(element(by.id('action-sheet-handle'))).toBeVisible();
await element(by.id('action-sheet-handle')).swipe('up', 'fast', 0.5);
await element(by[textMatcher]('Quote')).atIndex(0).tap();
await element(by.id('message-composer-actions')).tap();
await waitFor(element(by.id('action-sheet')))
.toExist()
.withTimeout(2000);
await element(by[textMatcher]('Choose from library')).atIndex(0).tap();
await sleep(500); // wait for animation
await waitFor(element(by.id(`markdown-preview-${originalMessage}`)).atIndex(0))
.toExist()
.withTimeout(20000);
});
});
});

View File

@ -192,7 +192,7 @@
"babel-loader": "8.3.0",
"babel-plugin-transform-remove-console": "^6.9.4",
"codecov": "^3.8.3",
"detox": "20.11.0",
"detox": "20.17.1",
"eslint": "^7.32.0",
"eslint-config-prettier": "^8.5.0",
"eslint-plugin-import": "2.26.0",

View File

@ -4335,6 +4335,11 @@
find-up "^5.0.0"
js-yaml "^4.1.0"
"@flatten-js/interval-tree@^1.1.2":
version "1.1.2"
resolved "https://registry.yarnpkg.com/@flatten-js/interval-tree/-/interval-tree-1.1.2.tgz#fcc891da48bc230392884be01c26fe8c625702e8"
integrity sha512-OwLoV9E/XM6b7bes2rSFnGNjyRy7vcoIHFTnmBR2WAaZTf0Fe4EX4GdA65vU1KgFAasti7iRSg2dZfYd1Zt00Q==
"@gar/promisify@^1.0.1":
version "1.1.3"
resolved "https://registry.yarnpkg.com/@gar/promisify/-/promisify-1.1.3.tgz#555193ab2e3bb3b6adc3d551c9c030d9e860daf6"
@ -8625,6 +8630,16 @@ builtins@^1.0.3:
resolved "https://registry.yarnpkg.com/builtins/-/builtins-1.0.3.tgz#cb94faeb61c8696451db36534e1422f94f0aee88"
integrity sha512-uYBjakWipfaO/bXI7E8rq6kpwHRZK5cNYrUv2OzZSI/FvmdMyXJ2tG9dKcjEC5YHmHpUAwsargWIZNWdxb/bnQ==
bunyamin@^1.5.0:
version "1.5.2"
resolved "https://registry.yarnpkg.com/bunyamin/-/bunyamin-1.5.2.tgz#681db204c0b16531369d5c1f6c89dc8d760b7558"
integrity sha512-Xp2nfqk33zt3nX90OSTkLVOc5N+1zdR3MWvfLHoIrm3cGRkdxPTPYB9CCgrDV8oum5rbghJjAbmXFXOrRXvMtg==
dependencies:
"@flatten-js/interval-tree" "^1.1.2"
multi-sort-stream "^1.0.4"
stream-json "^1.7.5"
trace-event-lib "^1.3.1"
bunyan-debug-stream@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/bunyan-debug-stream/-/bunyan-debug-stream-3.1.0.tgz#78309c67ad85cfb8f011155334152c49209dcda8"
@ -8642,6 +8657,18 @@ bunyan@^1.8.12:
mv "~2"
safe-json-stringify "~1"
bunyan@^2.0.5:
version "2.0.5"
resolved "https://registry.yarnpkg.com/bunyan/-/bunyan-2.0.5.tgz#9dd056755220dddd8b5bb9cf76f3d0d766e96e71"
integrity sha512-Jvl74TdxCN6rSP9W1I6+UOUtwslTDqsSFkDqZlFb/ilaSvQ+bZAnXT/GT97IZ5L+Vph0joPZPhxUyn6FLNmFAA==
dependencies:
exeunt "1.1.0"
optionalDependencies:
dtrace-provider "~0.8"
moment "^2.19.3"
mv "~2"
safe-json-stringify "~1"
bytebuffer@^5.0.1:
version "5.0.1"
resolved "https://registry.yarnpkg.com/bytebuffer/-/bytebuffer-5.0.1.tgz#582eea4b1a873b6d020a48d58df85f0bba6cfddd"
@ -10145,10 +10172,10 @@ detect-port@^1.3.0:
address "^1.0.1"
debug "^2.6.0"
detox@20.11.0:
version "20.11.0"
resolved "https://registry.yarnpkg.com/detox/-/detox-20.11.0.tgz#f240e01db12334e0706b7f3477e59b8a5e4358c8"
integrity sha512-01LpETlZwfo2V7Awo+5ccUbee7E1lvH3ldLlmXxsx3mQ0pEA65f9CaO+FWhtUGYh7vQRMOQ9SnzYdej/ydQ7iQ==
detox@20.17.1:
version "20.17.1"
resolved "https://registry.yarnpkg.com/detox/-/detox-20.17.1.tgz#55b9615cf5937819e1257fbf03fb2d2d58cf2acc"
integrity sha512-10pey6CR9D5GSloRkH60ObBGZ8VS11H7iuBNY7qq6jO2swiqqckHhPLRXfH9+WGR7l3vDnfU+G/gQs7JxQkJwA==
dependencies:
ajv "^8.6.3"
bunyan "^1.8.12"
@ -10162,6 +10189,7 @@ detox@20.11.0:
funpermaproxy "^1.1.0"
glob "^8.0.3"
ini "^1.3.4"
jest-environment-emit "^1.0.5"
json-cycle "^1.3.0"
lodash "^4.17.11"
multi-sort-stream "^1.0.3"
@ -11138,6 +11166,11 @@ execa@^5.0.0, execa@^5.1.1:
signal-exit "^3.0.3"
strip-final-newline "^2.0.0"
exeunt@1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/exeunt/-/exeunt-1.1.0.tgz#af72db6f94b3cb75e921aee375d513049843d284"
integrity sha512-dd++Yn/0Fp+gtJ04YHov7MeAii+LFivJc6KqnJNfplzLVUkUDrfKoQDTLlCgzcW15vY5hKlHasWeIsQJ8agHsw==
exif-parser@^0.1.12:
version "0.1.12"
resolved "https://registry.yarnpkg.com/exif-parser/-/exif-parser-0.1.12.tgz#58a9d2d72c02c1f6f02a0ef4a9166272b7760922"
@ -13769,6 +13802,20 @@ jest-each@^28.1.3:
jest-util "^28.1.3"
pretty-format "^28.1.3"
jest-environment-emit@^1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/jest-environment-emit/-/jest-environment-emit-1.0.5.tgz#e6f33451f98b88ccd48e9e1188bb535880f03c1b"
integrity sha512-OsQ08AhYxkkyDBTIow+9ogNmJheQIGWQKp0Nku+1ToLWjAj2Pd6LmypN8HgUIqYHs4HFcqkQ25kaf1qExmoZpg==
dependencies:
bunyamin "^1.5.0"
bunyan "^2.0.5"
bunyan-debug-stream "^3.1.0"
funpermaproxy "^1.1.0"
lodash.merge "^4.6.2"
node-ipc "9.2.1"
strip-ansi "^6.0.0"
tslib "^2.5.3"
jest-environment-node@^28.1.3:
version "28.1.3"
resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-28.1.3.tgz#7e74fe40eb645b9d56c0c4b70ca4357faa349be5"
@ -15787,7 +15834,7 @@ ms@2.1.3:
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2"
integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==
multi-sort-stream@^1.0.3:
multi-sort-stream@^1.0.3, multi-sort-stream@^1.0.4:
version "1.0.4"
resolved "https://registry.yarnpkg.com/multi-sort-stream/-/multi-sort-stream-1.0.4.tgz#e4348edc9edc36e16333e531a90c0f166235cc99"
integrity sha512-hAZ8JOEQFbgdLe8HWZbb7gdZg0/yAIHF00Qfo3kd0rXFv96nXe+/bPTrKHZ2QMHugGX4FiAyET1Lt+jiB+7Qlg==
@ -19586,6 +19633,13 @@ stream-json@^1.7.4:
dependencies:
stream-chain "^2.2.5"
stream-json@^1.7.5:
version "1.8.0"
resolved "https://registry.yarnpkg.com/stream-json/-/stream-json-1.8.0.tgz#53f486b2e3b4496c506131f8d7260ba42def151c"
integrity sha512-HZfXngYHUAr1exT4fxlbc1IOce1RYxp2ldeaf97LYCOPSoOqY/1Psp7iGvpb+6JIOgkra9zDYnPX01hGAHzEPw==
dependencies:
stream-chain "^2.2.5"
stream-shift@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.1.tgz#d7088281559ab2778424279b0877da3c392d5a3d"
@ -20476,6 +20530,11 @@ tslib@^2.0.0, tslib@^2.0.1, tslib@^2.1.0, tslib@^2.3.0:
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.0.tgz#7cecaa7f073ce680a05847aa77be941098f36dc3"
integrity sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==
tslib@^2.5.3:
version "2.6.2"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.2.tgz#703ac29425e7b37cd6fd456e92404d46d1f3e4ae"
integrity sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==
tsutils@^3.21.0:
version "3.21.0"
resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623"