-
Notifications
You must be signed in to change notification settings - Fork 2.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add unit and vr tests to Rating (#30414)
- Loading branch information
Showing
10 changed files
with
288 additions
and
76 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
58 changes: 58 additions & 0 deletions
58
apps/vr-tests-react-components/src/stories/Rating.stories.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
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', module) | ||
.addDecorator(TestWrapperDecoratorFixedWidth) | ||
.addDecorator(story => ( | ||
<StoryWright | ||
steps={new Steps() | ||
.snapshot('rest', { cropTo: '.testWrapper' }) | ||
.hover('input') | ||
.snapshot('hover', { 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', module) | ||
.addDecorator(TestWrapperDecoratorFixedWidth) | ||
.addDecorator(story => ( | ||
<StoryWright steps={new Steps().snapshot('rest', { cropTo: '.testWrapper' }).end()}>{story()}</StoryWright> | ||
)) | ||
.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', module) | ||
.addDecorator(TestWrapperDecoratorFixedWidth) | ||
.addDecorator(story => ( | ||
<StoryWright steps={new Steps().snapshot('rest', { cropTo: '.testWrapper' }).end()}>{story()}</StoryWright> | ||
)) | ||
.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} />, | ||
{}, | ||
); |
34 changes: 34 additions & 0 deletions
34
apps/vr-tests-react-components/src/stories/RatingDisplay.stories.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
import * as React from 'react'; | ||
import { storiesOf } from '@storybook/react'; | ||
import { CircleFilled, SquareFilled } from '@fluentui/react-icons'; | ||
import { RatingDisplay } from '@fluentui/react-rating-preview'; | ||
import { TestWrapperDecoratorFixedWidth } from '../utilities/TestWrapperDecorator'; | ||
import { Steps, StoryWright } from 'storywright'; | ||
|
||
storiesOf('RatingDisplay Converged', module) | ||
.addDecorator(TestWrapperDecoratorFixedWidth) | ||
.addDecorator(story => ( | ||
<StoryWright steps={new Steps().snapshot('rest', { cropTo: '.testWrapper' }).end()}>{story()}</StoryWright> | ||
)) | ||
.addStory('no value', () => <RatingDisplay />) | ||
.addStory('size small with value and count', () => <RatingDisplay size="small" value={5} count={1160} />) | ||
.addStory('size medium with value and count', () => <RatingDisplay size="medium" value={5} count={1160} />) | ||
.addStory('size large with value and count', () => <RatingDisplay size="large" value={5} count={1160} />) | ||
.addStory('size extra-large with value and count', () => <RatingDisplay size="extra-large" value={5} count={1160} />) | ||
.addStory('custom circle icons', () => <RatingDisplay icon={<CircleFilled />} value={3} />) | ||
.addStory('custom square icons', () => <RatingDisplay icon={<SquareFilled />} value={3} />) | ||
.addStory('rounded up', () => <RatingDisplay value={3.8} />) | ||
.addStory('rounded down', () => <RatingDisplay value={3.7} />) | ||
.addStory('Neutral with half value', () => <RatingDisplay value={2.5} />, { | ||
includeHighContrast: true, | ||
includeDarkMode: true, | ||
}) | ||
.addStory('Brand with half value', () => <RatingDisplay value={2.5} color="brand" />, { | ||
includeHighContrast: true, | ||
includeDarkMode: true, | ||
}) | ||
.addStory('Marigold with half value', () => <RatingDisplay value={2.5} color="marigold" />, { | ||
includeHighContrast: true, | ||
includeDarkMode: true, | ||
}) | ||
.addStory('Compact', () => <RatingDisplay compact value={3} />, {}); |
7 changes: 7 additions & 0 deletions
7
change/@fluentui-react-rating-preview-53ee592c-ae0d-4b3b-9828-2c08ee70057e.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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" | ||
} |
57 changes: 49 additions & 8 deletions
57
packages/react-components/react-rating-preview/src/components/Rating/Rating.test.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,15 +1,56 @@ | ||
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'); | ||
expect(checkedItems.length).toEqual(1); | ||
}); | ||
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[0].getAttribute('value')).toBe('3'); | ||
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); | ||
}); | ||
}); |
12 changes: 0 additions & 12 deletions
12
...-components/react-rating-preview/src/components/Rating/__snapshots__/Rating.test.tsx.snap
This file was deleted.
Oops, something went wrong.
45 changes: 34 additions & 11 deletions
45
...react-components/react-rating-preview/src/components/RatingDisplay/RatingDisplay.test.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,18 +1,41 @@ | ||
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} />); | ||
expect(getByRole('img').children.length).toEqual(10); | ||
}); | ||
it('renders the valueText slot when a value is provided', () => { | ||
const { getByText } = render(<RatingDisplay value={3} />); | ||
const valueText = getByText('3'); | ||
expect(valueText).toBeDefined(); | ||
expect(valueText.classList.contains('fui-RatingDisplay__valueText')).toBeTruthy(); | ||
}); | ||
it('does not render the valueText slot when a value is not provided', () => { | ||
const { container } = render(<RatingDisplay />); | ||
expect(container?.querySelector('.fui-RatingDisplay__valueText')).toBeNull(); | ||
}); | ||
it('renders the countText slot when a count is provided', () => { | ||
const { getByText } = render(<RatingDisplay count={1160} />); | ||
const countText = getByText('1,160'); | ||
expect(countText).toBeDefined(); | ||
expect(countText.classList.contains('fui-RatingDisplay__countText')).toBeTruthy(); | ||
}); | ||
it('does not render the countText slot when a count is not provided', () => { | ||
const { container } = render(<RatingDisplay />); | ||
expect(container?.querySelector('.fui-RatingDisplay__countText')).toBeNull(); | ||
}); | ||
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); | ||
}); | ||
}); |
13 changes: 0 additions & 13 deletions
13
...act-rating-preview/src/components/RatingDisplay/__snapshots__/RatingDisplay.test.tsx.snap
This file was deleted.
Oops, something went wrong.
108 changes: 105 additions & 3 deletions
108
packages/react-components/react-rating-preview/src/components/RatingItem/RatingItem.test.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,112 @@ | ||
import * as React from 'react'; | ||
import { 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 { queryAllByRole } = render( | ||
<RatingItemProvider value={contextValues}> | ||
<RatingItem value={2} /> | ||
</RatingItemProvider>, | ||
); | ||
const inputs = queryAllByRole('radio'); | ||
expect(inputs.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 { getByRole } = render( | ||
<RatingItemProvider value={contextValues}> | ||
<RatingItem value={2} /> | ||
</RatingItemProvider>, | ||
); | ||
const input = getByRole('radio') as HTMLInputElement; | ||
expect(input.value).toEqual('2'); | ||
}); | ||
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 { getAllByRole } = render( | ||
<RatingItemProvider value={contextValues}> | ||
<RatingItem value={2} /> | ||
</RatingItemProvider>, | ||
); | ||
const inputs = getAllByRole('radio') as HTMLInputElement[]; | ||
expect(inputs.length).toEqual(2); | ||
expect(inputs[0].value).toEqual('1.5'); | ||
expect(inputs[1].value).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 { queryAllByRole } = render( | ||
<RatingItemProvider value={contextValues}> | ||
<RatingItem value={3} /> | ||
</RatingItemProvider>, | ||
); | ||
const inputs = queryAllByRole('radio') as HTMLInputElement[]; | ||
const checkedInputs = inputs.filter(input => input.checked); | ||
expect(checkedInputs.length).toEqual(1); | ||
expect(checkedInputs[0].value).toEqual(contextValues.value?.toString()); | ||
}); | ||
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 { queryAllByRole } = render( | ||
<RatingItemProvider value={contextValues}> | ||
<RatingItem value={3} /> | ||
</RatingItemProvider>, | ||
); | ||
const inputs = queryAllByRole('radio') as HTMLInputElement[]; | ||
const checkedInputs = inputs.filter(input => input.checked); | ||
expect(checkedInputs.length).toEqual(1); | ||
expect(checkedInputs[0].value).toEqual(contextValues.value?.toString()); | ||
}); | ||
}); |
Oops, something went wrong.