Bluesky app fork with some witchin' additions 💫 witchsky.app
bluesky fork client

v1.118.0 E2E tests (#9994)

authored by samuel.fm and committed by

GitHub 30c9ea57 afbade6f

+85 -34
-1
__e2e__/flows/curate-lists.yml
··· 39 39 id: "editListNameInput" 40 40 - eraseText 41 41 - inputText: "Bad Ppl" 42 - - hideKeyboard 43 42 - tapOn: 44 43 id: "editListDescriptionInput" 45 44 - eraseText
+12 -6
__e2e__/flows/feed-reorder.yml
··· 35 35 id: "menuItemButton-Feeds" 36 36 - tapOn: 37 37 id: "editFeedsBtn" 38 - - tapOn: 39 - label: "Tap on down arrow" 40 - id: "feed-timeline-moveDown" 38 + - swipe: 39 + label: "Drag feed down" 40 + from: 41 + id: "feed-drag-handle" 42 + direction: "DOWN" 43 + duration: 1000 41 44 - tapOn: 42 45 label: "Save button" 43 46 id: "saveChangesBtn" ··· 55 58 id: "menuItemButton-Feeds" 56 59 - tapOn: 57 60 id: "editFeedsBtn" 58 - - tapOn: 59 - label: "Tap on down arrow" 60 - id: "feed-feed-moveDown" 61 + - swipe: 62 + label: "Drag feed down" 63 + from: 64 + id: "feed-drag-handle" 65 + direction: "DOWN" 66 + duration: 1000 61 67 - tapOn: 62 68 label: "Save button" 63 69 id: "saveChangesBtn"
+5
__e2e__/flows/login.yml
··· 15 15 - tapOn: 16 16 id: "customServerTextInput" 17 17 - inputText: "http://localhost:3000" 18 + - runFlow: 19 + when: 20 + platform: Android 21 + commands: 22 + - hideKeyboard 18 23 - tapOn: "Done" 19 24 - tapOn: 20 25 id: "loginUsernameInput"
+1
__e2e__/flows/report-dialog/post.reason-other.yml
··· 26 26 - tapOn: 27 27 id: "report:details" 28 28 - inputText: "This is a test report" 29 + - hideKeyboard 29 30 - tapOn: 30 31 id: "report:submit" 31 32 - assertNotVisible:
+23 -9
__e2e__/setupApp.yml
··· 3 3 - launchApp: 4 4 appId: "xyz.blueskyweb.app" 5 5 clearState: true 6 - - waitForAnimationToEnd 7 - - tapOn: "http://localhost:8081" 8 - - waitForAnimationToEnd 9 - - extendedWaitUntil: 10 - visible: "Continue" 11 - - swipe: 12 - from: "Bluesky" 13 - direction: DOWN 14 - duration: 100 6 + arguments: 7 + "-EXDevMenuIsOnboardingFinished": true 8 + - runFlow: 9 + when: 10 + platform: iOS 11 + commands: 12 + - openLink: "exp+bluesky://expo-development-client/?url=http%3A%2F%2Flocalhost%3A8081" 13 + - runFlow: 14 + when: 15 + visible: 'Open in "Bluesky"' 16 + commands: 17 + - tapOn: Open 18 + - runFlow: 19 + when: 20 + platform: Android 21 + commands: 22 + - tapOn: 'http://localhost:8081' 23 + - runFlow: 24 + label: "Dismiss Expo dev menu" 25 + when: 26 + visible: "Continue" 27 + commands: 28 + - back 15 29 - tapOn: 16 30 id: e2eProxyHeaderInput 17 31 - inputText: ${output.result}
+8
docs/testing.md
··· 9 9 2. You can write Maestro tests in `/.maestro/flows/` directory by creating a new `.yml` file or by modifying an existing one. 10 10 3. You can also use [Maestro Studio](https://maestro.mobile.dev/getting-started/maestro-studio) which automatically generates commands by recording your actions on the app. Therefore, you can create realistic tests without having to manually write any code. Use the `maestro studio` command to start recording your actions. 11 11 12 + ### Running on Android 13 + 14 + You will need to allow your device access to the port that the mock server is running on. 15 + 16 + ``` 17 + adb reverse tcp:3000 tcp:3000 18 + ``` 19 + 12 20 ### Running Maestro tests 13 21 14 22 - In one tab, run `yarn e2e:mock-server`
+1
src/Navigation.tsx
··· 690 690 headerShown: true, 691 691 headerTransparent: true, 692 692 headerTitle: '', 693 + headerBackVisible: false, 693 694 scrollEdgeEffects: { 694 695 top: 'soft', 695 696 },
+1
src/components/DraggableList/index.tsx
··· 454 454 const dragHandle = ( 455 455 <GestureDetector gesture={gesture}> 456 456 <Animated.View 457 + testID="feed-drag-handle" 457 458 style={[ 458 459 a.justify_center, 459 460 a.align_center,
+17 -1
src/screens/Profile/Header/GrowableBanner.tsx
··· 30 30 children, 31 31 onPress, 32 32 bannerRef, 33 + testID, 34 + label, 33 35 }: { 34 36 backButton?: React.ReactNode 35 37 children: React.ReactNode 36 38 onPress?: () => void 37 39 bannerRef?: AnimatedRef<Animated.View> 40 + testID?: string 41 + label?: string 38 42 }) { 39 43 const pagerContext = usePagerHeaderContext() 40 44 ··· 42 46 if (!pagerContext || !IS_IOS) { 43 47 return ( 44 48 <Pressable 49 + testID={testID} 45 50 onPress={onPress} 46 51 accessibilityRole="image" 52 + accessibilityLabel={label} 53 + accessibilityHint="" 47 54 style={[a.w_full, a.h_full]}> 48 55 <Animated.View ref={bannerRef} style={[a.w_full, a.h_full]}> 49 56 {children} ··· 60 67 scrollY={scrollY} 61 68 backButton={backButton} 62 69 onPress={onPress} 63 - bannerRef={bannerRef}> 70 + bannerRef={bannerRef} 71 + testID={testID} 72 + label={label}> 64 73 {children} 65 74 </GrowableBannerInner> 66 75 ) ··· 72 81 children, 73 82 onPress, 74 83 bannerRef, 84 + testID, 85 + label, 75 86 }: { 76 87 scrollY: SharedValue<number> 77 88 backButton?: React.ReactNode 78 89 children: React.ReactNode 79 90 onPress?: () => void 80 91 bannerRef?: AnimatedRef<Animated.View> 92 + testID?: string 93 + label?: string 81 94 }) { 82 95 const {top: topInset} = useSafeAreaInsets() 83 96 const isFetching = useIsProfileFetching() ··· 142 155 animatedStyle, 143 156 ]}> 144 157 <Pressable 158 + testID={testID} 145 159 onPress={onPress} 146 160 accessibilityRole="image" 161 + accessibilityLabel={label} 162 + accessibilityHint="" 147 163 style={[a.w_full, a.h_full]}> 148 164 <Animated.View 149 165 ref={bannerRef}
+10 -5
src/screens/Profile/Header/Shell.tsx
··· 10 10 import {useSafeAreaInsets} from 'react-native-safe-area-context' 11 11 import {type AppBskyActorDefs, type ModerationDecision} from '@atproto/api' 12 12 import {utils} from '@bsky.app/alf' 13 - import {msg} from '@lingui/core/macro' 14 - import {useLingui} from '@lingui/react' 13 + import {useLingui} from '@lingui/react/macro' 15 14 import {useNavigation} from '@react-navigation/native' 16 15 17 16 import {BACK_HITSLOP} from '#/lib/constants' ··· 56 55 const t = useTheme() 57 56 const ax = useAnalytics() 58 57 const {currentAccount} = useSession() 59 - const {_} = useLingui() 58 + const {t: l} = useLingui() 60 59 const {openLightbox} = useLightboxControls() 61 60 const navigation = useNavigation<NavigationProp>() 62 61 const {top: topInset} = useSafeAreaInsets() ··· 168 167 style={[a.relative, {height: 150}]}> 169 168 <StatusBarShadow /> 170 169 <GrowableBanner 170 + testID={profile.banner ? 'userBannerImage' : 'userBannerFallback'} 171 + label={ 172 + profile.banner 173 + ? l`View profile banner` 174 + : l`Profile banner placeholder` 175 + } 171 176 onPress={isPlaceholderProfile ? undefined : onPressBanner} 172 177 bannerRef={bannerRef} 173 178 backButton={ ··· 176 181 testID="profileHeaderBackBtn" 177 182 onPress={onPressBack} 178 183 hitSlop={BACK_HITSLOP} 179 - label={_(msg`Back`)} 184 + label={l`Back`} 180 185 style={[ 181 186 a.absolute, 182 187 a.pointer, ··· 259 264 testID="profileHeaderAviButton" 260 265 onPress={onPressAvi} 261 266 accessibilityRole="image" 262 - accessibilityLabel={_(msg`View ${profile.handle}'s avatar`)} 267 + accessibilityLabel={l`View ${profile.handle}'s avatar`} 263 268 accessibilityHint=""> 264 269 <View 265 270 style={[
+1 -1
src/screens/ProfileList/components/MoreOptionsMenu.tsx
··· 154 154 </Button> 155 155 )} 156 156 </Menu.Trigger> 157 - <Menu.Outer> 157 + <Menu.Outer showCancel> 158 158 <Menu.Group> 159 159 <Menu.Item 160 160 label={IS_WEB ? _(msg`Copy link to list`) : _(msg`Share via...`)}
+1
src/view/com/auth/LoggedOut.tsx
··· 57 57 const agent = useAgent() 58 58 useEffect(() => { 59 59 const actors = accounts.map(acc => acc.did) 60 + if (actors.length === 0) return 60 61 void queryClient.prefetchQuery({ 61 62 queryKey: profilesQueryKey(actors), 62 63 staleTime: STALE.MINUTES.FIVE,
+5 -9
src/view/com/testing/TestCtrls.e2e.tsx
··· 25 25 const onboardingDispatch = useOnboardingDispatch() 26 26 const {setShowLoggedOut} = useLoggedOutViewControls() 27 27 const onPressSignInAlice = async () => { 28 + console.info('[E2E] Signing in as Alice') 28 29 await login( 29 30 { 30 31 service: 'http://localhost:3000', ··· 36 37 setShowLoggedOut(false) 37 38 } 38 39 const onPressSignInBob = async () => { 40 + console.info('[E2E] Signing in as Bob') 39 41 await login( 40 42 { 41 43 service: 'http://localhost:3000', ··· 54 56 accessibilityHint="Enter proxy header" 55 57 testID="e2eProxyHeaderInput" 56 58 onChangeText={val => setProxyHeader(val as any)} 59 + autoComplete="off" 60 + autoCorrect={false} 61 + autoCapitalize="none" 57 62 onSubmitEditing={() => { 58 63 const header = `${proxyHeader}#bsky_appview` 59 64 BLUESKY_PROXY_HEADER.set(header) ··· 129 134 /> 130 135 <Pressable 131 136 testID="e2eStartOnboarding" 132 - onPress={() => { 133 - onboardingDispatch({type: 'start'}) 134 - }} 135 - accessibilityRole="button" 136 - style={BTN} 137 - /> 138 - {/* TODO remove this entire control when experiment is over */} 139 - <Pressable 140 - testID="e2eStartLongboarding" 141 137 onPress={() => { 142 138 onboardingDispatch({type: 'start'}) 143 139 }}
-2
src/view/com/util/UserBanner.tsx
··· 210 210 ) : banner && 211 211 !((moderation?.blur && IS_ANDROID) /* android crashes with blur */) ? ( 212 212 <Image 213 - testID="userBannerImage" 214 213 style={[styles.bannerImage, t.atoms.bg_contrast_25]} 215 214 contentFit="cover" 216 215 source={{uri: banner}} ··· 220 219 /> 221 220 ) : ( 222 221 <View 223 - testID="userBannerFallback" 224 222 style={[ 225 223 styles.bannerImage, 226 224 type === 'labeler' ? styles.labelerBanner : t.atoms.bg_contrast_25,