diff options
Diffstat (limited to 'src/view/com')
20 files changed, 108 insertions, 45 deletions
diff --git a/src/view/com/composer/Autocomplete.tsx b/src/view/com/composer/Autocomplete.tsx index 4ee527ee8..2ccd05653 100644 --- a/src/view/com/composer/Autocomplete.tsx +++ b/src/view/com/composer/Autocomplete.tsx @@ -46,6 +46,7 @@ export function Autocomplete({ <Animated.View style={[styles.outer, pal.view, pal.border, topAnimStyle]}> {items.map((item, i) => ( <TouchableOpacity + testID="autocompleteButton" key={i} style={[pal.border, styles.item]} onPress={() => onSelect(item.handle)}> diff --git a/src/view/com/composer/ComposePost.tsx b/src/view/com/composer/ComposePost.tsx index dc0bec135..790e0f784 100644 --- a/src/view/com/composer/ComposePost.tsx +++ b/src/view/com/composer/ComposePost.tsx @@ -56,11 +56,12 @@ export const ComposePost = observer(function ComposePost({ const [isSelectingPhotos, setIsSelectingPhotos] = useState(false) const [selectedPhotos, setSelectedPhotos] = useState<string[]>([]) - const autocompleteView = useMemo<UserAutocompleteViewModel>( + // Using default import (React.use...) instead of named import (use...) to be able to mock store's data in jest environment + const autocompleteView = React.useMemo<UserAutocompleteViewModel>( () => new UserAutocompleteViewModel(store), [store], ) - const localPhotos = useMemo<UserLocalPhotosModel>( + const localPhotos = React.useMemo<UserLocalPhotosModel>( () => new UserLocalPhotosModel(store), [store], ) @@ -179,11 +180,14 @@ export const ComposePost = observer(function ComposePost({ return ( <KeyboardAvoidingView + testID="composePostView" behavior={Platform.OS === 'ios' ? 'padding' : 'height'} style={[pal.view, styles.outer]}> <SafeAreaView style={s.flex1}> <View style={styles.topbar}> - <TouchableOpacity onPress={onPressCancel}> + <TouchableOpacity + testID="composerCancelButton" + onPress={onPressCancel}> <Text style={[pal.link, s.f18]}>Cancel</Text> </TouchableOpacity> <View style={s.flex1} /> @@ -192,7 +196,9 @@ export const ComposePost = observer(function ComposePost({ <ActivityIndicator /> </View> ) : canPost ? ( - <TouchableOpacity onPress={onPressPublish}> + <TouchableOpacity + testID="composerPublishButton" + onPress={onPressPublish}> <LinearGradient colors={[gradients.primary.start, gradients.primary.end]} start={{x: 0, y: 0}} @@ -257,6 +263,7 @@ export const ComposePost = observer(function ComposePost({ size={50} /> <TextInput + testID="composerTextInput" ref={textInput} multiline scrollEnabled @@ -283,6 +290,7 @@ export const ComposePost = observer(function ComposePost({ )} <View style={[pal.border, styles.bottomBar]}> <TouchableOpacity + testID="composerSelectPhotosButton" onPress={onPressSelectPhotos} style={[s.pl5]} hitSlop={HITSLOP}> diff --git a/src/view/com/composer/PhotoCarouselPicker.tsx b/src/view/com/composer/PhotoCarouselPicker.tsx index 6c6cd0a47..12dac5825 100644 --- a/src/view/com/composer/PhotoCarouselPicker.tsx +++ b/src/view/com/composer/PhotoCarouselPicker.tsx @@ -85,21 +85,25 @@ export const PhotoCarouselPicker = ({ return ( <ScrollView + testID="photoCarouselPickerView" horizontal style={[pal.view, styles.photosContainer]} showsHorizontalScrollIndicator={false}> <TouchableOpacity + testID="openCameraButton" style={[styles.galleryButton, pal.border, styles.photo]} onPress={handleOpenCamera}> <FontAwesomeIcon icon="camera" size={24} style={pal.link} /> </TouchableOpacity> <TouchableOpacity + testID="openGalleryButton" style={[styles.galleryButton, pal.border, styles.photo]} onPress={handleOpenGallery}> <FontAwesomeIcon icon="image" style={pal.link} size={24} /> </TouchableOpacity> {localPhotos.photos.map((item: any, index: number) => ( <TouchableOpacity + testID="openSelectPhotoButton" key={`local-image-${index}`} style={[pal.border, styles.photoButton]} onPress={() => handleSelectPhoto(item.node.image.uri)}> diff --git a/src/view/com/composer/Prompt.tsx b/src/view/com/composer/Prompt.tsx index 682a9990b..e8f52f84a 100644 --- a/src/view/com/composer/Prompt.tsx +++ b/src/view/com/composer/Prompt.tsx @@ -17,6 +17,7 @@ export function ComposePrompt({ const pal = usePalette('default') return ( <TouchableOpacity + testID="composePromptButton" style={[ pal.view, pal.border, diff --git a/src/view/com/composer/SelectedPhoto.tsx b/src/view/com/composer/SelectedPhoto.tsx index 7711415f6..393c0b573 100644 --- a/src/view/com/composer/SelectedPhoto.tsx +++ b/src/view/com/composer/SelectedPhoto.tsx @@ -25,13 +25,14 @@ export const SelectedPhoto = ({ ) return selectedPhotos.length !== 0 ? ( - <View style={styles.imageContainer}> + <View testID="selectedPhotosView" style={styles.imageContainer}> {selectedPhotos.length !== 0 && selectedPhotos.map((item, index) => ( <View key={`selected-image-${index}`} style={[styles.image, imageStyle]}> <TouchableOpacity + testID="removePhotoButton" onPress={() => handleRemovePhoto(item)} style={styles.removePhotoButton}> <FontAwesomeIcon @@ -41,7 +42,11 @@ export const SelectedPhoto = ({ /> </TouchableOpacity> - <Image style={[styles.image, imageStyle]} source={{uri: item}} /> + <Image + testID="selectedPhotoImage" + style={[styles.image, imageStyle]} + source={{uri: item}} + /> </View> ))} </View> diff --git a/src/view/com/discover/SuggestedFollows.tsx b/src/view/com/discover/SuggestedFollows.tsx index 017bd08c8..07f397447 100644 --- a/src/view/com/discover/SuggestedFollows.tsx +++ b/src/view/com/discover/SuggestedFollows.tsx @@ -1,4 +1,4 @@ -import React, {useMemo, useEffect, useState} from 'react' +import React, {useEffect, useState} from 'react' import { ActivityIndicator, FlatList, @@ -36,7 +36,8 @@ export const SuggestedFollows = observer( const store = useStores() const [follows, setFollows] = useState<Record<string, string>>({}) - const view = useMemo<SuggestedActorsViewModel>( + // Using default import (React.use...) instead of named import (use...) to be able to mock store's data in jest environment + const view = React.useMemo<SuggestedActorsViewModel>( () => new SuggestedActorsViewModel(store), [], ) diff --git a/src/view/com/login/CreateAccount.tsx b/src/view/com/login/CreateAccount.tsx index b68d3859e..83d17d374 100644 --- a/src/view/com/login/CreateAccount.tsx +++ b/src/view/com/login/CreateAccount.tsx @@ -171,7 +171,7 @@ export const CreateAccount = ({onPressBack}: {onPressBack: () => void}) => { const isReady = !!email && !!password && !!handle && is13 return ( - <ScrollView style={{flex: 1}}> + <ScrollView testID="createAccount" style={{flex: 1}}> <KeyboardAvoidingView behavior="padding" style={{flex: 1}}> <View style={styles.logoHero}> <Logo /> @@ -193,6 +193,7 @@ export const CreateAccount = ({onPressBack}: {onPressBack: () => void}) => { <View style={styles.groupContent}> <FontAwesomeIcon icon="globe" style={styles.groupContentIcon} /> <TouchableOpacity + testID="registerSelectServiceButton" style={styles.textBtn} onPress={onPressSelectService}> <Text style={styles.textBtnLabel}> @@ -235,6 +236,7 @@ export const CreateAccount = ({onPressBack}: {onPressBack: () => void}) => { style={styles.groupContentIcon} /> <TextInput + testID="registerEmailInput" style={[styles.textInput]} placeholder="Email address" placeholderTextColor={colors.blue0} @@ -248,6 +250,7 @@ export const CreateAccount = ({onPressBack}: {onPressBack: () => void}) => { <View style={styles.groupContent}> <FontAwesomeIcon icon="lock" style={styles.groupContentIcon} /> <TextInput + testID="registerPasswordInput" style={[styles.textInput]} placeholder="Choose your password" placeholderTextColor={colors.blue0} @@ -273,6 +276,7 @@ export const CreateAccount = ({onPressBack}: {onPressBack: () => void}) => { <View style={styles.groupContent}> <FontAwesomeIcon icon="at" style={styles.groupContentIcon} /> <TextInput + testID="registerHandleInput" style={[styles.textInput]} placeholder="eg alice" placeholderTextColor={colors.blue0} @@ -317,6 +321,7 @@ export const CreateAccount = ({onPressBack}: {onPressBack: () => void}) => { </View> <View style={styles.groupContent}> <TouchableOpacity + testID="registerIs13Input" style={styles.textBtn} onPress={() => setIs13(!is13)}> <View style={is13 ? styles.checkboxFilled : styles.checkbox}> @@ -339,7 +344,9 @@ export const CreateAccount = ({onPressBack}: {onPressBack: () => void}) => { </TouchableOpacity> <View style={s.flex1} /> {isReady ? ( - <TouchableOpacity onPress={onPressNext}> + <TouchableOpacity + testID="createAccountButton" + onPress={onPressNext}> {isProcessing ? ( <ActivityIndicator color="#fff" /> ) : ( @@ -347,7 +354,9 @@ export const CreateAccount = ({onPressBack}: {onPressBack: () => void}) => { )} </TouchableOpacity> ) : !serviceDescription && error ? ( - <TouchableOpacity onPress={onPressRetryConnect}> + <TouchableOpacity + testID="registerRetryButton" + onPress={onPressRetryConnect}> <Text style={[s.white, s.f18, s.bold, s.pr5]}>Retry</Text> </TouchableOpacity> ) : !serviceDescription ? ( diff --git a/src/view/com/login/Signin.tsx b/src/view/com/login/Signin.tsx index 03c634c46..f60b637b7 100644 --- a/src/view/com/login/Signin.tsx +++ b/src/view/com/login/Signin.tsx @@ -69,7 +69,7 @@ export const Signin = ({onPressBack}: {onPressBack: () => void}) => { const onPressRetryConnect = () => setRetryDescribeTrigger({}) return ( - <KeyboardAvoidingView behavior="padding" style={{flex: 1}}> + <KeyboardAvoidingView testID="signIn" behavior="padding" style={{flex: 1}}> <View style={styles.logoHero}> <Logo /> </View> @@ -194,8 +194,9 @@ const LoginForm = ({ const isReady = !!serviceDescription && !!handle && !!password return ( <> - <View style={styles.group}> + <View testID="loginFormView" style={styles.group}> <TouchableOpacity + testID="loginSelectServiceButton" style={[styles.groupTitle, {paddingRight: 0, paddingVertical: 6}]} onPress={onPressSelectService}> <Text style={[s.flex1, s.white, s.f18, s.bold]} numberOfLines={1}> @@ -213,6 +214,7 @@ const LoginForm = ({ <View style={styles.groupContent}> <FontAwesomeIcon icon="at" style={styles.groupContentIcon} /> <TextInput + testID="loginUsernameInput" style={styles.textInput} placeholder="Username" placeholderTextColor={colors.blue0} @@ -227,6 +229,7 @@ const LoginForm = ({ <View style={styles.groupContent}> <FontAwesomeIcon icon="lock" style={styles.groupContentIcon} /> <TextInput + testID="loginPasswordInput" style={styles.textInput} placeholder="Password" placeholderTextColor={colors.blue0} @@ -238,6 +241,7 @@ const LoginForm = ({ editable={!isProcessing} /> <TouchableOpacity + testID="forgotPasswordButton" style={styles.textInputInnerBtn} onPress={onPressForgotPassword}> <Text style={styles.textInputInnerBtnLabel}>Forgot</Text> @@ -260,7 +264,9 @@ const LoginForm = ({ </TouchableOpacity> <View style={s.flex1} /> {!serviceDescription && error ? ( - <TouchableOpacity onPress={onPressRetryConnect}> + <TouchableOpacity + testID="loginRetryButton" + onPress={onPressRetryConnect}> <Text style={[s.white, s.f18, s.bold, s.pr5]}>Retry</Text> </TouchableOpacity> ) : !serviceDescription ? ( @@ -271,7 +277,7 @@ const LoginForm = ({ ) : isProcessing ? ( <ActivityIndicator color="#fff" /> ) : isReady ? ( - <TouchableOpacity onPress={onPressNext}> + <TouchableOpacity testID="loginNextButton" onPress={onPressNext}> <Text style={[s.white, s.f18, s.bold, s.pr5]}>Next</Text> </TouchableOpacity> ) : undefined} @@ -339,8 +345,9 @@ const ForgotPasswordForm = ({ Enter the email you used to create your account. We'll send you a "reset code" so you can set a new password. </Text> - <View style={styles.group}> + <View testID="forgotPasswordView" style={styles.group}> <TouchableOpacity + testID="forgotPasswordSelectServiceButton" style={[styles.groupContent, {borderTopWidth: 0}]} onPress={onPressSelectService}> <FontAwesomeIcon icon="globe" style={styles.groupContentIcon} /> @@ -359,6 +366,7 @@ const ForgotPasswordForm = ({ <View style={styles.groupContent}> <FontAwesomeIcon icon="envelope" style={styles.groupContentIcon} /> <TextInput + testID="forgotPasswordEmail" style={styles.textInput} placeholder="Email address" placeholderTextColor={colors.blue0} @@ -391,7 +399,7 @@ const ForgotPasswordForm = ({ ) : !email ? ( <Text style={[s.blue1, s.f18, s.bold, s.pr5]}>Next</Text> ) : ( - <TouchableOpacity onPress={onPressNext}> + <TouchableOpacity testID="newPasswordButton" onPress={onPressNext}> <Text style={[s.white, s.f18, s.bold, s.pr5]}>Next</Text> </TouchableOpacity> )} @@ -451,10 +459,11 @@ const SetNewPasswordForm = ({ You will receive an email with a "reset code." Enter that code here, then enter your new password. </Text> - <View style={styles.group}> + <View testID="newPasswordView" style={styles.group}> <View style={[styles.groupContent, {borderTopWidth: 0}]}> <FontAwesomeIcon icon="ticket" style={styles.groupContentIcon} /> <TextInput + testID="resetCodeInput" style={[styles.textInput]} placeholder="Reset code" placeholderTextColor={colors.blue0} @@ -469,6 +478,7 @@ const SetNewPasswordForm = ({ <View style={styles.groupContent}> <FontAwesomeIcon icon="lock" style={styles.groupContentIcon} /> <TextInput + testID="newPasswordInput" style={styles.textInput} placeholder="New password" placeholderTextColor={colors.blue0} @@ -501,7 +511,7 @@ const SetNewPasswordForm = ({ ) : !resetCode || !password ? ( <Text style={[s.blue1, s.f18, s.bold, s.pr5]}>Next</Text> ) : ( - <TouchableOpacity onPress={onPressNext}> + <TouchableOpacity testID="setNewPasswordButton" onPress={onPressNext}> <Text style={[s.white, s.f18, s.bold, s.pr5]}>Next</Text> </TouchableOpacity> )} diff --git a/src/view/com/notifications/InviteAccepter.tsx b/src/view/com/notifications/InviteAccepter.tsx index eefe7a273..a8789b171 100644 --- a/src/view/com/notifications/InviteAccepter.tsx +++ b/src/view/com/notifications/InviteAccepter.tsx @@ -1,4 +1,4 @@ -import React, {useState} from 'react' +import React from 'react' import {StyleSheet, TouchableOpacity, View} from 'react-native' import LinearGradient from 'react-native-linear-gradient' import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome' @@ -13,7 +13,8 @@ import {s, colors, gradients} from '../../lib/styles' export function InviteAccepter({item}: {item: NotificationsViewItemModel}) { const store = useStores() - const [confirmationUri, setConfirmationUri] = useState<string>('') + // Using default import (React.use...) instead of named import (use...) to be able to mock store's data in jest environment + const [confirmationUri, setConfirmationUri] = React.useState<string>('') const isMember = confirmationUri !== '' || store.me.memberships?.isMemberOf(item.author.did) const onPressAccept = async () => { @@ -54,7 +55,7 @@ export function InviteAccepter({item}: {item: NotificationsViewItemModel}) { return ( <View style={styles.container}> {!isMember ? ( - <TouchableOpacity onPress={onPressAccept}> + <TouchableOpacity testID="acceptInviteButton" onPress={onPressAccept}> <LinearGradient colors={[gradients.primary.start, gradients.primary.end]} start={{x: 0, y: 0}} @@ -64,7 +65,7 @@ export function InviteAccepter({item}: {item: NotificationsViewItemModel}) { </LinearGradient> </TouchableOpacity> ) : ( - <View style={styles.inviteAccepted}> + <View testID="inviteAccepted" style={styles.inviteAccepted}> <FontAwesomeIcon icon="check" size={14} style={s.mr5} /> <Text style={[s.gray5, s.f15]}>Invite accepted</Text> </View> diff --git a/src/view/com/post-thread/PostRepostedBy.tsx b/src/view/com/post-thread/PostRepostedBy.tsx index 5dbb6219e..12d5a2177 100644 --- a/src/view/com/post-thread/PostRepostedBy.tsx +++ b/src/view/com/post-thread/PostRepostedBy.tsx @@ -1,4 +1,4 @@ -import React, {useState, useEffect} from 'react' +import React, {useEffect} from 'react' import {observer} from 'mobx-react-lite' import {ActivityIndicator, FlatList, StyleSheet, View} from 'react-native' import { @@ -18,7 +18,8 @@ export const PostRepostedBy = observer(function PostRepostedBy({ uri: string }) { const store = useStores() - const [view, setView] = useState<RepostedByViewModel | undefined>() + // Using default import (React.use...) instead of named import (use...) to be able to mock store's data in jest environment + const [view, setView] = React.useState<RepostedByViewModel | undefined>() useEffect(() => { if (view?.params.uri === uri) { diff --git a/src/view/com/post-thread/PostVotedBy.tsx b/src/view/com/post-thread/PostVotedBy.tsx index 17ed9f9f8..af5bc2475 100644 --- a/src/view/com/post-thread/PostVotedBy.tsx +++ b/src/view/com/post-thread/PostVotedBy.tsx @@ -1,4 +1,4 @@ -import React, {useState, useEffect} from 'react' +import React, {useEffect} from 'react' import {observer} from 'mobx-react-lite' import {ActivityIndicator, FlatList, StyleSheet, View} from 'react-native' import { @@ -20,7 +20,7 @@ export const PostVotedBy = observer(function PostVotedBy({ direction: 'up' | 'down' }) { const store = useStores() - const [view, setView] = useState<VotesViewModel | undefined>() + const [view, setView] = React.useState<VotesViewModel | undefined>() useEffect(() => { if (view?.params.uri === uri) { diff --git a/src/view/com/posts/Feed.tsx b/src/view/com/posts/Feed.tsx index 76f595cd4..f3402428e 100644 --- a/src/view/com/posts/Feed.tsx +++ b/src/view/com/posts/Feed.tsx @@ -25,6 +25,7 @@ export const Feed = observer(function Feed({ onPressCompose, onPressTryAgain, onScroll, + testID, }: { feed: FeedModel style?: StyleProp<ViewStyle> @@ -32,6 +33,7 @@ export const Feed = observer(function Feed({ onPressCompose: () => void onPressTryAgain?: () => void onScroll?: OnScrollCb + testID?: string }) { // TODO optimize renderItem or FeedItem, we're getting this notice from RN: -prf // VirtualizedList: You have a large list that is slow to update - make sure your @@ -83,7 +85,7 @@ export const Feed = observer(function Feed({ <View /> ) return ( - <View style={style}> + <View testID={testID} style={style}> {!data && <ComposePrompt onPressCompose={onPressCompose} />} {feed.isLoading && !data && <PostFeedLoadingPlaceholder />} {feed.hasError && ( diff --git a/src/view/com/profile/ProfileFollowers.tsx b/src/view/com/profile/ProfileFollowers.tsx index e6e710ff3..26939c7ce 100644 --- a/src/view/com/profile/ProfileFollowers.tsx +++ b/src/view/com/profile/ProfileFollowers.tsx @@ -1,4 +1,4 @@ -import React, {useState, useEffect} from 'react' +import React, {useEffect} from 'react' import {observer} from 'mobx-react-lite' import {ActivityIndicator, FlatList, StyleSheet, View} from 'react-native' import { @@ -19,7 +19,7 @@ export const ProfileFollowers = observer(function ProfileFollowers({ name: string }) { const store = useStores() - const [view, setView] = useState<UserFollowersViewModel | undefined>() + const [view, setView] = React.useState<UserFollowersViewModel | undefined>() useEffect(() => { if (view?.params.user === name) { diff --git a/src/view/com/profile/ProfileFollows.tsx b/src/view/com/profile/ProfileFollows.tsx index 73e765d19..03c5b13bb 100644 --- a/src/view/com/profile/ProfileFollows.tsx +++ b/src/view/com/profile/ProfileFollows.tsx @@ -1,4 +1,4 @@ -import React, {useState, useEffect} from 'react' +import React, {useEffect} from 'react' import {observer} from 'mobx-react-lite' import {ActivityIndicator, FlatList, StyleSheet, View} from 'react-native' import { @@ -10,7 +10,7 @@ import {Link} from '../util/Link' import {Text} from '../util/text/Text' import {ErrorMessage} from '../util/error/ErrorMessage' import {UserAvatar} from '../util/UserAvatar' -import {s, colors} from '../../lib/styles' +import {s} from '../../lib/styles' import {usePalette} from '../../lib/hooks/usePalette' export const ProfileFollows = observer(function ProfileFollows({ @@ -19,7 +19,7 @@ export const ProfileFollows = observer(function ProfileFollows({ name: string }) { const store = useStores() - const [view, setView] = useState<UserFollowsViewModel | undefined>() + const [view, setView] = React.useState<UserFollowsViewModel | undefined>() useEffect(() => { if (view?.params.user === name) { diff --git a/src/view/com/profile/ProfileHeader.tsx b/src/view/com/profile/ProfileHeader.tsx index a4d7c7a92..4fd766952 100644 --- a/src/view/com/profile/ProfileHeader.tsx +++ b/src/view/com/profile/ProfileHeader.tsx @@ -147,7 +147,7 @@ export const ProfileHeader = observer(function ProfileHeader({ // = if (view.hasError) { return ( - <View> + <View testID="profileHeaderHasError"> <Text>{view.error}</Text> </View> ) @@ -192,6 +192,7 @@ export const ProfileHeader = observer(function ProfileHeader({ <View style={[styles.buttonsLine]}> {isMe ? ( <TouchableOpacity + testID="profileHeaderEditProfileButton" onPress={onPressEditProfile} style={[styles.btn, styles.mainBtn, pal.btn]}> <Text type="button" style={pal.text}> @@ -214,7 +215,9 @@ export const ProfileHeader = observer(function ProfileHeader({ </Text> </TouchableOpacity> ) : ( - <TouchableOpacity onPress={onPressToggleFollow}> + <TouchableOpacity + testID="profileHeaderToggleFollowButton" + onPress={onPressToggleFollow}> <LinearGradient colors={[gradient[1], gradient[0]]} start={{x: 0, y: 0}} @@ -257,6 +260,7 @@ export const ProfileHeader = observer(function ProfileHeader({ </View> <View style={styles.metricsLine}> <TouchableOpacity + testID="profileHeaderFollowersButton" style={[s.flexRow, s.mr10]} onPress={onPressFollowers}> <Text type="body2" style={[s.bold, s.mr2, pal.text]}> @@ -268,6 +272,7 @@ export const ProfileHeader = observer(function ProfileHeader({ </TouchableOpacity> {view.isUser ? ( <TouchableOpacity + testID="profileHeaderFollowsButton" style={[s.flexRow, s.mr10]} onPress={onPressFollows}> <Text type="body2" style={[s.bold, s.mr2, pal.text]}> @@ -280,6 +285,7 @@ export const ProfileHeader = observer(function ProfileHeader({ ) : undefined} {view.isScene ? ( <TouchableOpacity + testID="profileHeaderMembersButton" style={[s.flexRow, s.mr10]} onPress={onPressMembers}> <Text type="body2" style={[s.bold, s.mr2, pal.text]}> @@ -350,7 +356,9 @@ export const ProfileHeader = observer(function ProfileHeader({ </View> {view.isScene && view.creator === store.me.did ? ( <View style={[styles.sceneAdminContainer, pal.border]}> - <TouchableOpacity onPress={onPressInviteMembers}> + <TouchableOpacity + testID="profileHeaderInviteMembersButton" + onPress={onPressInviteMembers}> <LinearGradient colors={[gradient[1], gradient[0]]} start={{x: 0, y: 0}} @@ -369,6 +377,7 @@ export const ProfileHeader = observer(function ProfileHeader({ </View> ) : undefined} <TouchableOpacity + testID="profileHeaderAviButton" style={[pal.view, {borderColor: pal.colors.background}, styles.avi]} onPress={onPressAvi}> <UserAvatar diff --git a/src/view/com/profile/ProfileMembers.tsx b/src/view/com/profile/ProfileMembers.tsx index 7f566c198..a63de9e32 100644 --- a/src/view/com/profile/ProfileMembers.tsx +++ b/src/view/com/profile/ProfileMembers.tsx @@ -1,4 +1,4 @@ -import React, {useState, useEffect} from 'react' +import React, {useEffect} from 'react' import {observer} from 'mobx-react-lite' import {ActivityIndicator, FlatList, View} from 'react-native' import {MembersViewModel, MemberItem} from '../../../state/models/members-view' @@ -12,7 +12,8 @@ export const ProfileMembers = observer(function ProfileMembers({ name: string }) { const store = useStores() - const [view, setView] = useState<MembersViewModel | undefined>() + // Using default import (React.use...) instead of named import (use...) to be able to mock store's data in jest environment + const [view, setView] = React.useState<MembersViewModel | undefined>() useEffect(() => { if (view?.params.actor === name) { @@ -37,7 +38,7 @@ export const ProfileMembers = observer(function ProfileMembers({ view.params.actor !== name ) { return ( - <View> + <View testID="profileMembersActivityIndicatorView"> <ActivityIndicator /> </View> ) @@ -68,7 +69,7 @@ export const ProfileMembers = observer(function ProfileMembers({ /> ) return ( - <View> + <View testID="profileMembersFlatList"> <FlatList data={view.members} keyExtractor={item => item._reactKey} diff --git a/src/view/com/util/PostCtrls.tsx b/src/view/com/util/PostCtrls.tsx index c0ef412d8..25f171598 100644 --- a/src/view/com/util/PostCtrls.tsx +++ b/src/view/com/util/PostCtrls.tsx @@ -115,6 +115,7 @@ export function PostCtrls(opts: PostCtrlsOpts) { <View style={[styles.ctrls, opts.style]}> <View style={s.flex1}> <TouchableOpacity + testID="postCtrlsReplyButton" style={styles.ctrl} hitSlop={HITSLOP} onPress={opts.onPressReply}> @@ -130,6 +131,7 @@ export function PostCtrls(opts: PostCtrlsOpts) { </View> <View style={s.flex1}> <TouchableOpacity + testID="postCtrlsToggleRepostButton" hitSlop={HITSLOP} onPress={onPressToggleRepostWrapper} style={styles.ctrl}> @@ -156,6 +158,7 @@ export function PostCtrls(opts: PostCtrlsOpts) { </View> <View style={s.flex1}> <TouchableOpacity + testID="postCtrlsToggleUpvoteButton" style={styles.ctrl} hitSlop={HITSLOP} onPress={onPressToggleUpvoteWrapper}> diff --git a/src/view/com/util/error/ErrorMessage.tsx b/src/view/com/util/error/ErrorMessage.tsx index 905268d3e..ee31ad2cb 100644 --- a/src/view/com/util/error/ErrorMessage.tsx +++ b/src/view/com/util/error/ErrorMessage.tsx @@ -8,7 +8,6 @@ import { } from 'react-native' import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome' import {Text} from '../text/Text' -import {colors} from '../../../lib/styles' import {useTheme} from '../../../lib/ThemeContext' import {usePalette} from '../../../lib/hooks/usePalette' @@ -26,7 +25,7 @@ export function ErrorMessage({ const theme = useTheme() const pal = usePalette('error') return ( - <View style={[styles.outer, pal.view, style]}> + <View testID="errorMessageView" style={[styles.outer, pal.view, style]}> <View style={[styles.errorIcon, {backgroundColor: theme.palette.error.icon}]}> <FontAwesomeIcon icon="exclamation" style={pal.text} size={16} /> @@ -38,7 +37,10 @@ export function ErrorMessage({ {message} </Text> {onPressTryAgain && ( - <TouchableOpacity style={styles.btn} onPress={onPressTryAgain}> + <TouchableOpacity + testID="errorMessageTryAgainButton" + style={styles.btn} + onPress={onPressTryAgain}> <FontAwesomeIcon icon="arrows-rotate" style={{color: theme.palette.error.icon}} diff --git a/src/view/com/util/error/ErrorScreen.tsx b/src/view/com/util/error/ErrorScreen.tsx index 6db54a9f2..0033195d9 100644 --- a/src/view/com/util/error/ErrorScreen.tsx +++ b/src/view/com/util/error/ErrorScreen.tsx @@ -11,16 +11,18 @@ export function ErrorScreen({ message, details, onPressTryAgain, + testID, }: { title: string message: string details?: string onPressTryAgain?: () => void + testID?: string }) { const theme = useTheme() const pal = usePalette('error') return ( - <View style={[styles.outer, pal.view]}> + <View testID={testID} style={[styles.outer, pal.view]}> <View style={styles.errorIconContainer}> <View style={[ @@ -40,6 +42,7 @@ export function ErrorScreen({ <Text style={[styles.message, pal.textLight]}>{message}</Text> {details && ( <Text + testID={`${testID}-details`} type="body2" style={[ styles.details, @@ -52,6 +55,7 @@ export function ErrorScreen({ {onPressTryAgain && ( <View style={styles.btnContainer}> <TouchableOpacity + testID="errorScreenTryAgainButton" style={[styles.btn, {backgroundColor: theme.palette.error.icon}]} onPress={onPressTryAgain}> <FontAwesomeIcon icon="arrows-rotate" style={pal.text} size={16} /> diff --git a/src/view/com/util/forms/DropdownButton.tsx b/src/view/com/util/forms/DropdownButton.tsx index c81ccf6c5..33387f894 100644 --- a/src/view/com/util/forms/DropdownButton.tsx +++ b/src/view/com/util/forms/DropdownButton.tsx @@ -75,7 +75,8 @@ export function DropdownButton({ style={style} onPress={onPress} hitSlop={HITSLOP} - ref={ref}> + // Fix an issue where specific references cause runtime error in jest environment + ref={process.env.JEST_WORKER_ID != null ? null : ref}> {children} </TouchableOpacity> ) |