[Inji 648] add accessibility id to elements in different screens (#1105)

* [INJI-648] add accessibility IDs to the requested elements in different screens

Signed-off-by: PuBHARGAVI <46226958+PuBHARGAVI@users.noreply.github.com>

* [INJI-648] fix accessibility IDs for some elements to work in ios

Signed-off-by: PuBHARGAVI <46226958+PuBHARGAVI@users.noreply.github.com>

* [INJI-648] change accessibility IDs for pressable and child elements to work in ios

Signed-off-by: PuBHARGAVI <46226958+PuBHARGAVI@users.noreply.github.com>

* [INJI-648] remove icon parameter in testId function for plus icon

Signed-off-by: PuBHARGAVI <46226958+PuBHARGAVI@users.noreply.github.com>

---------

Signed-off-by: PuBHARGAVI <46226958+PuBHARGAVI@users.noreply.github.com>
This commit is contained in:
PuBHARGAVI
2023-12-21 10:43:36 +05:30
committed by GitHub
parent 680e1bb504
commit 03b64426ed
28 changed files with 159 additions and 49 deletions

View File

@@ -44,7 +44,7 @@ fileignoreconfig:
- filename: screens/Issuers/IssuersScreen.tsx - filename: screens/Issuers/IssuersScreen.tsx
checksum: 9c53e3770dbefe26e0de67ee4b7d5cc9c52d9823cbb136a1a5104dcb0a101071 checksum: 9c53e3770dbefe26e0de67ee4b7d5cc9c52d9823cbb136a1a5104dcb0a101071
- filename: ios/Podfile.lock - filename: ios/Podfile.lock
checksum: c30eada0d288ef1705e0eeb03bb941863ca7e5663196baaa814cb24e8312655e checksum: 2487c4e11fb1bd95032cc4511435d9420fc0dfc62f3c015d177213fa089df7f2
- filename: screens/Home/IntroSlidersScreen.tsx - filename: screens/Home/IntroSlidersScreen.tsx
checksum: 72ef913857448ef05763e52e32356faa2d1f3de8130a1c638d1897f44823031f checksum: 72ef913857448ef05763e52e32356faa2d1f3de8130a1c638d1897f44823031f
- filename: shared/commonUtil.ts - filename: shared/commonUtil.ts

View File

@@ -5,13 +5,16 @@ import Clipboard from '@react-native-clipboard/clipboard';
import {Icon} from 'react-native-elements'; import {Icon} from 'react-native-elements';
import {Row, Text} from './ui'; import {Row, Text} from './ui';
import {useTranslation} from 'react-i18next'; import {useTranslation} from 'react-i18next';
import testIDProps from '../shared/commonUtil';
export const CopyButton: React.FC<CopyButtonProps> = ({content}) => { export const CopyButton: React.FC<CopyButtonProps> = ({content}) => {
const {t} = useTranslation('common'); const {t} = useTranslation('common');
const [buttonText, setButtonText] = useState(t('clipboard.copy')); const [buttonText, setButtonText] = useState(t('clipboard.copy'));
return ( return (
<Pressable <Pressable
{...testIDProps(`${buttonText}Button`)}
accessible={false}
style={Theme.Styles.iconContainer}
onPress={() => { onPress={() => {
setButtonText(t('clipboard.copied')); setButtonText(t('clipboard.copied'));
setTimeout(() => setButtonText(t('clipboard.copy')), 3000); setTimeout(() => setButtonText(t('clipboard.copy')), 3000);
@@ -19,13 +22,18 @@ export const CopyButton: React.FC<CopyButtonProps> = ({content}) => {
}}> }}>
<Row crossAlign="center"> <Row crossAlign="center">
<Icon <Icon
{...testIDProps('fileCopyIcon')}
type={'material'} type={'material'}
name={'file-copy'} name={'file-copy'}
color={Theme.Colors.Icon} color={Theme.Colors.Icon}
style={{marginRight: 2}} style={{marginRight: 2}}
size={19} size={19}
/> />
<Text weight="semibold" align="center" style={{paddingTop: 5}}> <Text
testID={`${buttonText}Text`}
weight="semibold"
align="center"
style={{paddingTop: 5}}>
{buttonText} {buttonText}
</Text> </Text>
</Row> </Row>

View File

@@ -67,6 +67,7 @@ export const DualMessageOverlay: React.FC<DualMessageOverlayProps> = props => {
<Row style={Theme.MessageOverlayStyles.buttonContainer}> <Row style={Theme.MessageOverlayStyles.buttonContainer}>
{!props.children && props.onTryAgain ? ( {!props.children && props.onTryAgain ? (
<Button <Button
testID='tryAgain'
title={t('tryAgain')} title={t('tryAgain')}
type="gradient" type="gradient"
onPress={props.onTryAgain} onPress={props.onTryAgain}
@@ -79,6 +80,7 @@ export const DualMessageOverlay: React.FC<DualMessageOverlayProps> = props => {
) : null} ) : null}
{!props.children && props.onIgnore ? ( {!props.children && props.onIgnore ? (
<Button <Button
testID='ignore'
type="gradient" type="gradient"
title={t('ignore')} title={t('ignore')}
onPress={props.onIgnore} onPress={props.onIgnore}

View File

@@ -29,7 +29,11 @@ export const EditableListItem: React.FC<EditableListItemProps> = props => {
} }
return ( return (
<ListItem bottomDivider topDivider onPress={() => setIsEditing(true)}> <ListItem
{...testIDProps(props.testID)}
bottomDivider
topDivider
onPress={() => setIsEditing(true)}>
<Icon <Icon
name={props.Icon} name={props.Icon}
type={props.IconType} type={props.IconType}
@@ -37,7 +41,9 @@ export const EditableListItem: React.FC<EditableListItemProps> = props => {
color={Theme.Colors.Icon} color={Theme.Colors.Icon}
/> />
<ListItem.Content> <ListItem.Content>
<ListItem.Title {...testIDProps(props.testID)} style={{paddingTop: 3}}> <ListItem.Title
{...testIDProps(props.testID + 'Title')}
style={{paddingTop: 3}}>
<Text weight="semibold" color={props.titleColor}> <Text weight="semibold" color={props.titleColor}>
{props.title} {props.title}
</Text> </Text>
@@ -57,8 +63,11 @@ export const EditableListItem: React.FC<EditableListItemProps> = props => {
{props.items.map((item: ListItemProps, index) => { {props.items.map((item: ListItemProps, index) => {
return ( return (
<React.Fragment key={index}> <React.Fragment key={index}>
<Text>{t('editLabel', {label: item.label})}</Text> <Text testID={item.testID + 'Label'}>
{t('editLabel', {label: item.label})}
</Text>
<Input <Input
{...testIDProps(item.testID + 'InputField')}
autoFocus autoFocus
value={items[index].value} value={items[index].value}
onChangeText={value => updateItems(item.label, value)} onChangeText={value => updateItems(item.label, value)}
@@ -68,7 +77,9 @@ export const EditableListItem: React.FC<EditableListItemProps> = props => {
}} }}
/> />
{index === 0 && props.response === 'error' && ( {index === 0 && props.response === 'error' && (
<Text style={Theme.TextStyles.error}> <Text
testID={item.testID + 'ErrorMessage'}
style={Theme.TextStyles.error}>
{props.errorMessage} {props.errorMessage}
</Text> </Text>
)} )}
@@ -77,8 +88,15 @@ export const EditableListItem: React.FC<EditableListItemProps> = props => {
})} })}
{props.response === 'success' && overlayOpened && closePopup()} {props.response === 'success' && overlayOpened && closePopup()}
<Row> <Row>
<Button fill type="clear" title={t('cancel')} onPress={dismiss} />
<Button <Button
testID="cancel"
fill
type="clear"
title={t('cancel')}
onPress={dismiss}
/>
<Button
testID="save"
fill fill
title={t('save')} title={t('save')}
onPress={edit} onPress={edit}
@@ -128,4 +146,5 @@ interface EditableListItemProps {
interface ListItemProps { interface ListItemProps {
label: string; label: string;
value: string; value: string;
testID: string;
} }

View File

@@ -15,6 +15,7 @@ export const HelpScreen: React.FC<HelpScreenProps & MainRouteProps> = props => {
return ( return (
<React.Fragment> <React.Fragment>
<Pressable <Pressable
accessible={false}
onPress={() => { onPress={() => {
setShowHelpPage(!showHelpPage); setShowHelpPage(!showHelpPage);
}}> }}>

View File

@@ -17,7 +17,7 @@ export const LanguageSelector: React.FC<LanguageSelectorProps> = props => {
return ( return (
<View> <View>
<Picker <Picker
testID="language" testID="languages"
items={languages} items={languages}
selectedValue={i18n.language} selectedValue={i18n.language}
onValueChange={language => changeLanguage(i18n, language)} onValueChange={language => changeLanguage(i18n, language)}

View File

@@ -24,12 +24,13 @@ export const MessageOverlay: React.FC<MessageOverlayProps> = props => {
onShow={props.onShow} onShow={props.onShow}
onBackdropPress={props.onBackdropPress}> onBackdropPress={props.onBackdropPress}>
<Column <Column
testID={props.testID}
width={Dimensions.get('screen').width * 0.8} width={Dimensions.get('screen').width * 0.8}
style={[Theme.MessageOverlayStyles.popupOverLay, style.customHeight]}> style={[Theme.MessageOverlayStyles.popupOverLay, style.customHeight]}>
<Column padding="21" crossAlign="center"> <Column padding="21" crossAlign="center">
{props.title && ( {props.title && (
<Text <Text
testID={props.testID} testID={props.testID && props.testID + 'Title'}
style={{paddingTop: 3}} style={{paddingTop: 3}}
align="center" align="center"
weight="bold" weight="bold"
@@ -40,6 +41,7 @@ export const MessageOverlay: React.FC<MessageOverlayProps> = props => {
)} )}
{props.message && ( {props.message && (
<Text <Text
testID={props.testID && props.testID + 'Message'}
align="center" align="center"
weight="semibold" weight="semibold"
size="small" size="small"
@@ -51,6 +53,7 @@ export const MessageOverlay: React.FC<MessageOverlayProps> = props => {
{props.progress && <Progress progress={props.progress} />} {props.progress && <Progress progress={props.progress} />}
{props.hint && ( {props.hint && (
<Text <Text
testID={props.testID && props.testID + 'Hint'}
size="smaller" size="smaller"
color={Theme.Colors.textLabel} color={Theme.Colors.textLabel}
margin={[4, 0, 0, 0]}> margin={[4, 0, 0, 0]}>
@@ -61,6 +64,7 @@ export const MessageOverlay: React.FC<MessageOverlayProps> = props => {
</Column> </Column>
{!props.children && props.onButtonPress ? ( {!props.children && props.onButtonPress ? (
<Button <Button
testID="cancel"
type="gradient" type="gradient"
title={props.buttonText ? t(props.buttonText) : t('cancel')} title={props.buttonText ? t(props.buttonText) : t('cancel')}
onPress={props.onButtonPress} onPress={props.onButtonPress}

View File

@@ -5,6 +5,7 @@ import {Centered, Column, Row, Text} from './ui';
import QRCode from 'react-native-qrcode-svg'; import QRCode from 'react-native-qrcode-svg';
import {Theme} from './ui/styleUtils'; import {Theme} from './ui/styleUtils';
import {useTranslation} from 'react-i18next'; import {useTranslation} from 'react-i18next';
import testIDProps from '../shared/commonUtil';
import {SvgImage} from './ui/svg'; import {SvgImage} from './ui/svg';
export const QrCodeOverlay: React.FC<QrCodeOverlayProps> = props => { export const QrCodeOverlay: React.FC<QrCodeOverlayProps> = props => {
@@ -15,10 +16,11 @@ export const QrCodeOverlay: React.FC<QrCodeOverlayProps> = props => {
const toggleQrOverlay = () => setIsQrOverlayVisible(!isQrOverlayVisible); const toggleQrOverlay = () => setIsQrOverlayVisible(!isQrOverlayVisible);
return ( return (
<React.Fragment> <React.Fragment>
<Pressable onPress={toggleQrOverlay}> <Pressable {...testIDProps('qrCodePressable')} onPress={toggleQrOverlay}>
<View style={Theme.QrCodeStyles.QrView}> <View style={Theme.QrCodeStyles.QrView}>
<Row> <Row>
<QRCode <QRCode
{...testIDProps('qrCode')}
size={90} size={90}
value={props.qrCodeDetails} value={props.qrCodeDetails}
backgroundColor={Theme.Colors.QRCodeBackgroundColor} backgroundColor={Theme.Colors.QRCodeBackgroundColor}
@@ -26,6 +28,7 @@ export const QrCodeOverlay: React.FC<QrCodeOverlayProps> = props => {
</Row> </Row>
</View> </View>
<Row <Row
testID="magnifierZoom"
align="flex-end" align="flex-end"
margin="-35 0 0 67" margin="-35 0 0 67"
style={Theme.QrCodeStyles.magnifierZoom}> style={Theme.QrCodeStyles.magnifierZoom}>
@@ -46,6 +49,7 @@ export const QrCodeOverlay: React.FC<QrCodeOverlayProps> = props => {
{t('qrCodeHeader')} {t('qrCodeHeader')}
</Text> </Text>
<Icon <Icon
{...testIDProps('qrCodeCloseIcon')}
name="close" name="close"
onPress={toggleQrOverlay} onPress={toggleQrOverlay}
color={Theme.Colors.Details} color={Theme.Colors.Details}
@@ -54,6 +58,7 @@ export const QrCodeOverlay: React.FC<QrCodeOverlayProps> = props => {
</Row> </Row>
<Centered testID="qrCodeDetails" pY={30}> <Centered testID="qrCodeDetails" pY={30}>
<QRCode <QRCode
{...testIDProps('qrCodeExpandedView')}
size={300} size={300}
value={props.qrCodeDetails} value={props.qrCodeDetails}
backgroundColor={Theme.Colors.QRCodeBackgroundColor} backgroundColor={Theme.Colors.QRCodeBackgroundColor}

View File

@@ -10,6 +10,7 @@ import {useSelector} from '@xstate/react';
import {selectIsActive} from '../machines/app'; import {selectIsActive} from '../machines/app';
import {useTranslation} from 'react-i18next'; import {useTranslation} from 'react-i18next';
import {useScanLayout} from '../screens/Scan/ScanLayoutController'; import {useScanLayout} from '../screens/Scan/ScanLayoutController';
import testIDProps from '../shared/commonUtil';
import {SvgImage} from './ui/svg'; import {SvgImage} from './ui/svg';
export const QrScanner: React.FC<QrScannerProps> = props => { export const QrScanner: React.FC<QrScannerProps> = props => {
@@ -48,16 +49,20 @@ export const QrScanner: React.FC<QrScannerProps> = props => {
const CameraDisabledPopUp: React.FC = () => { const CameraDisabledPopUp: React.FC = () => {
return ( return (
<View style={Theme.Styles.cameraDisabledPopupContainer}> <View
{...testIDProps('cameraDisabledPopup')}
style={Theme.Styles.cameraDisabledPopupContainer}>
<Row style={Theme.Styles.cameraDisabledPopUp}> <Row style={Theme.Styles.cameraDisabledPopUp}>
<Column style={{flex: 1}}> <Column style={{flex: 1}}>
<Text <Text
testID="cameraAccessDisabled"
color={Theme.Colors.whiteText} color={Theme.Colors.whiteText}
weight="semibold" weight="semibold"
margin="0 0 5 0"> margin="0 0 5 0">
{t('cameraAccessDisabled')} {t('cameraAccessDisabled')}
</Text> </Text>
<Text <Text
testID="cameraPermissionGuide"
color={Theme.Colors.whiteText} color={Theme.Colors.whiteText}
size="regular" size="regular"
style={{opacity: 0.8}}> style={{opacity: 0.8}}>
@@ -66,6 +71,7 @@ export const QrScanner: React.FC<QrScannerProps> = props => {
</Column> </Column>
<Pressable> <Pressable>
<Icon <Icon
testID="close"
name="close" name="close"
onPress={controller.DISMISS} onPress={controller.DISMISS}
color={Theme.Colors.whiteText} color={Theme.Colors.whiteText}
@@ -81,6 +87,7 @@ export const QrScanner: React.FC<QrScannerProps> = props => {
<View style={Theme.Styles.scannerContainer}> <View style={Theme.Styles.scannerContainer}>
{hasPermission ? ( {hasPermission ? (
<Camera <Camera
{...testIDProps('camera')}
style={Theme.Styles.scanner} style={Theme.Styles.scanner}
barCodeScannerSettings={{ barCodeScannerSettings={{
barcodeTypes: [BarCodeScanner.Constants.BarCodeType.qr], barcodeTypes: [BarCodeScanner.Constants.BarCodeType.qr],
@@ -94,6 +101,7 @@ export const QrScanner: React.FC<QrScannerProps> = props => {
</View> </View>
{props.title && ( {props.title && (
<Text <Text
testID="holdPhoneSteadyMessage"
align="center" align="center"
weight="semibold" weight="semibold"
style={Theme.TextStyles.base} style={Theme.TextStyles.base}
@@ -113,7 +121,7 @@ export const QrScanner: React.FC<QrScannerProps> = props => {
}}> }}>
{SvgImage.FlipCameraIcon()} {SvgImage.FlipCameraIcon()}
</TouchableOpacity> </TouchableOpacity>
<Text size="small" weight="semibold" margin="8"> <Text testID="flipCameraText" size="small" weight="semibold" margin="8">
{t('flipCamera')} {t('flipCamera')}
</Text> </Text>
</Column> </Column>

View File

@@ -3,6 +3,7 @@ import {Dimensions, Pressable} from 'react-native';
import {Icon, ListItem, Overlay} from 'react-native-elements'; import {Icon, ListItem, Overlay} from 'react-native-elements';
import {Column} from './Layout'; import {Column} from './Layout';
import {Text} from './Text'; import {Text} from './Text';
import testIDProps from '../../shared/commonUtil';
interface Picker extends React.VFC<PickerProps<unknown>> { interface Picker extends React.VFC<PickerProps<unknown>> {
<T>(props: PickerProps<T>): ReturnType<React.FC>; <T>(props: PickerProps<T>): ReturnType<React.FC>;
@@ -38,7 +39,7 @@ export const Picker: Picker = (props: PickerProps<unknown>) => {
width={Dimensions.get('window').width * 0.8}> width={Dimensions.get('window').width * 0.8}>
{props.items.map((item, index) => ( {props.items.map((item, index) => (
<ListItem <ListItem
testID={item.value} {...testIDProps(item.value as string)}
topDivider={index !== 0} topDivider={index !== 0}
onPress={() => selectItem(index)} onPress={() => selectItem(index)}
key={index}> key={index}>

View File

@@ -160,6 +160,7 @@ export class SvgImage {
const {width, height} = Theme.Styles.cameraFlipIcon; const {width, height} = Theme.Styles.cameraFlipIcon;
return ( return (
<FlipCameraIcon <FlipCameraIcon
{...testIDProps('flipCameraIcon')}
color1={Theme.Colors.linearGradientStart} color1={Theme.Colors.linearGradientStart}
color2={Theme.Colors.linearGradientEnd} color2={Theme.Colors.linearGradientEnd}
width={width} width={width}

View File

@@ -6,7 +6,7 @@ PODS:
- AppAuth/ExternalUserAgent (1.6.2): - AppAuth/ExternalUserAgent (1.6.2):
- AppAuth/Core - AppAuth/Core
- ASN1Decoder (1.8.0) - ASN1Decoder (1.8.0)
- biometric-sdk-react-native (0.2.4): - biometric-sdk-react-native (0.2.6):
- BiometricSdk (= 0.5.9) - BiometricSdk (= 0.5.9)
- React-Core - React-Core
- BiometricSdk (0.5.9): - BiometricSdk (0.5.9):
@@ -369,7 +369,7 @@ PODS:
- ReactCommon/turbomodule/core - ReactCommon/turbomodule/core
- react-native-secure-key-store (2.0.10): - react-native-secure-key-store (2.0.10):
- React-Core - React-Core
- react-native-secure-keystore (0.1.1): - react-native-secure-keystore (0.1.2):
- React-Core - React-Core
- react-native-spinkit (1.4.1): - react-native-spinkit (1.4.1):
- React - React
@@ -778,7 +778,7 @@ EXTERNAL SOURCES:
SPEC CHECKSUMS: SPEC CHECKSUMS:
AppAuth: 3bb1d1cd9340bd09f5ed189fb00b1cc28e1e8570 AppAuth: 3bb1d1cd9340bd09f5ed189fb00b1cc28e1e8570
ASN1Decoder: 6110fdeacfdb41559b1481457a1645be716610aa ASN1Decoder: 6110fdeacfdb41559b1481457a1645be716610aa
biometric-sdk-react-native: 5d1207e0d9ee34788cb4ccb59cfc205022d7e3f1 biometric-sdk-react-native: d2a3a1279013cc4a7514a1b43fe557eb76e4e4c1
BiometricSdk: 303e7329404ea4d922dc14108449d10d21574f77 BiometricSdk: 303e7329404ea4d922dc14108449d10d21574f77
boost: 57d2868c099736d80fcd648bf211b4431e51a558 boost: 57d2868c099736d80fcd648bf211b4431e51a558
BVLinearGradient: 916632041121a658c704df89d99f04acb038de0f BVLinearGradient: 916632041121a658c704df89d99f04acb038de0f
@@ -840,7 +840,7 @@ SPEC CHECKSUMS:
react-native-rsa-native: 12132eb627797529fdb1f0d22fd0f8f9678df64a react-native-rsa-native: 12132eb627797529fdb1f0d22fd0f8f9678df64a
react-native-safe-area-context: 39c2d8be3328df5d437ac1700f4f3a4f75716acc react-native-safe-area-context: 39c2d8be3328df5d437ac1700f4f3a4f75716acc
react-native-secure-key-store: 910e6df6bc33cb790aba6ee24bc7818df1fe5898 react-native-secure-key-store: 910e6df6bc33cb790aba6ee24bc7818df1fe5898
react-native-secure-keystore: d9e791a495d23c33db7711732f3a761533b882db react-native-secure-keystore: 2396168e3fac38697297bc0b716d87f8683e689f
react-native-spinkit: da294fd828216ad211fe36a5c14c1e09f09e62db react-native-spinkit: da294fd828216ad211fe36a5c14c1e09f09e62db
react-native-tuvali: bd369208d58ff9e1528c2a76dce126f60d7fd35d react-native-tuvali: bd369208d58ff9e1528c2a76dce126f60d7fd35d
React-perflogger: d21f182895de9d1b077f8a3cd00011095c8c9100 React-perflogger: d21f182895de9d1b077f8a3cd00011095c8c9100
@@ -876,4 +876,4 @@ SPEC CHECKSUMS:
PODFILE CHECKSUM: 01f58b130fa221dabb14b2d82d981ef24dcaba53 PODFILE CHECKSUM: 01f58b130fa221dabb14b2d82d981ef24dcaba53
COCOAPODS: 1.14.2 COCOAPODS: 1.14.3

View File

@@ -15,6 +15,7 @@ import LinearGradient from 'react-native-linear-gradient';
import {EsignetMosipVCItemMachine} from '../../machines/VCItemMachine/EsignetMosipVCItem/EsignetMosipVCItemMachine'; import {EsignetMosipVCItemMachine} from '../../machines/VCItemMachine/EsignetMosipVCItem/EsignetMosipVCItemMachine';
import {ErrorMessageOverlay} from '../../components/MessageOverlay'; import {ErrorMessageOverlay} from '../../components/MessageOverlay';
import {Pressable} from 'react-native'; import {Pressable} from 'react-native';
import testIDProps from '../../shared/commonUtil';
export const HomeScreen: React.FC<HomeRouteProps> = props => { export const HomeScreen: React.FC<HomeRouteProps> = props => {
const {t} = useTranslation('HomeScreen'); const {t} = useTranslation('HomeScreen');
@@ -35,6 +36,8 @@ export const HomeScreen: React.FC<HomeRouteProps> = props => {
const DownloadFABIcon: React.FC = () => { const DownloadFABIcon: React.FC = () => {
const plusIcon = ( const plusIcon = (
<Icon <Icon
{...testIDProps('plusIcon')}
accessible={true}
name={'plus'} name={'plus'}
type={'entypo'} type={'entypo'}
size={36} size={36}
@@ -49,7 +52,8 @@ export const HomeScreen: React.FC<HomeRouteProps> = props => {
onPress={() => { onPress={() => {
controller.GOTO_ISSUERS(); controller.GOTO_ISSUERS();
}} }}
testID="downloadIcon" {...testIDProps('downloadCardButton')}
accessible={false}
style={({pressed}) => style={({pressed}) =>
pressed pressed
? Theme.Styles.downloadFabIconPressed ? Theme.Styles.downloadFabIconPressed

View File

@@ -43,7 +43,7 @@ export const GetIdInputModal: React.FC<GetIdInputModalProps> = props => {
</Text> </Text>
<Row crossAlign="flex-end"> <Row crossAlign="flex-end">
<Input <Input
{...testIDProps('getIdInput')} {...testIDProps('getIdInputModalIndividualId')}
placeholder={!controller.id ? inputLabel : ''} placeholder={!controller.id ? inputLabel : ''}
labelStyle={{ labelStyle={{
color: controller.isInvalid color: controller.isInvalid

View File

@@ -59,7 +59,7 @@ export const IdInputModal: React.FC<IdInputModalProps> = props => {
<Row crossAlign="flex-end" style={Theme.Styles.idInputContainer}> <Row crossAlign="flex-end" style={Theme.Styles.idInputContainer}>
<Column style={Theme.Styles.idInputPicker}> <Column style={Theme.Styles.idInputPicker}>
<Picker <Picker
testID="selectIdType" {...testIDProps('selectIdTypePicker')}
selectedValue={controller.idType} selectedValue={controller.idType}
onValueChange={controller.SELECT_ID_TYPE}> onValueChange={controller.SELECT_ID_TYPE}>
<Picker.Item label="UIN" value="UIN" /> <Picker.Item label="UIN" value="UIN" />
@@ -67,7 +67,7 @@ export const IdInputModal: React.FC<IdInputModalProps> = props => {
</Picker> </Picker>
</Column> </Column>
<Input <Input
{...testIDProps('idInput')} {...testIDProps('idInputModalIndividualId')}
placeholder={!controller.id ? inputLabel : ''} placeholder={!controller.id ? inputLabel : ''}
inputContainerStyle={ inputContainerStyle={
controller.id ? Theme.Styles.idInputBottom : null controller.id ? Theme.Styles.idInputBottom : null
@@ -106,7 +106,7 @@ export const IdInputModal: React.FC<IdInputModalProps> = props => {
</Text> </Text>
<TouchableOpacity activeOpacity={1} onPress={props.onPress}> <TouchableOpacity activeOpacity={1} onPress={props.onPress}>
<Text <Text
testID="getItHere" testID="getItNow"
color={Theme.Colors.AddIdBtnBg} color={Theme.Colors.AddIdBtnBg}
weight="bold" weight="bold"
size="small" size="small"

View File

@@ -121,6 +121,7 @@ export const ViewVcModal: React.FC<ViewVcModalProps> = props => {
/> />
<MessageOverlay <MessageOverlay
testID='walletBindingError'
isVisible={controller.isBindingError} isVisible={controller.isBindingError}
title={controller.walletBindingError} title={controller.walletBindingError}
onButtonPress={() => { onButtonPress={() => {

View File

@@ -11,6 +11,7 @@ import {RootRouteProps} from '../routes';
import {HomeScreen} from './Home/HomeScreen'; import {HomeScreen} from './Home/HomeScreen';
import {IssuersScreen} from './Issuers/IssuersScreen'; import {IssuersScreen} from './Issuers/IssuersScreen';
import {SettingScreen} from './Settings/SettingScreen'; import {SettingScreen} from './Settings/SettingScreen';
import testIDProps from '../shared/commonUtil';
import {SvgImage} from '../components/ui/svg'; import {SvgImage} from '../components/ui/svg';
const {Navigator, Screen} = createNativeStackNavigator(); const {Navigator, Screen} = createNativeStackNavigator();
@@ -51,6 +52,8 @@ export const HomeScreenLayout: React.FC<RootRouteProps> = props => {
<HelpScreen <HelpScreen
triggerComponent={ triggerComponent={
<Icon <Icon
{...testIDProps('help')}
accessible={true}
name="question" name="question"
type="font-awesome" type="font-awesome"
size={21} size={21}
@@ -65,6 +68,8 @@ export const HomeScreenLayout: React.FC<RootRouteProps> = props => {
<SettingScreen <SettingScreen
triggerComponent={ triggerComponent={
<Icon <Icon
{...testIDProps('settings')}
accessible={true}
name="settings" name="settings"
type="simple-line-icon" type="simple-line-icon"
size={21} size={21}

View File

@@ -133,6 +133,7 @@ export const IssuersScreen: React.FC<
margin={[0, 8, 0, 0]} margin={[0, 8, 0, 0]}
/> />
<Button <Button
testID="tryAgain"
fill fill
title={t('common:tryAgain')} title={t('common:tryAgain')}
onPress={controller.TRY_AGAIN} onPress={controller.TRY_AGAIN}

View File

@@ -32,7 +32,12 @@ export const MainLayout: React.FC<
}; };
return ( return (
<Navigator initialRouteName={mainRoutes[0].name} screenOptions={options}> <Navigator
initialRouteName={mainRoutes[0].name}
screenOptions={({route}) => ({
tabBarAccessibilityLabel: route.name,
options,
})}>
{mainRoutes.map(route => ( {mainRoutes.map(route => (
<Screen <Screen
key={route.name} key={route.name}
@@ -50,7 +55,7 @@ export const MainLayout: React.FC<
title: t(route.name), title: t(route.name),
tabBarIcon: ({focused}) => ( tabBarIcon: ({focused}) => (
<Icon <Icon
{...testIDProps(route.name)} {...testIDProps(route.name + 'Icon')}
name={route.icon} name={route.icon}
color={focused ? Theme.Colors.Icon : Theme.Colors.GrayIcon} color={focused ? Theme.Colors.Icon : Theme.Colors.GrayIcon}
style={focused ? Theme.Styles.bottomTabIconStyle : null} style={focused ? Theme.Styles.bottomTabIconStyle : null}

View File

@@ -44,6 +44,7 @@ export const QrLogin: React.FC<QrLoginProps> = props => {
isVisible={controller.isShowingError} isVisible={controller.isShowingError}
title={controller.error} title={controller.error}
onButtonPress={controller.DISMISS} onButtonPress={controller.DISMISS}
testID='qrLoginError'
/> />
<VerifyIdentityOverlay <VerifyIdentityOverlay
@@ -68,6 +69,7 @@ export const QrLogin: React.FC<QrLoginProps> = props => {
margin={[0, 8, 0, 0]} margin={[0, 8, 0, 0]}
/> />
<Button <Button
testID='tryAgain'
fill fill
title={t('common:tryAgain')} title={t('common:tryAgain')}
onPress={controller.RETRY_VERIFICATION} onPress={controller.RETRY_VERIFICATION}

View File

@@ -70,6 +70,7 @@ export const ReceiveVcScreen: React.FC = () => {
margin={[0, 8, 0, 0]} margin={[0, 8, 0, 0]}
/> />
<Button <Button
testID='tryAgain'
fill fill
title={t('common:tryAgain')} title={t('common:tryAgain')}
onPress={controller.RETRY_VERIFICATION} onPress={controller.RETRY_VERIFICATION}

View File

@@ -6,7 +6,7 @@ import {Centered, Button, Column, Text} from '../../components/ui';
import {Theme} from '../../components/ui/styleUtils'; import {Theme} from '../../components/ui/styleUtils';
import {useRequestScreen} from './RequestScreenController'; import {useRequestScreen} from './RequestScreenController';
import BluetoothStateManager from 'react-native-bluetooth-state-manager'; import BluetoothStateManager from 'react-native-bluetooth-state-manager';
import {Platform} from 'react-native'; import {Platform, View} from 'react-native';
import Storage from '../../shared/storage'; import Storage from '../../shared/storage';
import {ErrorMessageOverlay} from '../../components/MessageOverlay'; import {ErrorMessageOverlay} from '../../components/MessageOverlay';
import { import {
@@ -18,6 +18,7 @@ import {MainBottomTabParamList} from '../../routes/main';
import {BOTTOM_TAB_ROUTES} from '../../routes/routesConstants'; import {BOTTOM_TAB_ROUTES} from '../../routes/routesConstants';
import {ProgressingModal} from '../../components/ProgressingModal'; import {ProgressingModal} from '../../components/ProgressingModal';
import {isIOS} from '../../shared/constants'; import {isIOS} from '../../shared/constants';
import testIDProps from '../../shared/commonUtil';
type RequestStackParamList = { type RequestStackParamList = {
RequestScreen: undefined; RequestScreen: undefined;
@@ -106,7 +107,11 @@ export const RequestScreen: React.FC = () => {
const BluetoothPrompt: React.FC<RequestScreenProps> = ({t}) => { const BluetoothPrompt: React.FC<RequestScreenProps> = ({t}) => {
return ( return (
<Centered fill> <Centered fill>
<Text color={Theme.Colors.errorMessage} align="center" margin="0 10"> <Text
testID="bluetoothIsTurnedOffMessage"
color={Theme.Colors.errorMessage}
align="center"
margin="0 10">
{t(isIOS() ? 'bluetoothStateIos' : 'bluetoothStateAndroid')} {t(isIOS() ? 'bluetoothStateIos' : 'bluetoothStateAndroid')}
</Text> </Text>
</Centered> </Centered>
@@ -117,11 +122,15 @@ const NearByPrompt: React.FC<RequestScreenProps> = ({t, controller}) => {
return ( return (
<Column fill align="space-between"> <Column fill align="space-between">
<Centered fill> <Centered fill>
<Text color={Theme.Colors.errorMessage} align="center"> <Text
testID="allowNearbyDevicesPermissionMessage"
color={Theme.Colors.errorMessage}
align="center">
{t('errors.nearbyDevicesPermissionDenied.message')} {t('errors.nearbyDevicesPermissionDenied.message')}
</Text> </Text>
</Centered> </Centered>
<Button <Button
testID="allowNearbyDevicesPermissionButton"
title={t('errors.nearbyDevicesPermissionDenied.button')} title={t('errors.nearbyDevicesPermissionDenied.button')}
onPress={controller.GOTO_SETTINGS} onPress={controller.GOTO_SETTINGS}
/> />
@@ -132,15 +141,19 @@ const NearByPrompt: React.FC<RequestScreenProps> = ({t, controller}) => {
const SharingQR: React.FC<RequestScreenProps> = ({t, controller}) => { const SharingQR: React.FC<RequestScreenProps> = ({t, controller}) => {
return ( return (
<React.Fragment> <React.Fragment>
<Text align="center">{t('showQrCode')}</Text> <Text testID="showQrCode" align="center">
{t('showQrCode')}
</Text>
<Centered fill> <Centered fill>
{controller.openId4VpUri !== '' ? ( {controller.openId4VpUri !== '' ? (
<QRCode <View {...testIDProps('qrCode')}>
size={200} <QRCode
value={controller.openId4VpUri} size={200}
backgroundColor={Theme.Colors.QRCodeBackgroundColor} value={controller.openId4VpUri}
/> backgroundColor={Theme.Colors.QRCodeBackgroundColor}
/>
</View>
) : null} ) : null}
</Centered> </Centered>
</React.Fragment> </React.Fragment>
@@ -150,10 +163,15 @@ const SharingQR: React.FC<RequestScreenProps> = ({t, controller}) => {
const StatusMessage: React.FC<RequestScreenProps> = ({t, controller}) => { const StatusMessage: React.FC<RequestScreenProps> = ({t, controller}) => {
return ( return (
controller.statusMessage !== '' && ( controller.statusMessage !== '' && (
<Column elevation={1} padding="16 24"> <Column testID='recievedCardStatus' elevation={1} padding="16 24">
<Text>{controller.statusMessage}</Text> <Text testID="receiveCardStatusMessage">
{controller.statusMessage}
</Text>
{controller.statusHint !== '' && ( {controller.statusHint !== '' && (
<Text size="small" color={Theme.Colors.textLabel}> <Text
testID="receiveCardStatusHint"
size="small"
color={Theme.Colors.textLabel}>
{controller.statusHint} {controller.statusHint}
</Text> </Text>
)} )}

View File

@@ -46,6 +46,7 @@ export const ScanScreen: React.FC = () => {
function noShareableVcText() { function noShareableVcText() {
return ( return (
<Text <Text
testID="noShareableVcs"
align="center" align="center"
style={{paddingTop: 3}} style={{paddingTop: 3}}
color={Theme.Colors.errorMessage} color={Theme.Colors.errorMessage}
@@ -57,7 +58,7 @@ export const ScanScreen: React.FC = () => {
function bluetoothIsOffText() { function bluetoothIsOffText() {
return ( return (
<Text align="center" color={Theme.Colors.errorMessage} margin="0 10"> <Text testID="bluetoothIsTurnedOffMessage" align="center" color={Theme.Colors.errorMessage} margin="0 10">
{t(isIOS() ? 'bluetoothStateIos' : 'bluetoothStateAndroid')} {t(isIOS() ? 'bluetoothStateIos' : 'bluetoothStateAndroid')}
</Text> </Text>
); );
@@ -87,12 +88,16 @@ export const ScanScreen: React.FC = () => {
return ( return (
<Column padding="24" fill align="space-between"> <Column padding="24" fill align="space-between">
<Centered fill> <Centered fill>
<Text align="center" color={Theme.Colors.errorMessage}> <Text
testID="allowNearbyDevicesPermissionMessage"
align="center"
color={Theme.Colors.errorMessage}>
{t('errors.nearbyDevicesPermissionDenied.message')} {t('errors.nearbyDevicesPermissionDenied.message')}
</Text> </Text>
</Centered> </Centered>
<Button <Button
testID="allowNearbyDevicesPermissionButton"
title={t('errors.nearbyDevicesPermissionDenied.button')} title={t('errors.nearbyDevicesPermissionDenied.button')}
onPress={openSettings}></Button> onPress={openSettings}></Button>
</Column> </Column>
@@ -103,12 +108,16 @@ export const ScanScreen: React.FC = () => {
return ( return (
<Column padding="24" fill align="space-between"> <Column padding="24" fill align="space-between">
<Centered fill> <Centered fill>
<Text align="center" color={Theme.Colors.errorMessage}> <Text
testID="enableLocationServicesMessage"
align="center"
color={Theme.Colors.errorMessage}>
{controller.locationError.message} {controller.locationError.message}
</Text> </Text>
</Centered> </Centered>
<Button <Button
testID="enableLocationServicesButton"
title={controller.locationError.button} title={controller.locationError.button}
onPress={controller.LOCATION_REQUEST} onPress={controller.LOCATION_REQUEST}
/> />
@@ -156,6 +165,7 @@ export const ScanScreen: React.FC = () => {
return ( return (
!controller.isEmpty && ( !controller.isEmpty && (
<MessageOverlay <MessageOverlay
testID="storageLimitReachedError"
isVisible={ isVisible={
controller.isMinimumStorageRequiredForAuditEntryLimitReached controller.isMinimumStorageRequiredForAuditEntryLimitReached
} }
@@ -171,13 +181,14 @@ export const ScanScreen: React.FC = () => {
return ( return (
!controller.isEmpty && ( !controller.isEmpty && (
<MessageOverlay <MessageOverlay
testID='invalidQrPopup'
isVisible={controller.selectIsInvalid} isVisible={controller.selectIsInvalid}
customHeight={'auto'} customHeight={'auto'}
title={t('invalidQR')} title={t('invalidQR')}
message
onBackdropPress={controller.DISMISS}> onBackdropPress={controller.DISMISS}>
<Row> <Row>
<Button <Button
testID='cancel'
fill fill
type="clear" type="clear"
title={t('common:cancel')} title={t('common:cancel')}
@@ -185,6 +196,7 @@ export const ScanScreen: React.FC = () => {
margin={[0, 8, 0, 0]} margin={[0, 8, 0, 0]}
/> />
<Button <Button
testID='tryAgain'
fill fill
title={t('common:tryAgain')} title={t('common:tryAgain')}
onPress={controller.DISMISS} onPress={controller.DISMISS}

View File

@@ -143,6 +143,7 @@ export const SendVcScreen: React.FC = () => {
onBackdropPress={controller.DISMISS}> onBackdropPress={controller.DISMISS}>
<Row> <Row>
<Button <Button
testID='cancel'
fill fill
type="clear" type="clear"
title={t('common:cancel')} title={t('common:cancel')}
@@ -150,6 +151,7 @@ export const SendVcScreen: React.FC = () => {
margin={[0, 8, 0, 0]} margin={[0, 8, 0, 0]}
/> />
<Button <Button
testID='tryAgain'
fill fill
title={t('common:tryAgain')} title={t('common:tryAgain')}
onPress={controller.RETRY_VERIFICATION} onPress={controller.RETRY_VERIFICATION}

View File

@@ -34,7 +34,7 @@ export const AboutInji: React.FC<AboutInjiProps> = ({appId}) => {
onPress={() => { onPress={() => {
setShowAboutInji(!showAboutInji); setShowAboutInji(!showAboutInji);
}}> }}>
<ListItem testID="aboutInji" topDivider bottomDivider> <ListItem {...testIDProps('aboutInji')} topDivider bottomDivider>
<Icon <Icon
type={'feather'} type={'feather'}
name={'file'} name={'file'}
@@ -43,7 +43,7 @@ export const AboutInji: React.FC<AboutInjiProps> = ({appId}) => {
/> />
<ListItem.Content> <ListItem.Content>
<ListItem.Title <ListItem.Title
{...testIDProps('aboutInji')} {...testIDProps('aboutInjiTitle')}
style={{paddingTop: 3}}> style={{paddingTop: 3}}>
<Text weight="semibold" color={Theme.Colors.settingsLabel}> <Text weight="semibold" color={Theme.Colors.settingsLabel}>
{t('aboutInji')} {t('aboutInji')}
@@ -122,6 +122,7 @@ export const AboutInji: React.FC<AboutInjiProps> = ({appId}) => {
style={Theme.Styles.versionContainer}> style={Theme.Styles.versionContainer}>
<Row> <Row>
<Text <Text
testID="tuvaliVersion"
weight="semibold" weight="semibold"
style={{paddingTop: 3}} style={{paddingTop: 3}}
color={Theme.Colors.aboutVersion}> color={Theme.Colors.aboutVersion}>

View File

@@ -6,6 +6,7 @@ import {Theme} from '../../components/ui/styleUtils';
import {Image} from 'react-native'; import {Image} from 'react-native';
import {useReceivedVcsTab} from '../Home/ReceivedVcsTabController'; import {useReceivedVcsTab} from '../Home/ReceivedVcsTabController';
import {ReceivedCardsModal} from './ReceivedCardsModal'; import {ReceivedCardsModal} from './ReceivedCardsModal';
import testIDProps from '../../shared/commonUtil';
import {SvgImage} from '../../components/ui/svg'; import {SvgImage} from '../../components/ui/svg';
export const ReceivedCards: React.FC = () => { export const ReceivedCards: React.FC = () => {
@@ -14,7 +15,9 @@ export const ReceivedCards: React.FC = () => {
return ( return (
<React.Fragment> <React.Fragment>
<Pressable onPress={controller.TOGGLE_RECEIVED_CARDS}> <Pressable
{...testIDProps('receivedCardsPressableArea')}
onPress={controller.TOGGLE_RECEIVED_CARDS}>
<Column align="center" style={Theme.Styles.receiveCardsContainer}> <Column align="center" style={Theme.Styles.receiveCardsContainer}>
{SvgImage.ReceivedCards()} {SvgImage.ReceivedCards()}
<Text <Text

View File

@@ -16,6 +16,7 @@ export const ReceivedCardsModal: React.FC<ReceivedCardsProps> = ({
const {t} = useTranslation('ReceivedVcsTab'); const {t} = useTranslation('ReceivedVcsTab');
return ( return (
<Modal <Modal
testID='receivedCardsModal'
isVisible={isVisible} isVisible={isVisible}
arrowLeft={<Icon name={''} />} arrowLeft={<Icon name={''} />}
headerTitle={t('header')} headerTitle={t('header')}

View File

@@ -24,7 +24,7 @@ const LanguageSetting: React.FC = () => {
return ( return (
<LanguageSelector <LanguageSelector
triggerComponent={ triggerComponent={
<ListItem> <ListItem {...testIDProps('language')}>
<Icon <Icon
name="globe" name="globe"
size={22} size={22}
@@ -33,7 +33,7 @@ const LanguageSetting: React.FC = () => {
/> />
<ListItem.Content> <ListItem.Content>
<ListItem.Title <ListItem.Title
{...testIDProps('language')} {...testIDProps('languageTitle')}
style={{paddingTop: 3}}> style={{paddingTop: 3}}>
<Text weight="semibold" color={Theme.Colors.settingsLabel}> <Text weight="semibold" color={Theme.Colors.settingsLabel}>
{t('language')} {t('language')}
@@ -41,6 +41,7 @@ const LanguageSetting: React.FC = () => {
</ListItem.Title> </ListItem.Title>
</ListItem.Content> </ListItem.Content>
<Icon <Icon
{...testIDProps('chevronRightIcon')}
name="chevron-right" name="chevron-right"
size={21} size={21}
color={Theme.Colors.chevronRightColor} color={Theme.Colors.chevronRightColor}
@@ -64,7 +65,7 @@ export const SettingScreen: React.FC<
return ( return (
<React.Fragment> <React.Fragment>
<Pressable onPress={controller.TOGGLE_SETTINGS}> <Pressable accessible={false} onPress={controller.TOGGLE_SETTINGS}>
{props.triggerComponent} {props.triggerComponent}
</Pressable> </Pressable>
<Modal <Modal
@@ -89,7 +90,9 @@ export const SettingScreen: React.FC<
<Row <Row
align="space-evenly" align="space-evenly"
backgroundColor={Theme.Colors.whiteBackgroundColor}> backgroundColor={Theme.Colors.whiteBackgroundColor}>
<Pressable onPress={controller.RECEIVE_CARD}> <Pressable
{...testIDProps('receiveCardPressableArea')}
onPress={controller.RECEIVE_CARD}>
<Column <Column
align="center" align="center"
style={Theme.Styles.receiveCardsContainer}> style={Theme.Styles.receiveCardsContainer}>
@@ -165,10 +168,12 @@ export const SettingScreen: React.FC<
{ {
label: t('credentialRegistry'), label: t('credentialRegistry'),
value: controller.credentialRegistry, value: controller.credentialRegistry,
testID: 'credentialRegistry',
}, },
{ {
label: t('esignethosturl'), label: t('esignethosturl'),
value: controller.esignetHostUrl, value: controller.esignetHostUrl,
testID: 'esignetHost',
}, },
]} ]}
response={controller.credentialRegistryResponse} response={controller.credentialRegistryResponse}