Skip to content

Commit 2c04f82

Browse files
authored
feat: avatar with fallback icons component (#1763)
* feat: avatar with fallback icons component Signed-off-by: Adam Setch <[email protected]> * feat: avatar with fallback icons component Signed-off-by: Adam Setch <[email protected]> --------- Signed-off-by: Adam Setch <[email protected]>
1 parent 6493d7f commit 2c04f82

15 files changed

+1866
-725
lines changed
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import { render, screen } from '@testing-library/react';
2+
3+
import { type Link, Size } from '../../types';
4+
import {
5+
AvatarWithFallback,
6+
type IAvatarWithFallback,
7+
} from './AvatarWithFallback';
8+
9+
describe('renderer/components/avatars/AvatarWithFallback.tsx', () => {
10+
const props: IAvatarWithFallback = {
11+
src: 'https://avatars.githubusercontent.com/u/133795385?s=200&v=4' as Link,
12+
alt: 'gitify-app',
13+
name: '@gitify-app',
14+
size: Size.MEDIUM,
15+
userType: 'User',
16+
};
17+
18+
it('should render avatar - human user', () => {
19+
const tree = render(<AvatarWithFallback {...props} />);
20+
expect(tree).toMatchSnapshot();
21+
});
22+
23+
it('should render avatar - non-human user', () => {
24+
const tree = render(
25+
<AvatarWithFallback {...props} userType={'Organization'} />,
26+
);
27+
expect(tree).toMatchSnapshot();
28+
});
29+
30+
it('renders the fallback icon when no src url - human user', () => {
31+
const tree = render(<AvatarWithFallback {...props} src={null} />);
32+
33+
expect(tree).toMatchSnapshot();
34+
});
35+
36+
it('renders the fallback icon when no src url - non human user', () => {
37+
const tree = render(
38+
<AvatarWithFallback {...props} src={null} userType="Bot" />,
39+
);
40+
41+
expect(tree).toMatchSnapshot();
42+
});
43+
44+
it('renders the fallback icon when the image fails to load (isBroken = true) - human user', () => {
45+
render(<AvatarWithFallback {...props} />);
46+
47+
// Find the avatar element by its alt text
48+
const avatar = screen.getByAltText('gitify-app') as HTMLImageElement;
49+
50+
// Simulate an error event on the image element
51+
avatar.dispatchEvent(new Event('error'));
52+
53+
expect(screen.getByTestId('avatar')).toMatchSnapshot();
54+
});
55+
56+
it('renders the fallback icon when the image fails to load (isBroken = true) - non human user', () => {
57+
render(<AvatarWithFallback {...props} userType={'Bot'} />);
58+
59+
// Find the avatar element by its alt text
60+
const avatar = screen.getByAltText('gitify-app') as HTMLImageElement;
61+
62+
// Simulate an error event on the image element
63+
avatar.dispatchEvent(new Event('error'));
64+
65+
expect(screen.getByTestId('avatar')).toMatchSnapshot();
66+
});
67+
});
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import type React from 'react';
2+
import { useState } from 'react';
3+
4+
import { FeedPersonIcon, MarkGithubIcon } from '@primer/octicons-react';
5+
import { Avatar, Stack, Text } from '@primer/react';
6+
7+
import { type Link, Size } from '../../types';
8+
import type { UserType } from '../../typesGitHub';
9+
import { isNonHumanUser } from '../../utils/helpers';
10+
11+
export interface IAvatarWithFallback {
12+
src?: Link;
13+
alt?: string;
14+
name?: string;
15+
size?: number;
16+
userType?: UserType;
17+
}
18+
19+
export const AvatarWithFallback: React.FC<IAvatarWithFallback> = ({
20+
src,
21+
alt,
22+
name,
23+
size = Size.MEDIUM,
24+
userType = 'User',
25+
}) => {
26+
const [isBroken, setIsBroken] = useState(false);
27+
28+
const isNonHuman = isNonHumanUser(userType);
29+
return (
30+
<Stack
31+
direction="horizontal"
32+
align="center"
33+
gap="condensed"
34+
data-testid="avatar"
35+
>
36+
{!src || isBroken ? (
37+
isNonHuman ? (
38+
<MarkGithubIcon size={size} />
39+
) : (
40+
<FeedPersonIcon size={size} />
41+
)
42+
) : (
43+
<Avatar
44+
src={src}
45+
alt={alt}
46+
size={size}
47+
square={isNonHuman}
48+
onError={() => setIsBroken(true)}
49+
/>
50+
)}
51+
{name && <Text>{name}</Text>}
52+
</Stack>
53+
);
54+
};

0 commit comments

Comments
 (0)