Skip to content

Conversation

@jefische
Copy link
Contributor

@jefische jefische commented Oct 16, 2025

Description

Before:

The Avatar component lacked unit tests.

After:

Unit tests have been added for Avatar component:

  • renders user avatar image when valid src attribute is provided
  • renders fallback/default avatar image when src is undefined
  • added alt text to AvatarImage to access element by semantic query

Closes #174

Testing instructions

If applicable, provide steps for reviewers to test changes locally -- including necessary setup, commands, and expected results

Additional information

Share any additional info that may provide context for the PR evaluation (performance considerations, design choices, etc)

[optional] Screenshots

image

Pre-submission checklist

  • Code builds and passes locally
  • PR title follows Conventional Commit format (e.g. test #001: created unit test for __ component)
  • Request reviews from the Peer Code Reviewers and Senior+ Code Reviewers groups
  • Thread has been created in Discord and PR is linked in gis-code-questions

@vercel
Copy link

vercel bot commented Oct 16, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Preview Comments Updated (UTC)
elecretanta Ready Ready Preview Comment Nov 5, 2025 4:58pm
elecretanta-storybook Ready Ready Preview Comment Nov 5, 2025 4:58pm
elecretanta-unit-test Ready Ready Preview Comment Nov 5, 2025 4:58pm

@jefische jefische changed the title Jeremy/174 unit test avatar component test #174: created unit test for Avatar component Oct 16, 2025
@jefische jefische requested review from a team October 16, 2025 16:30
const actual = jest.requireActual('@radix-ui/react-avatar');
return ({
...actual,
Image: ({src, alt, ...props}: {src?: string, alt?: string}) => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove ...props from the Image mock. When testing, you should only mock the necessary behavior. For the Avatar component, you're currently only testing for src and alt. The other properties of Image aren't needed.

return ({
...actual,
Image: ({src, alt, ...props}: {src?: string, alt?: string}) => {
return <img data-testid="avatar-image" src={src} alt={alt} {...props}/>;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't add data-testids inside components used in testing. While you fetched the element by role, which is good, the id still isn't necessary for the mock.

If anything, this id should have been added to the AvatarImage component.

const actual = jest.requireActual('@radix-ui/react-avatar');
return ({
...actual,
Image: ({src, alt, ...props}: {src?: string, alt?: string}) => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove the optional ? on the alt?. This property will always be included in both the AvatarImage and AvatarFallback.

return (
<AvatarBody>
<AvatarImage src={userAvatar} alt="" />
<AvatarImage src={userAvatar} alt="user avatar" />
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

refactor (a11y): "user avatar" is too generic. If the avatar conveys meaning, add more context, like the username, otherwise leave the alt test to "".

Suggested change
<AvatarImage src={userAvatar} alt="user avatar" />
<AvatarImage src={userAvatar} alt=`profile image for user ${username}` />

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think adding more context with the username makes sense. After adding username as a prop:

const Avatar = ({ userAvatar, username }: { userAvatar: string | undefined, username: string })

I believe I would need to update each instance where the Avatar component is used:

<Avatar userAvatar={avatar} />

<Avatar data-testid="avatar" userAvatar={profile?.avatar} />

<Avatar userAvatar={member.member.avatar} />

I want to make sure this correct and okay to do inside the same PR as I'm starting to change multiple files. For the UserDropdownMenu component it gets more complicated to pass a username as well.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, this is only a unit test task. This should be removed into an A11Y ticket. I want to keep things simple for your first test.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, I'll just leave the AvatarImage alt text as it was prior to my edits.

import Avatar from './Avatar';
import { render, screen } from '@testing-library/react';

jest.mock('@radix-ui/react-avatar', () => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just FYI for anyone coming across this. My first instinct was to ask why are we mocking this as you always want to mock as little as possible or not at all so we are testing the actual implementation.

In this case, we mock Radix’s Avatar.Image because in JSDOM, what we use in Jest tests, image load events don’t fire as it's not a real browser environment, so only the fallback is ever shown in tests if we don't mock.

return (
<AvatarBody>
<AvatarImage src={userAvatar} alt="" />
<AvatarImage src={userAvatar} alt="user avatar" />
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, this is only a unit test task. This should be removed into an A11Y ticket. I want to keep things simple for your first test.


});

it('Renders the fallback image when src is undefined', () => {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about when there's a string given bug the image is not found?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That makes sense, I'll add this test scenario.


describe('Avatar Component', () => {

it('Renders the component with user image using valid src attribute', () => {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should the fallback component show here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not for this scenario. I wanted to test that the user provided image is correctly added to the document.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add an exception to check that fallback doesn't show in this default scenario.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interestingly the fallback image is still showing in the document for this scenario. I tried using .not.toBeVisible() method as well as .not.toBeInTheDocument() but both tests fail:

1st attempt:

+ const avatarElementFallbackImage = screen.getByTestId('avatar-fallback')
+ expect(avatarElementFallbackImage).not.toBeVisible();

2nd attempt:

+ const avatarElementFallbackImage = screen.getByTestId('avatar-fallback')
+ expect(avatarElementFallbackImage).not.toBeInTheDocument();

I tried looking at screen.debug() and it's showing both elements in the JSDOM. Are both of these supposed to show up like this?

Screen-debug-avatar-component

it('Renders the component with user image using valid src attribute', () => {
render(<Avatar userAvatar='https://mdbcdn.b-cdn.net/img/new/avatars/2.webp' />);

const avatarElementWithImage = screen.getByRole('img', { name: 'user avatar'});
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Follow how we're doing the other components by adding a data-testid attribute.

@shashilo shashilo removed the request for review from a team October 22, 2025 15:28
shashilo
shashilo previously approved these changes Oct 22, 2025
nickytonline
nickytonline previously approved these changes Oct 25, 2025
Copy link
Member

@nickytonline nickytonline left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚀

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

@jefische
Copy link
Contributor Author

jefische commented Nov 5, 2025

The unit test for the ProfileCard component failed as a result of adding data-testid="avatar-image" to the AvatarImage component. ProfileCard was mocking the image and adding a data-testid to the mock rather than the actual component. They were also mocking the AvatarFallback incorrectly so I’ve updated the ProfileCard test to be consistent with the mock for our Avatar component. All tests are passing now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Create unit test for Avatar.tsx

5 participants