Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/CONST/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -986,6 +986,7 @@ const CONST = {
RILLET: 'rillet',
RULES_REVAMP: 'rulesRevamp',
COMMUTER_EXCLUSIONS: 'commuterExclusions',
DEFAULT_LETTER_AVATARS: 'defaultLetterAvatars',
},
BUTTON_STATES: {
DEFAULT: 'default',
Expand Down
47 changes: 25 additions & 22 deletions src/components/AvatarSelector.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import useLetterAvatars from '@hooks/useLetterAvatars';
import useLocalize from '@hooks/useLocalize';
import usePermissions from '@hooks/usePermissions';
import useStyleUtils from '@hooks/useStyleUtils';
import useThemeStyles from '@hooks/useThemeStyles';

Expand Down Expand Up @@ -43,6 +44,7 @@ function AvatarSelector({selectedID, onSelect, label, name, size = CONST.AVATAR_
const styles = useThemeStyles();
const StyleUtils = useStyleUtils();
const {avatarList} = useLetterAvatars(name, size);
const {isBetaEnabled} = usePermissions();

const iconSize = StyleUtils.getAvatarSize(size);

Expand Down Expand Up @@ -74,28 +76,29 @@ function AvatarSelector({selectedID, onSelect, label, name, size = CONST.AVATAR_
</PressableWithFeedback>
);
})}
{avatarList.map(({id, StyledLetterAvatar}) => {
const isSelected = selectedID === id;

return (
<PressableWithFeedback
key={id}
accessible
accessibilityRole="button"
accessibilityLabel={translate('avatarPage.selectAvatar')}
onPress={() => onSelect(id)}
style={[styles.avatarSelectorWrapper, isSelected && styles.avatarSelected]}
>
<Avatar
type={CONST.ICON_TYPE_AVATAR}
source={StyledLetterAvatar}
size={size}
containerStyles={styles.avatarSelectorContainer}
testID={`AvatarSelector_${id}`}
/>
</PressableWithFeedback>
);
})}
{isBetaEnabled(CONST.BETAS.DEFAULT_LETTER_AVATARS) &&
avatarList.map(({id, StyledLetterAvatar}) => {
Comment thread
grgia marked this conversation as resolved.
const isSelected = selectedID === id;

return (
<PressableWithFeedback
key={id}
accessible
accessibilityRole="button"
accessibilityLabel={translate('avatarPage.selectAvatar')}
onPress={() => onSelect(id)}
style={[styles.avatarSelectorWrapper, isSelected && styles.avatarSelected]}
>
<Avatar
type={CONST.ICON_TYPE_AVATAR}
source={StyledLetterAvatar}
size={size}
containerStyles={styles.avatarSelectorContainer}
testID={`AvatarSelector_${id}`}
/>
</PressableWithFeedback>
);
})}
{/* We need to add several invisible items at the end of the avatar list to guarantee that the last row avatars are aligned properly */}
{[...Array(SPACER_SIZE).keys()].map((i) => (
<View
Expand Down
23 changes: 23 additions & 0 deletions tests/ui/AvatarSelector.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,13 @@ jest.mock('@hooks/useLetterAvatars', () => ({
return {avatarList, avatarMap: {}};
},
}));

const mockIsBetaEnabled = jest.fn<boolean, [string]>();
jest.mock('@hooks/usePermissions', () => ({
__esModule: true,
default: () => ({isBetaEnabled: mockIsBetaEnabled}),
}));

const mockName = 'Alice';

describe('AvatarSelector', () => {
Expand All @@ -50,6 +57,7 @@ describe('AvatarSelector', () => {

beforeEach(() => {
jest.clearAllMocks();
mockIsBetaEnabled.mockReturnValue(false);
});

const renderAvatarSelector = (props = {}) => {
Expand Down Expand Up @@ -130,6 +138,10 @@ describe('AvatarSelector', () => {
describe('avatarList (letter avatars)', () => {
const firstChar = getFirstAlphaNumericCharacter(mockName).toLowerCase();

beforeEach(() => {
mockIsBetaEnabled.mockReturnValue(true);
});

it('letter avatars have correct ID format when they are rendered', async () => {
renderAvatarSelector({name: mockName});
await waitForBatchedUpdates();
Expand Down Expand Up @@ -207,4 +219,15 @@ describe('AvatarSelector', () => {
expect(letterAvatars.at(0)?.props.testID).toMatch(/^AvatarSelector_letter-avatar-/);
});
});

describe('when LETTER_AVATARS beta is disabled', () => {
it('does not render any letter avatars even with a name', async () => {
renderAvatarSelector({name: mockName});
await waitForBatchedUpdates();

const letterAvatars = screen.queryAllByTestId(/^AvatarSelector_letter-avatar/);

expect(letterAvatars).toHaveLength(0);
});
});
});
Loading