Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
3a44a6c
adding testing to AvatarGroup
sopranopillow Jun 14, 2022
88a1d6e
restore badge api file
sopranopillow Jun 14, 2022
c352c71
change fileS
sopranopillow Jun 14, 2022
24dd476
reverting api file
sopranopillow Jun 14, 2022
4e95874
fixing interactive story in vr-tests
sopranopillow Jun 14, 2022
71002e5
fixing cropping of interactive story
sopranopillow Jun 14, 2022
eee2ddc
possible border radius fix
sopranopillow Jun 14, 2022
c870975
Merge branch 'master' of https://github.com/microsoft/fluentui into a…
sopranopillow Jun 15, 2022
63f5ace
removing unnecessary div
sopranopillow Jun 15, 2022
4e116a6
reverting changes
sopranopillow Jun 15, 2022
a778010
possible fix
sopranopillow Jun 15, 2022
2b19bdb
sync
sopranopillow Jun 16, 2022
6742709
reverting files to deal with issue in another PR
sopranopillow Jun 16, 2022
9956bd3
Update change/@fluentui-react-avatar-0ebe3e03-9d8f-48f7-a4c0-2a95b701…
sopranopillow Jun 17, 2022
9b4bd3f
Update apps/vr-tests-react-components/src/stories/AvatarGroup.stories…
sopranopillow Jun 17, 2022
233ae01
Update packages/react-components/react-avatar/src/components/AvatarGr…
sopranopillow Jun 17, 2022
0491379
Merge branch 'master' of https://github.com/microsoft/fluentui into a…
sopranopillow Jun 17, 2022
b093681
Merge branch 'avatargroup-tests' of https://github.com/sopranopillow/…
sopranopillow Jun 17, 2022
d8e1a19
covering stack and pie for rtl+HCM+dark mode
sopranopillow Jun 17, 2022
7a64e8b
updating vr-tests
sopranopillow Jun 17, 2022
985a2f1
Merge branch 'master' of https://github.com/microsoft/fluentui into a…
sopranopillow Jun 23, 2022
563c3ba
updating classname tests for AvatarGroup
sopranopillow Jun 23, 2022
8cad6e4
adding color to diviers
sopranopillow Jun 28, 2022
d819130
Merge branch 'master' of https://github.com/microsoft/fluentui into a…
sopranopillow Jun 28, 2022
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import * as React from 'react';
import { storiesOf } from '@storybook/react';
import Screener from 'screener-storybook/src/screener';
import { AvatarGroup, AvatarGroupItem, AvatarGroupProps } from '@fluentui/react-avatar';
import { TestWrapperDecorator } from '../utilities/TestWrapperDecorator';

const names = [
'Katri Athokas',
'Elvia Atkins',
'Mauricio August',
'Colin Ballinger',
'Lydia Bauer',
'Amanda Brady',
'Henry Brill',
'Celeste Burton',
'Robin Counts',
'Tim Deboer',
'Cameron Evans',
'Isaac Fielder',
'Cecil Folk',
'Miguel Garcia',
'Wanda Howard',
'Mona Kane',
'Kat Larsson',
'Ashley McCarthy',
'Johnie McConnell',
'Allan Munger',
'Erik Nason',
'Kristin Patterson',
'Daisy Phillips',
'Carole Poland',
'Carlos Slattery',
'Robert Tolbert',
'Kevin Sturgis',
'Charlotte Waltson',
'Elliot Woodward',
];

const sizes = [16, 20, 24, 28, 32, 36, 40, 48, 56, 64, 72, 96, 120, 128];

const AvatarGroupList: React.FC<AvatarGroupProps> = props => {
return (
<div style={{ display: 'flex', flexDirection: 'column', flexWrap: 'wrap', gap: '10px' }}>
{sizes.map(size => (
<AvatarGroup key={size} size={size as AvatarGroupProps['size']} {...props}>
{names.map(name => (
<AvatarGroupItem key={name} name={name} />
))}
</AvatarGroup>
))}
</div>
);
};

// Non-interactive stories
storiesOf('AvatarGroup Converged', module)
.addDecorator(TestWrapperDecorator)
.addDecorator(story => (
<Screener steps={new Screener.Steps().snapshot('default', { cropTo: '.testWrapper' }).end()}>{story()}</Screener>
))
.addStory('basic', () => <AvatarGroupList />, {
includeHighContrast: true,
includeDarkMode: true,
})
.addStory('layoutPie', () => <AvatarGroupList layout="pie" />, {
includeHighContrast: true,
includeDarkMode: true,
})
.addStory('layoutStack', () => <AvatarGroupList layout="stack" />, {
includeHighContrast: true,
includeDarkMode: true,
})
.addStory('overflowIndicator', () => <AvatarGroupList overflowIndicator="icon" />);

