diff --git a/assets/images/expensify-logo--adhoc.svg b/assets/images/expensify-logo--adhoc.svg
index 6a4b393a5fc5..273002deca9b 100644
--- a/assets/images/expensify-logo--adhoc.svg
+++ b/assets/images/expensify-logo--adhoc.svg
@@ -1 +1 @@
-
+
diff --git a/assets/images/expensify-logo--dev.svg b/assets/images/expensify-logo--dev.svg
index c9e21d55f3a2..e8e3fb5033d9 100644
--- a/assets/images/expensify-logo--dev.svg
+++ b/assets/images/expensify-logo--dev.svg
@@ -1 +1 @@
-
+
diff --git a/assets/images/expensify-logo--staging.svg b/assets/images/expensify-logo--staging.svg
index a3cd345fc186..78dcc1581f99 100644
--- a/assets/images/expensify-logo--staging.svg
+++ b/assets/images/expensify-logo--staging.svg
@@ -1 +1 @@
-
+
diff --git a/ios/Podfile.lock b/ios/Podfile.lock
index 3597afe23355..66eb16da53f9 100644
--- a/ios/Podfile.lock
+++ b/ios/Podfile.lock
@@ -35,7 +35,7 @@ PODS:
- ExpoModulesCore
- Expo (49.0.13):
- ExpoModulesCore
- - ExpoImage (1.6.0):
+ - ExpoImage (1.7.0):
- ExpoModulesCore
- SDWebImage (~> 5.17.0)
- SDWebImageAVIFCoder (~> 0.10.1)
@@ -1217,7 +1217,7 @@ SPEC CHECKSUMS:
DoubleConversion: 5189b271737e1565bdce30deb4a08d647e3f5f54
EXApplication: 042aa2e3f05258a16962ea1a9914bf288db9c9a1
Expo: e7d2116b947e2e6fdeb09ee4f2754f819426d1b6
- ExpoImage: 64cd716d10414edf59342de32043857a58e9a2a3
+ ExpoImage: d765c73f5373f52f2c96bdd4a664c80d827446c0
ExpoModulesCore: 51cb2e7ab4c8da14be3f40b66d54c1781002e99d
FBLazyVector: 5d4a3b7f411219a45a6d952f77d2c0a6c9989da5
FBReactNativeSpec: 3fc2d478e1c4b08276f9dd9128f80ec6d5d85c1f
diff --git a/package-lock.json b/package-lock.json
index a60d0cbaa9e6..a93b482bc004 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -54,7 +54,7 @@
"expensify-common": "git+ssh://git@github.com/Expensify/expensify-common.git#82bfcd1cb077afd03d1c8c069618c7dd5bd405d8",
"expo": "^49.0.0",
"expo-asset": "~8.10.1",
- "expo-image": "^1.6.0",
+ "expo-image": "^1.7.0",
"fbjs": "^3.0.2",
"htmlparser2": "^7.2.0",
"idb-keyval": "^6.2.1",
@@ -32393,9 +32393,9 @@
}
},
"node_modules/expo-image": {
- "version": "1.6.0",
- "resolved": "https://registry.npmjs.org/expo-image/-/expo-image-1.6.0.tgz",
- "integrity": "sha512-DjTubSHJHHUyQ2AU3FGoU2mtmb6fIDQw0ccMMWPX0vvXo6o1c1AbXPuQnIp8/sQy11ZhaKB3BLV3jWIU4c+qeQ==",
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/expo-image/-/expo-image-1.7.0.tgz",
+ "integrity": "sha512-tHI7ADaqAd2lzSI0MlZ6K4JzaU+s7Q4xWm2o1FRvQeheqETIjdgOMBhWwzCno+xaxbJDSWhbMwWMsbjB3zmLHw==",
"peerDependencies": {
"expo": "*"
}
@@ -39757,6 +39757,11 @@
"node": ">=8"
}
},
+ "node_modules/jimp-compact": {
+ "version": "0.16.1",
+ "resolved": "https://registry.npmjs.org/jimp-compact/-/jimp-compact-0.16.1.tgz",
+ "integrity": "sha512-dZ6Ra7u1G8c4Letq/B5EzAxj4tLFHL+cGtdpR+PVm4yzPDj+lCk+AbivWt1eOM+ikzkowtyV7qSqX6qr3t71Ww=="
+ },
"node_modules/jiti": {
"version": "1.20.0",
"resolved": "https://registry.npmjs.org/jiti/-/jiti-1.20.0.tgz",
@@ -53575,6 +53580,11 @@
"node": ">=6.10"
}
},
+ "node_modules/ts-interface-checker": {
+ "version": "0.1.13",
+ "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz",
+ "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA=="
+ },
"node_modules/ts-object-utils": {
"version": "0.0.5",
"resolved": "https://registry.npmjs.org/ts-object-utils/-/ts-object-utils-0.0.5.tgz",
@@ -80150,9 +80160,9 @@
}
},
"expo-image": {
- "version": "1.6.0",
- "resolved": "https://registry.npmjs.org/expo-image/-/expo-image-1.6.0.tgz",
- "integrity": "sha512-DjTubSHJHHUyQ2AU3FGoU2mtmb6fIDQw0ccMMWPX0vvXo6o1c1AbXPuQnIp8/sQy11ZhaKB3BLV3jWIU4c+qeQ==",
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/expo-image/-/expo-image-1.7.0.tgz",
+ "integrity": "sha512-tHI7ADaqAd2lzSI0MlZ6K4JzaU+s7Q4xWm2o1FRvQeheqETIjdgOMBhWwzCno+xaxbJDSWhbMwWMsbjB3zmLHw==",
"requires": {}
},
"expo-keep-awake": {
@@ -85170,6 +85180,11 @@
}
}
},
+ "jimp-compact": {
+ "version": "0.16.1",
+ "resolved": "https://registry.npmjs.org/jimp-compact/-/jimp-compact-0.16.1.tgz",
+ "integrity": "sha512-dZ6Ra7u1G8c4Letq/B5EzAxj4tLFHL+cGtdpR+PVm4yzPDj+lCk+AbivWt1eOM+ikzkowtyV7qSqX6qr3t71Ww=="
+ },
"jiti": {
"version": "1.20.0",
"resolved": "https://registry.npmjs.org/jiti/-/jiti-1.20.0.tgz",
@@ -95091,6 +95106,11 @@
"integrity": "sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ==",
"dev": true
},
+ "ts-interface-checker": {
+ "version": "0.1.13",
+ "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz",
+ "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA=="
+ },
"ts-object-utils": {
"version": "0.0.5",
"resolved": "https://registry.npmjs.org/ts-object-utils/-/ts-object-utils-0.0.5.tgz",
diff --git a/package.json b/package.json
index 2e7e28ec36f1..d2b851900222 100644
--- a/package.json
+++ b/package.json
@@ -102,7 +102,7 @@
"expensify-common": "git+ssh://git@github.com/Expensify/expensify-common.git#82bfcd1cb077afd03d1c8c069618c7dd5bd405d8",
"expo": "^49.0.0",
"expo-asset": "~8.10.1",
- "expo-image": "^1.6.0",
+ "expo-image": "^1.7.0",
"fbjs": "^3.0.2",
"htmlparser2": "^7.2.0",
"idb-keyval": "^6.2.1",
@@ -177,8 +177,6 @@
"underscore": "^1.13.1"
},
"devDependencies": {
- "@dword-design/eslint-plugin-import-alias": "^4.0.8",
- "@trivago/prettier-plugin-sort-imports": "^4.2.0",
"@actions/core": "1.10.0",
"@actions/github": "5.1.1",
"@babel/core": "^7.20.0",
@@ -189,6 +187,7 @@
"@babel/preset-react": "^7.10.4",
"@babel/preset-typescript": "^7.21.5",
"@babel/runtime": "^7.20.0",
+ "@dword-design/eslint-plugin-import-alias": "^4.0.8",
"@electron/notarize": "^2.1.0",
"@jest/globals": "^29.5.0",
"@octokit/core": "4.0.4",
@@ -208,6 +207,7 @@
"@svgr/webpack": "^6.0.0",
"@testing-library/jest-native": "5.4.1",
"@testing-library/react-native": "11.5.1",
+ "@trivago/prettier-plugin-sort-imports": "^4.2.0",
"@types/concurrently": "^7.0.0",
"@types/jest": "^29.5.2",
"@types/jest-when": "^3.5.2",
diff --git a/src/components/Avatar.js b/src/components/Avatar.js
index 296ad1a4baaf..2a52862faafd 100644
--- a/src/components/Avatar.js
+++ b/src/components/Avatar.js
@@ -43,6 +43,9 @@ const propTypes = {
*/
fallbackIcon: PropTypes.oneOfType([PropTypes.string, sourcePropTypes]),
+ /** Used to locate fallback icon in end-to-end tests. */
+ fallbackIconTestID: PropTypes.string,
+
/** Denotes whether it is an avatar or a workspace avatar */
type: PropTypes.oneOf([CONST.ICON_TYPE_AVATAR, CONST.ICON_TYPE_WORKSPACE]),
@@ -58,6 +61,7 @@ const defaultProps = {
size: CONST.AVATAR_SIZE.DEFAULT,
fill: null,
fallbackIcon: Expensicons.FallbackAvatar,
+ fallbackIconTestID: '',
type: CONST.ICON_TYPE_AVATAR,
name: '',
};
@@ -86,6 +90,8 @@ function Avatar(props) {
const iconFillColor = isWorkspace ? StyleUtils.getDefaultWorkspaceAvatarColor(props.name).fill : props.fill;
const fallbackAvatar = isWorkspace ? ReportUtils.getDefaultWorkspaceAvatar(props.name) : props.fallbackIcon || Expensicons.FallbackAvatar;
+ const fallbackAvatarTestID = isWorkspace ? ReportUtils.getDefaultWorkspaceAvatarTestID(props.name) : props.fallbackIconTestID || 'SvgFallbackAvatar Icon';
+ const avatarTestId = imageError ? 'AvatarIcon' : fallbackAvatarTestID;
return (
{}}: SplashScreenHiderProps) {
]}
>
-
diff --git a/src/components/TabSelector/TabSelectorItem.js b/src/components/TabSelector/TabSelectorItem.js
index 37420db9441c..cd5748596973 100644
--- a/src/components/TabSelector/TabSelectorItem.js
+++ b/src/components/TabSelector/TabSelectorItem.js
@@ -1,11 +1,11 @@
import PropTypes from 'prop-types';
import React from 'react';
import {Animated, StyleSheet} from 'react-native';
+import sourcePropTypes from '@components/Image/sourcePropTypes';
import PressableWithFeedback from '@components/Pressable/PressableWithFeedback';
import styles from '@styles/styles';
import TabIcon from './TabIcon';
import TabLabel from './TabLabel';
-import sourcePropTypes from '../Image/sourcePropTypes';
const propTypes = {
/** Function to call when onPress */
diff --git a/src/components/TextInput/baseTextInputPropTypes.js b/src/components/TextInput/baseTextInputPropTypes.js
index 8d50f58ae4e1..78c37e94196a 100644
--- a/src/components/TextInput/baseTextInputPropTypes.js
+++ b/src/components/TextInput/baseTextInputPropTypes.js
@@ -1,5 +1,5 @@
import PropTypes from 'prop-types';
-import sourcePropTypes from '../Image/sourcePropTypes';
+import sourcePropTypes from '@components/Image/sourcePropTypes';
const propTypes = {
/** Input label */
diff --git a/src/components/ThreeDotsMenu/ThreeDotsMenuItemPropTypes.js b/src/components/ThreeDotsMenu/ThreeDotsMenuItemPropTypes.js
index f0f1376e0193..9f09eabbc7f7 100644
--- a/src/components/ThreeDotsMenu/ThreeDotsMenuItemPropTypes.js
+++ b/src/components/ThreeDotsMenu/ThreeDotsMenuItemPropTypes.js
@@ -1,5 +1,5 @@
import PropTypes from 'prop-types';
-import sourcePropTypes from '../Image/sourcePropTypes';
+import sourcePropTypes from '@components/Image/sourcePropTypes';
const menuItemProps = PropTypes.arrayOf(
PropTypes.shape({
diff --git a/src/components/menuItemPropTypes.js b/src/components/menuItemPropTypes.js
index 5e932236f70e..5623ed9cefdd 100644
--- a/src/components/menuItemPropTypes.js
+++ b/src/components/menuItemPropTypes.js
@@ -3,8 +3,8 @@ import _ from 'underscore';
import stylePropTypes from '@styles/stylePropTypes';
import CONST from '@src/CONST';
import avatarPropTypes from './avatarPropTypes';
-import refPropTypes from './refPropTypes';
import sourcePropTypes from './Image/sourcePropTypes';
+import refPropTypes from './refPropTypes';
const propTypes = {
/** Text to be shown as badge near the right end. */
diff --git a/src/libs/ReportUtils.js b/src/libs/ReportUtils.js
index fb05407ab39a..edc71302d0ca 100644
--- a/src/libs/ReportUtils.js
+++ b/src/libs/ReportUtils.js
@@ -28,6 +28,8 @@ let currentUserEmail;
let currentUserAccountID;
let isAnonymousUser;
+const defaultAvatarBuildingIconTestID = 'SvgDefaultAvatarBuilding Icon';
+
Onyx.connect({
key: ONYXKEYS.SESSION,
callback: (val) => {
@@ -1015,6 +1017,25 @@ function getDefaultWorkspaceAvatar(workspaceName) {
return !alphaNumeric ? defaultWorkspaceAvatars.WorkspaceBuilding : defaultWorkspaceAvatars[`Workspace${alphaNumeric[0]}`];
}
+/**
+ * Helper method to return the default avatar testID associated with the given login
+ * @param {String} [workspaceName]
+ * @returns {String}
+ */
+function getDefaultWorkspaceAvatarTestID(workspaceName) {
+ if (!workspaceName) {
+ return defaultAvatarBuildingIconTestID;
+ }
+
+ // Remove all chars not A-Z or 0-9 including underscore
+ const alphaNumeric = workspaceName
+ .normalize('NFD')
+ .replace(/[^0-9a-z]/gi, '')
+ .toLowerCase();
+
+ return !alphaNumeric ? defaultAvatarBuildingIconTestID : `SvgDefaultAvatar_${alphaNumeric[0]} Icon`;
+}
+
function getWorkspaceAvatar(report) {
const workspaceName = getPolicyName(report, allPolicies);
return lodashGet(allPolicies, [`${ONYXKEYS.COLLECTION.POLICY}${report.policyID}`, 'avatar']) || getDefaultWorkspaceAvatar(workspaceName);
@@ -4233,6 +4254,7 @@ export {
getNewMarkerReportActionID,
canSeeDefaultRoom,
getDefaultWorkspaceAvatar,
+ getDefaultWorkspaceAvatarTestID,
getCommentLength,
getParsedComment,
getMoneyRequestOptions,
diff --git a/src/pages/iou/ReceiptDropUI.js b/src/pages/iou/ReceiptDropUI.js
index 5e769d5949c4..fd489f6c6924 100644
--- a/src/pages/iou/ReceiptDropUI.js
+++ b/src/pages/iou/ReceiptDropUI.js
@@ -1,12 +1,12 @@
+import CONST from '@CONST';
+import PropTypes from 'prop-types';
import React from 'react';
import {Text, View} from 'react-native';
-import PropTypes from 'prop-types';
-import CONST from '../../CONST';
-import styles from '../../styles/styles';
-import ReceiptUpload from '../../../assets/images/receipt-upload.svg';
-import useLocalize from '../../hooks/useLocalize';
-import DragAndDropConsumer from '../../components/DragAndDrop/Consumer';
-import ImageSVG from '../../components/ImageSVG';
+import ReceiptUpload from '@assets/images/receipt-upload.svg';
+import DragAndDropConsumer from '@components/DragAndDrop/Consumer';
+import ImageSVG from '@components/ImageSVG';
+import useLocalize from '@hooks/useLocalize';
+import styles from '@styles/styles';
const propTypes = {
/** Callback to execute when a file is dropped. */
diff --git a/src/pages/signin/SignInPageLayout/BackgroundImage/index.ios.js b/src/pages/signin/SignInPageLayout/BackgroundImage/index.ios.js
index d7c45b8ac853..1c526710f376 100644
--- a/src/pages/signin/SignInPageLayout/BackgroundImage/index.ios.js
+++ b/src/pages/signin/SignInPageLayout/BackgroundImage/index.ios.js
@@ -1,9 +1,9 @@
-import React from 'react';
-import PropTypes from 'prop-types';
import {Image} from 'expo-image';
-import MobileBackgroundImage from '../../../../../assets/images/home-background--mobile-new.svg';
-import DesktopBackgroundImage from '../../../../../assets/images/home-background--desktop.svg';
-import styles from '../../../../styles/styles';
+import PropTypes from 'prop-types';
+import React from 'react';
+import DesktopBackgroundImage from '@assets/images/home-background--desktop.svg';
+import MobileBackgroundImage from '@assets/images/home-background--mobile-new.svg';
+import styles from '@styles/styles';
import defaultPropTypes from './propTypes';
const defaultProps = {
diff --git a/tsconfig.json b/tsconfig.json
index 151087fb1321..049ea075bcbd 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -40,11 +40,11 @@
"@navigation/*": ["./src/libs/Navigation/*"],
"@pages/*": ["./src/pages/*"],
"@styles/*": ["./src/styles/*"],
- // This path is provide alias for files like `ONYXKEYS` and `CONST`.
"@src/*": ["./src/*"],
"@userActions/*": ["./src/libs/actions/*"]
}
},
"exclude": ["**/node_modules/*", "**/dist/*", ".github/actions/**/index.js", "**/docs/*"],
- "include": ["src", "desktop", "web", "docs", "assets", "config", "tests", "jest", "__mocks__", ".github/**/*", ".storybook/**/*"]
+ "include": ["src", "desktop", "web", "docs", "assets", "config", "tests", "jest", "__mocks__", ".github/**/*", ".storybook/**/*"],
+ "extends": "expo/tsconfig.base"
}