Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add unit and vr tests to Rating #30414

Merged
merged 13 commits into from
Feb 2, 2024
Merged
1 change: 1 addition & 0 deletions apps/vr-tests-react-components/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
"@fluentui/react-progress": "*",
"@fluentui/react-provider": "*",
"@fluentui/react-radio": "*",
"@fluentui/react-rating-preview": "*",
"@fluentui/react-search-preview": "*",
"@fluentui/react-select": "*",
"@fluentui/react-shared-contexts": "*",
Expand Down
54 changes: 54 additions & 0 deletions apps/vr-tests-react-components/src/stories/Rating.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import * as React from 'react';
import { Steps, StoryWright } from 'storywright';
import { storiesOf } from '@storybook/react';
import { CircleRegular, CircleFilled, SquareRegular, SquareFilled } from '@fluentui/react-icons';
import { Rating } from '@fluentui/react-rating-preview';
import { TestWrapperDecoratorFixedWidth } from '../utilities/TestWrapperDecorator';

storiesOf('Rating Converged Color', module)
.addDecorator(TestWrapperDecoratorFixedWidth)
.addDecorator(story => (
<StoryWright
steps={new Steps()
.snapshot('rest', { cropTo: '.testWrapper' })
.hover('input')
.snapshot('hover', { cropTo: '.testWrapper' })
.hover('input'[4])
.snapshot('active', { cropTo: '.testWrapper' })
.end()}
>
{story()}
</StoryWright>
))
.addStory('Neutral Rating with half star', () => <Rating defaultValue={3.5} />, {
includeHighContrast: true,
includeDarkMode: true,
})
.addStory('Brand Rating with half star', () => <Rating color="brand" defaultValue={3.5} />, {
includeHighContrast: true,
includeDarkMode: true,
})
.addStory('Marigold Rating with half star', () => <Rating color="marigold" defaultValue={3.5} />, {
includeHighContrast: true,
includeDarkMode: true,
});

storiesOf('Rating Converged Size', module)
.addDecorator(TestWrapperDecoratorFixedWidth)
.addStory('Rating size small', () => <Rating size="small" />, {})
.addStory('Rating size medium', () => <Rating size="medium" />, {})
.addStory('Rating size large', () => <Rating size="large" />, {})
.addStory('Rating size extra-large', () => <Rating size="extra-large" />, {});

storiesOf('Rating Converged Custom Icons', module)
.addDecorator(TestWrapperDecoratorFixedWidth)
.addStory(
'Rating with custom circle icons',
() => <Rating iconFilled={<CircleFilled />} iconOutline={<CircleRegular />} defaultValue={3.5} />,
{},
)
.addStory(
'Rating with custom square icons',
() => <Rating iconFilled={<SquareFilled />} iconOutline={<SquareRegular />} defaultValue={3.5} />,
{},
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import * as React from 'react';
import { storiesOf } from '@storybook/react';
import { CircleRegular, CircleFilled, SquareRegular, SquareFilled } from '@fluentui/react-icons';
import { RatingDisplay } from '@fluentui/react-rating-preview';
import { TestWrapperDecoratorFixedWidth } from '../utilities/TestWrapperDecorator';

storiesOf('RatingDisplay Converged Size', module)
.addDecorator(TestWrapperDecoratorFixedWidth)
.addStory('RatingDisplay size small', () => <RatingDisplay size="small" value={3.5} />, {})
.addStory(
'RatingDisplay size small with value and count',
() => <RatingDisplay size="small" value={5} count={1160} />,
{},
)
.addStory('RatingDisplay size medium with value', () => <RatingDisplay size="medium" value={3} />, {})
.addStory(
'RatingDisplay size medium with value and count',
() => <RatingDisplay size="medium" value={5} count={1160} />,
{},
)
.addStory('RatingDisplay size large with value', () => <RatingDisplay size="large" value={3} />, {})
.addStory(
'RatingDisplay size large with value and count',
() => <RatingDisplay size="large" value={5} count={1160} />,
{},
)
.addStory('RatingDisplay size extra large with value', () => <RatingDisplay size="extra-large" value={3} />, {})
.addStory(
'RatingDisplay size extra large with value and count',
() => <RatingDisplay size="extra-large" value={5} count={1160} />,
{},
);

storiesOf('RatingDisplay Converged Custom Icons', module)
.addStory(
'RatingDisplay with custom circle icons',
() => <RatingDisplay iconFilled={<CircleFilled />} iconOutline={<CircleRegular />} value={3} />,
{},
)
.addStory(
'RatingDisplay with custom square icons',
() => <RatingDisplay iconFilled={<SquareFilled />} iconOutline={<SquareRegular />} value={3} />,
{},
);

storiesOf('RatingDisplay Converged Color', module)
.addStory('Neutral RatingDisplay with half value', () => <RatingDisplay value={2.5} />, {
includeHighContrast: true,
includeDarkMode: true,
})
.addStory('Brand RatingDisplay with half value', () => <RatingDisplay value={2.5} color="brand" />, {
includeHighContrast: true,
includeDarkMode: true,
})
.addStory('Marigold RatingDisplay with half value', () => <RatingDisplay value={2.5} color="marigold" />, {
includeHighContrast: true,
includeDarkMode: true,
})
.addStory('Compact RatingDisplay', () => <RatingDisplay compact value={3} />, {});
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "patch",
"comment": "chore: add accesibility props to Rating and RatingDisplay",
"packageName": "@fluentui/react-rating-preview",
"email": "[email protected]",
"dependentChangeType": "patch"
}
Original file line number Diff line number Diff line change
@@ -1,15 +1,54 @@
import * as React from 'react';
import { render } from '@testing-library/react';
// import { isConformant } from '../../testing/isConformant';
import { isConformant } from '../../testing/isConformant';
import { Rating } from './Rating';