// Interactive stories
storiesOf('AvatarGroup Converged', module)
.addDecorator(TestWrapperDecorator)
.addDecorator(story => (
<Screener steps={new Screener.Steps().click('#show-overflow').snapshot('overflowContentOpen').end()}>
{story()}
</Screener>
))
.addStory(
'overflowContent',
() => (
<AvatarGroup overflowButton={{ id: 'show-overflow' }}>
{names.map(name => (
<AvatarGroupItem key={name} name={name} />
))}
</AvatarGroup>
),
{
includeHighContrast: true,
includeDarkMode: true,
},
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "none",
"comment": "chore: Adding unit tests for AvatarGroup. ",
"packageName": "@fluentui/react-avatar",
"email": "[email protected]",
"dependentChangeType": "none"
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,176 @@ import * as React from 'react';
import { AvatarGroup } from './AvatarGroup';
import { AvatarGroupItem } from '../AvatarGroupItem';
import { isConformant } from '../../common/isConformant';
import { render } from '@testing-library/react';
import { render, RenderResult, screen, within } from '@testing-library/react';
import { avatarGroupClassNames } from './useAvatarGroupStyles';

// testing-library's queryByRole function doesn't look inside portals
function queryByRoleList(result: RenderResult) {
const lists = result.baseElement.querySelectorAll('*[role="list"]');
if (!lists?.length) {
return null;
} else {
expect(lists.length).toBe(1);
return lists.item(0) as HTMLElement;
}
}

const getOverflowContentElement = (result: RenderResult) => {
// overflowButton needs to be clicked otherwise overflowContent won't be rendered.
result.queryByRole('button')?.click();
return queryByRoleList(result)!;
};

describe('AvatarGroup', () => {
// TODO: Remove component-has-static-classnames-object from disabled tests.
isConformant({
Component: AvatarGroup,
displayName: 'AvatarGroup',
disabledTests: [
'component-has-static-classname',
'component-has-static-classname-exported',
'component-has-static-classnames-object',
'make-styles-overrides-win',
],
testOptions: {
'has-static-classnames': [
{
props: {},
expectedClassNames: {
root: avatarGroupClassNames.root,
overflowButton: avatarGroupClassNames.overflowButton,
overflowContent: avatarGroupClassNames.overflowContent,
},
getPortalElement: getOverflowContentElement,
},
],
},
requiredProps: {
children: [
<AvatarGroupItem key="0" name="Katri Athokas" />,
<AvatarGroupItem key="1" name="Elvia Atkins" />,
<AvatarGroupItem key="2" name="Cameron Evans" />,
<AvatarGroupItem key="3" name="Wanda Howard" />,
<AvatarGroupItem key="4" name="Mona Kane" />,
<AvatarGroupItem key="5" name="Allan Munger" />,
<AvatarGroupItem key="6" name="Daisy Phillips" />,
<AvatarGroupItem key="7" name="Robert Tolbert" />,
<AvatarGroupItem key="8" name="Kevin Sturgis" />,
],
},
});

it('renders an overflow indicator when AvatarGroupItems overflow', () => {
render(
<AvatarGroup>
<AvatarGroupItem name="Katri Athokas" />
<AvatarGroupItem name="Elvia Atkins" />
<AvatarGroupItem name="Cameron Evans" />
<AvatarGroupItem name="Wanda Howard" />
<AvatarGroupItem name="Mona Kane" />
<AvatarGroupItem name="Allan Munger" />
<AvatarGroupItem name="Daisy Phillips" />
<AvatarGroupItem name="Robert Tolbert" />
<AvatarGroupItem name="Kevin Sturgis" />
</AvatarGroup>,
);

expect(screen.getByText('+5')).toBeTruthy();
});

it('renders an icon overflow indicator when size is less than 24', () => {
render(
<AvatarGroup size={20}>
<AvatarGroupItem name="Katri Athokas" />
<AvatarGroupItem name="Elvia Atkins" />
<AvatarGroupItem name="Cameron Evans" />
<AvatarGroupItem name="Wanda Howard" />
<AvatarGroupItem name="Mona Kane" />
<AvatarGroupItem name="Allan Munger" />
<AvatarGroupItem name="Daisy Phillips" />
<AvatarGroupItem name="Robert Tolbert" />
<AvatarGroupItem name="Kevin Sturgis" />
</AvatarGroup>,
);

expect(screen.getByRole('button').textContent).toBe('');
});

it('ignores maxAvatars when using pie layout', () => {
render(
<AvatarGroup layout="pie">
<AvatarGroupItem name="Katri Athokas" />
<AvatarGroupItem name="Elvia Atkins" />
<AvatarGroupItem name="Cameron Evans" />
<AvatarGroupItem name="Wanda Howard" />
<AvatarGroupItem name="Mona Kane" />
<AvatarGroupItem name="Allan Munger" />
<AvatarGroupItem name="Daisy Phillips" />
<AvatarGroupItem name="Robert Tolbert" />
<AvatarGroupItem name="Kevin Sturgis" />
</AvatarGroup>,
);

// maxAvatars is 3 when the layout is pie, but it also renders a transparent button
// so it needs to check for 3 children + 1 button
expect(screen.getByRole('group').children.length).toBe(4);
});

// TODO add more tests here, and create visual regression tests in /apps/vr-tests
it('renders the avatars in the correct order when using a stack or spread layout', () => {
render(
<AvatarGroup>
<AvatarGroupItem name="Katri Athokas" />
<AvatarGroupItem name="Elvia Atkins" />
<AvatarGroupItem name="Cameron Evans" />
<AvatarGroupItem name="Wanda Howard" />
<AvatarGroupItem name="Mona Kane" />
<AvatarGroupItem name="Allan Munger" />
<AvatarGroupItem name="Daisy Phillips" />
<AvatarGroupItem name="Robert Tolbert" />
<AvatarGroupItem name="Kevin Sturgis" />
</AvatarGroup>,
);

it('renders a default state', () => {
const result = render(
const avatarChildren = screen.getByRole('group').children;

expect(avatarChildren.item(0)?.textContent).toBe('AM');
expect(avatarChildren.item(1)?.textContent).toBe('DP');
expect(avatarChildren.item(2)?.textContent).toBe('RT');
expect(avatarChildren.item(3)?.textContent).toBe('KS');
});

it('renders all AvatarGroupItems inside the overflowContent when using a pie layout', () => {
const { baseElement } = render(
<AvatarGroup layout="pie">
<AvatarGroupItem name="Katri Athokas" />
<AvatarGroupItem name="Elvia Atkins" />
<AvatarGroupItem name="Cameron Evans" />
<AvatarGroupItem name="Wanda Howard" />
<AvatarGroupItem name="Mona Kane" />
<AvatarGroupItem name="Allan Munger" />
<AvatarGroupItem name="Daisy Phillips" />
<AvatarGroupItem name="Robert Tolbert" />
<AvatarGroupItem name="Kevin Sturgis" />
</AvatarGroup>,
);

const button = screen.getByRole('button');
button.click();
// overflowContent is rendered in a portal, so using baseElement let's you access its content
const avatarGroupItems = within(baseElement as HTMLElement).getAllByRole('listitem');
const avatarGroupItemAvatars = avatarGroupItems.map(item => within(item).getByRole('img'));

expect(avatarGroupItemAvatars[0].textContent).toBe('KA');
expect(avatarGroupItemAvatars[1].textContent).toBe('EA');
expect(avatarGroupItemAvatars[2].textContent).toBe('CE');
expect(avatarGroupItemAvatars[3].textContent).toBe('WH');
expect(avatarGroupItemAvatars[4].textContent).toBe('MK');
expect(avatarGroupItemAvatars[5].textContent).toBe('AM');
expect(avatarGroupItemAvatars[6].textContent).toBe('DP');
expect(avatarGroupItemAvatars[7].textContent).toBe('RT');
expect(avatarGroupItemAvatars[8].textContent).toBe('KS');
});

it('handles maxAvatars', () => {
render(
<AvatarGroup>
<AvatarGroupItem name="Katri Athokas" />
<AvatarGroupItem name="Elvia Atkins" />
Expand All @@ -32,6 +184,25 @@ describe('AvatarGroup', () => {
<AvatarGroupItem name="Kevin Sturgis" />
</AvatarGroup>,
);
expect(result.container).toMatchSnapshot();

expect(screen.getByRole('group').children.length).toBe(5);
});

it('handles custom maxAvatars', () => {
render(
<AvatarGroup maxAvatars={8}>
<AvatarGroupItem name="Katri Athokas" />
<AvatarGroupItem name="Elvia Atkins" />
<AvatarGroupItem name="Cameron Evans" />
<AvatarGroupItem name="Wanda Howard" />
<AvatarGroupItem name="Mona Kane" />
<AvatarGroupItem name="Allan Munger" />
<AvatarGroupItem name="Daisy Phillips" />
<AvatarGroupItem name="Robert Tolbert" />
<AvatarGroupItem name="Kevin Sturgis" />
</AvatarGroup>,
);

expect(screen.getByRole('group').children.length).toBe(8);
});
});
Loading