Improve e2e tests (#8927)
* get e2e image picker working * verify create account actually reaches onboarding * wait for image to actually be attached before posting * wait until login finishes before moving on * sign out before switch accounts then wait until logged in * disable onboarding experiments in e2e * add testId to handle availability checkmark * fix too long username * update thread muting test to reflect current behaviour * hackfix for the british english translation * unflake the onboarding tests * fix curate list flow * admit defeat on the most list one
This commit is contained in:
@@ -7,6 +7,7 @@ import ExpoImageCropTool, {type OpenCropperOptions} from 'expo-image-crop-tool'
|
||||
|
||||
import {compressIfNeeded} from './manip'
|
||||
import {type PickerImage} from './picker.shared'
|
||||
import {ImagePickerResult} from 'expo-image-picker'
|
||||
|
||||
async function getFile() {
|
||||
const imagesDir = documentDirectory!
|
||||
@@ -38,6 +39,22 @@ export async function openPicker(): Promise<PickerImage[]> {
|
||||
return [await getFile()]
|
||||
}
|
||||
|
||||
export async function openUnifiedPicker(): Promise<ImagePickerResult> {
|
||||
const file = await getFile()
|
||||
|
||||
return {
|
||||
assets: [
|
||||
{
|
||||
type: 'image',
|
||||
uri: file.path,
|
||||
mimeType: file.mime,
|
||||
...file,
|
||||
},
|
||||
],
|
||||
canceled: false,
|
||||
}
|
||||
}
|
||||
|
||||
export async function openCamera(): Promise<PickerImage> {
|
||||
return await getFile()
|
||||
}
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
import {
|
||||
type ImagePickerOptions,
|
||||
launchImageLibraryAsync,
|
||||
UIImagePickerPreferredAssetRepresentationMode,
|
||||
} from 'expo-image-picker'
|
||||
import {t} from '@lingui/macro'
|
||||
|
||||
import {isIOS, isWeb} from '#/platform/detection'
|
||||
import {type ImageMeta} from '#/state/gallery'
|
||||
import * as Toast from '#/view/com/util/Toast'
|
||||
import {VIDEO_MAX_DURATION_MS} from '../constants'
|
||||
import {getDataUriSize} from './util'
|
||||
|
||||
export type PickerImage = ImageMeta & {
|
||||
@@ -36,3 +39,22 @@ export async function openPicker(opts?: ImagePickerOptions) {
|
||||
size: getDataUriSize(image.uri),
|
||||
}))
|
||||
}
|
||||
|
||||
export async function openUnifiedPicker({
|
||||
selectionCountRemaining,
|
||||
}: {
|
||||
selectionCountRemaining: number
|
||||
}) {
|
||||
return await launchImageLibraryAsync({
|
||||
exif: false,
|
||||
mediaTypes: ['images', 'videos'],
|
||||
quality: 1,
|
||||
allowsMultipleSelection: true,
|
||||
legacy: true,
|
||||
base64: isWeb,
|
||||
selectionLimit: isIOS ? selectionCountRemaining : undefined,
|
||||
preferredAssetRepresentationMode:
|
||||
UIImagePickerPreferredAssetRepresentationMode.Current,
|
||||
videoMaxDuration: VIDEO_MAX_DURATION_MS / 1000,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
import ExpoImageCropTool, {type OpenCropperOptions} from 'expo-image-crop-tool'
|
||||
import {type ImagePickerOptions, launchCameraAsync} from 'expo-image-picker'
|
||||
|
||||
export {openPicker, type PickerImage as RNImage} from './picker.shared'
|
||||
export {
|
||||
openPicker,
|
||||
openUnifiedPicker,
|
||||
type PickerImage as RNImage,
|
||||
} from './picker.shared'
|
||||
|
||||
export async function openCamera(customOpts: ImagePickerOptions) {
|
||||
const opts: ImagePickerOptions = {
|
||||
|
||||
@@ -3,7 +3,7 @@ import {type OpenCropperOptions} from 'expo-image-crop-tool'
|
||||
import {type PickerImage} from './picker.shared'
|
||||
import {type CameraOpts} from './types'
|
||||
|
||||
export {openPicker} from './picker.shared'
|
||||
export {openPicker, openUnifiedPicker} from './picker.shared'
|
||||
|
||||
export async function openCamera(_opts: CameraOpts): Promise<PickerImage> {
|
||||
throw new Error('openCamera is not supported on web')
|
||||
|
||||
@@ -580,6 +580,7 @@ function LegacyFinalStep({
|
||||
|
||||
<OnboardingControls.Portal>
|
||||
<Button
|
||||
testID="onboardingFinish"
|
||||
disabled={saving}
|
||||
key={state.activeStep} // remove focus state on nav
|
||||
color="primary"
|
||||
|
||||
@@ -244,6 +244,7 @@ export function StepInterests() {
|
||||
) : (
|
||||
<Button
|
||||
disabled={saving || !data}
|
||||
testID="onboardingContinue"
|
||||
variant="solid"
|
||||
color="primary"
|
||||
size="large"
|
||||
|
||||
@@ -268,6 +268,7 @@ export function StepProfile() {
|
||||
<OnboardingControls.Portal>
|
||||
<View style={[a.gap_md, gtMobile && a.flex_row_reverse]}>
|
||||
<Button
|
||||
testID="onboardingContinue"
|
||||
variant="solid"
|
||||
color="primary"
|
||||
size="large"
|
||||
@@ -279,6 +280,7 @@ export function StepProfile() {
|
||||
<ButtonIcon icon={ChevronRight} position="right" />
|
||||
</Button>
|
||||
<Button
|
||||
testID="onboardingAvatarCreator"
|
||||
variant="ghost"
|
||||
color="primary"
|
||||
size="large"
|
||||
|
||||
@@ -13,13 +13,15 @@ import {StepFinished} from '#/screens/Onboarding/StepFinished'
|
||||
import {StepInterests} from '#/screens/Onboarding/StepInterests'
|
||||
import {StepProfile} from '#/screens/Onboarding/StepProfile'
|
||||
import {Portal} from '#/components/Portal'
|
||||
import {ENV} from '#/env'
|
||||
import {StepSuggestedAccounts} from './StepSuggestedAccounts'
|
||||
|
||||
export function Onboarding() {
|
||||
const {_} = useLingui()
|
||||
const gate = useGate()
|
||||
const showValueProp = gate('onboarding_value_prop')
|
||||
const showSuggestedAccounts = gate('onboarding_suggested_accounts')
|
||||
const showValueProp = ENV !== 'e2e' && gate('onboarding_value_prop')
|
||||
const showSuggestedAccounts =
|
||||
ENV !== 'e2e' && gate('onboarding_suggested_accounts')
|
||||
const [state, dispatch] = useReducer(reducer, {
|
||||
...initialState,
|
||||
totalSteps: showSuggestedAccounts ? 4 : 3,
|
||||
|
||||
@@ -168,7 +168,10 @@ export function StepHandle() {
|
||||
</TextField.GhostText>
|
||||
)}
|
||||
{isHandleAvailable?.available && (
|
||||
<CheckIcon style={[{color: t.palette.positive_600}, a.z_20]} />
|
||||
<CheckIcon
|
||||
testID="handleAvailableCheck"
|
||||
style={[{color: t.palette.positive_600}, a.z_20]}
|
||||
/>
|
||||
)}
|
||||
</TextField.Root>
|
||||
</View>
|
||||
|
||||
@@ -1,10 +1,6 @@
|
||||
import {useCallback} from 'react'
|
||||
import {Keyboard} from 'react-native'
|
||||
import {
|
||||
type ImagePickerAsset,
|
||||
launchImageLibraryAsync,
|
||||
UIImagePickerPreferredAssetRepresentationMode,
|
||||
} from 'expo-image-picker'
|
||||
import {type ImagePickerAsset} from 'expo-image-picker'
|
||||
import {msg, plural} from '@lingui/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
|
||||
@@ -13,8 +9,9 @@ import {
|
||||
usePhotoLibraryPermission,
|
||||
useVideoLibraryPermission,
|
||||
} from '#/lib/hooks/usePermissions'
|
||||
import {openUnifiedPicker} from '#/lib/media/picker'
|
||||
import {extractDataUriMime} from '#/lib/media/util'
|
||||
import {isIOS, isNative, isWeb} from '#/platform/detection'
|
||||
import {isNative, isWeb} from '#/platform/detection'
|
||||
import {MAX_IMAGES} from '#/view/com/composer/state/composer'
|
||||
import {atoms as a, useTheme} from '#/alf'
|
||||
import {Button} from '#/components/Button'
|
||||
@@ -448,18 +445,7 @@ export function SelectMediaButton({
|
||||
}
|
||||
|
||||
const {assets, canceled} = await sheetWrapper(
|
||||
launchImageLibraryAsync({
|
||||
exif: false,
|
||||
mediaTypes: ['images', 'videos'],
|
||||
quality: 1,
|
||||
allowsMultipleSelection: true,
|
||||
legacy: true,
|
||||
base64: isWeb,
|
||||
selectionLimit: isIOS ? selectionCountRemaining : undefined,
|
||||
preferredAssetRepresentationMode:
|
||||
UIImagePickerPreferredAssetRepresentationMode.Current,
|
||||
videoMaxDuration: VIDEO_MAX_DURATION_MS / 1000,
|
||||
}),
|
||||
openUnifiedPicker({selectionCountRemaining}),
|
||||
)
|
||||
|
||||
if (canceled) return
|
||||
|
||||
Reference in New Issue
Block a user