describe('Rating', () => {
// isConformant({
// Component: Rating,
// displayName: 'Rating',
// });
it('renders a default state', () => {
const result = render(<Rating>Default RatingItem</Rating>);
expect(result.container).toMatchSnapshot();
isConformant({
Component: Rating,
displayName: 'Rating',
// TODO re-enable consistent-callback-args once https://github.com/microsoft/fluentui/pull/30376 is merged
disabledTests: ['consistent-callback-args'],
});
it('respects a default value', () => {
const { getAllByRole } = render(<Rating defaultValue={3} />);
const checkedItems = getAllByRole('radio').filter(item => (item as HTMLInputElement).checked);
expect(checkedItems[0].getAttribute('value')).toBe('3');
});
it('only sets the selected rating item to checked', () => {
const { getAllByRole } = render(<Rating value={3} />);
const checkedItems = getAllByRole('radio').filter(item => (item as HTMLInputElement).checked);
expect(checkedItems.length).toEqual(1);
});
it('renders the correct number of items', () => {
const { getAllByRole } = render(<Rating max={10} />);
const items = getAllByRole('radio');
expect(items.length).toEqual(10);
});
it('calle onChange when a rating is clicked', () => {
const onChange = jest.fn();
const { getAllByRole } = render(<Rating onChange={onChange} />);
const items = getAllByRole('radio');
items[0].click();
expect(onChange).toHaveBeenCalledTimes(1);
});
it('does not call onChange when a rating is clicked and the value is the same', () => {
const onChange = jest.fn();
const { getAllByRole } = render(<Rating value={3} onChange={onChange} />);
const items = getAllByRole('radio');
items[2].click();
expect(onChange).toHaveBeenCalledTimes(0);
});
it('calls onChange with the correct value when a rating is clicked', () => {
const onChange = jest.fn();
const { getAllByRole } = render(<Rating onChange={onChange} />);
const items = getAllByRole('radio');
items[3].click();
items[2].click();
items[1].click();
expect(onChange).toHaveBeenCalledTimes(3);
expect(onChange.mock.calls[0][1].value).toBe(4);
expect(onChange.mock.calls[1][1].value).toBe(3);
expect(onChange.mock.calls[2][1].value).toBe(2);
});
});

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,18 +1,42 @@
import * as React from 'react';
import { render } from '@testing-library/react';
//import { isConformant } from '../../testing/isConformant';
import { isConformant } from '../../testing/isConformant';
import { RatingDisplay } from './RatingDisplay';

describe('RatingDisplay', () => {
// isConformant({
// Component: RatingDisplay,
// displayName: 'RatingDisplay',
// });

// TODO add more tests here, and create visual regression tests in /apps/vr-tests

it('renders a default state', () => {
const result = render(<RatingDisplay>Default RatingDisplay</RatingDisplay>);
expect(result.container).toMatchSnapshot();
isConformant({
Component: RatingDisplay,
displayName: 'RatingDisplay',
requiredProps: { count: 1160, value: 4.5 },
});
it('renders the correct number of items', () => {
const { getByRole } = render(<RatingDisplay max={10} />);
const items = getByRole('img');
expect(items.getElementsByClassName('fui-RatingItem').length).toEqual(10);
});
it('renders the valueText slot when a value is provided', () => {
const { getByRole } = render(<RatingDisplay value={3} />);
const items = getByRole('img');
expect(items.getElementsByClassName('fui-RatingDisplay__valueText').length).toEqual(1);
});
it('does not render the valueText slot when a value is not provided', () => {
const { getByRole } = render(<RatingDisplay />);
const items = getByRole('img');
expect(items.getElementsByClassName('fui-RatingDisplay__valueText').length).toEqual(0);
});
it('renders the countText slot when a count is provided', () => {
const { getByRole } = render(<RatingDisplay count={1160} />);
const items = getByRole('img');
expect(items.getElementsByClassName('fui-RatingDisplay__countText').length).toEqual(1);
});
it('does not render the countText slot when a count is not provided', () => {
const { getByRole } = render(<RatingDisplay />);
const items = getByRole('img');
expect(items.getElementsByClassName('fui-RatingDisplay__countText').length).toEqual(0);
});
it('renders only one item when compact is true', () => {
const { getByRole } = render(<RatingDisplay compact />);
const items = getByRole('img');
expect(items.getElementsByClassName('fui-RatingItem').length).toEqual(1);
});
});

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,10 +1,108 @@
import * as React from 'react';
import { render } from '@testing-library/react';
import { queryAllByRole, render } from '@testing-library/react';
import { isConformant } from '../../testing/isConformant';
import { RatingItem } from './RatingItem';
import { RatingItemProvider } from '../../contexts/RatingItemContext';
import { RatingItemContextValue } from './RatingItem.types';
import { StarFilled, StarRegular } from '@fluentui/react-icons';

describe('RatingItem', () => {
it('renders a default state', () => {
const result = render(<RatingItem>Default RatingItem</RatingItem>);
expect(result.container).toMatchSnapshot();
isConformant({
Component: RatingItem,
displayName: 'RatingItem',
// Need to disable this test because certain slots are not rendered without specific context values
disabledTests: ['component-has-static-classnames-object'],
});
it('does not render input elements when interactive is false', () => {
const contextValues: RatingItemContextValue = {
value: 3,
interactive: false,
iconFilled: <StarFilled />,
iconOutline: <StarRegular />,
color: 'neutral',
step: 1,
size: 'medium',
};
const { getByTestId } = render(
<RatingItemProvider value={contextValues}>
<RatingItem value={2} data-testid="test" />
</RatingItemProvider>,
);
const items = getByTestId('test');
expect(items.getElementsByTagName('input').length).toEqual(0);
});
it('renders only the full value input when step is 1 and interactive is true', () => {
const contextValues: RatingItemContextValue = {
value: 3,
interactive: true,
iconFilled: <StarFilled />,
iconOutline: <StarRegular />,
color: 'neutral',
step: 1,
size: 'medium',
};
const { getByTestId } = render(
<RatingItemProvider value={contextValues}>
<RatingItem value={2} data-testid="test" />
</RatingItemProvider>,
);
const items = getByTestId('test');
expect(items.getElementsByTagName('input').length).toEqual(1);
});
it('renders both the full value input and the half value input when step is 0.5 and interactive is true', () => {
const contextValues: RatingItemContextValue = {
value: 3,
interactive: true,
iconFilled: <StarFilled />,
iconOutline: <StarRegular />,
color: 'neutral',
step: 0.5,
size: 'medium',
};
const { getByTestId } = render(
<RatingItemProvider value={contextValues}>
<RatingItem value={2} data-testid="test" />
</RatingItemProvider>,
);
const items = getByTestId('test');
expect(items.getElementsByTagName('input').length).toEqual(2);
});
it('sets the half value input to checked when the value is 2.5', () => {
const contextValues: RatingItemContextValue = {
value: 2.5,
interactive: true,
iconFilled: <StarFilled />,
iconOutline: <StarRegular />,
color: 'neutral',
step: 0.5,
size: 'medium',
};
const { getByTestId } = render(
<RatingItemProvider value={contextValues}>
<RatingItem value={2.5} data-testid="test" />
</RatingItemProvider>,
);
const items = getByTestId('test');
const checkedItems = queryAllByRole(items, 'radio').filter(item => (item as HTMLInputElement).checked);
expect(checkedItems.length).toEqual(1);
});
it('sets the full value input to checked when the value is 3', () => {
const contextValues: RatingItemContextValue = {
value: 3,
interactive: true,
iconFilled: <StarFilled />,
iconOutline: <StarRegular />,
color: 'neutral',
step: 1,
size: 'medium',
};
const { getByTestId } = render(
<RatingItemProvider value={contextValues}>
<RatingItem value={3} data-testid="test" />
</RatingItemProvider>,
);
const items = getByTestId('test');
const checkedItems = queryAllByRole(items, 'radio').filter(item => (item as HTMLInputElement).checked);
expect(checkedItems.length).toEqual(1);
});
});
Loading
Loading