Skip to content

feat: improve conformance test to check argument types#20096

Merged
layershifter merged 9 commits intomasterfrom
test/conformance-arg-types
Oct 20, 2021
Merged

feat: improve conformance test to check argument types#20096
layershifter merged 9 commits intomasterfrom
test/conformance-arg-types

Conversation

@layershifter
Copy link
Member

@layershifter layershifter commented Oct 4, 2021

Pull request checklist

Sample error of the test

image

Description of changes

This PR improves consistent-callback-args conformance test to also check types of parameters 🎉

  • getCallbackArguments() was improve to handle types resolution, i.e. resolve OnOpenChange types
  • new validateCallbackArguments() provides detailed error reporting

Other change 💥

I have to update types in Menu and Popover to simplify them as resolving Pick is not the simplest thing 😐

@fabricteam
Copy link
Collaborator

fabricteam commented Oct 4, 2021

📊 Bundle size report

Unchanged fixtures
Package & Exports Size (minified/GZIP)
react-accordion
Accordion (including children components)
57.694 kB
18.16 kB
react-avatar
Avatar
54.953 kB
15.667 kB
react-badge
Badge
23.182 kB
6.986 kB
react-badge
CounterBadge
25.642 kB
7.682 kB
react-badge
PresenseBadge
237 B
177 B
react-button
Button
25.501 kB
7.738 kB
react-button
CompoundButton
30.758 kB
8.689 kB
react-button
MenuButton
27.526 kB
8.413 kB
react-button
SplitButton
33.637 kB
9.597 kB
react-button
ToggleButton
34.727 kB
8.39 kB
react-card
Card - All
48.995 kB
14.558 kB
react-card
Card
44.482 kB
13.339 kB
react-card
CardFooter
8.128 kB
3.424 kB
react-card
CardHeader
9.448 kB
3.878 kB
react-card
CardPreview
8.421 kB
3.599 kB
react-components
react-components: Accordion, Button, FluentProvider, Image, Menu, Popover
169.335 kB
48.057 kB
react-components
react-components: FluentProvider & webLightTheme
32.188 kB
10.658 kB
react-divider
Divider
15.342 kB
5.585 kB
react-image
Image
9.771 kB
3.975 kB
react-input
Input
31.319 kB
11.305 kB
react-label
Label
8.952 kB
3.708 kB
react-link
Link
11.646 kB
4.699 kB
react-menu
Menu (including children components)
105.789 kB
32.202 kB
react-menu
Menu (including selectable components)
108.065 kB
32.575 kB
react-popover
Popover
101.153 kB
30.37 kB
react-portal
Portal
6.725 kB
2.237 kB
react-provider
FluentProvider
15.147 kB
5.573 kB
react-slider
RangedSlider
41.41 kB
11.97 kB
react-slider
Slider
34.788 kB
10.855 kB
react-switch
Switch
26.602 kB
8.557 kB
react-text
Text - Default
11.338 kB
4.418 kB
react-text
Text - Wrappers
14.407 kB
4.724 kB
react-tooltip
Tooltip
45.543 kB
15.541 kB
🤖 This report was generated against f728d06fc101970d9d42b5f46de6806a59a0a0c5

@size-auditor
Copy link

size-auditor bot commented Oct 5, 2021

Asset size changes

Size Auditor did not detect a change in bundle size for any component!

Baseline commit: f728d06fc101970d9d42b5f46de6806a59a0a0c5 (build)

@codesandbox-ci
Copy link

codesandbox-ci bot commented Oct 5, 2021

This pull request is automatically built and testable in CodeSandbox.

To see build info of the built libraries, click here or the icon next to each commit SHA.

Latest deployment of this branch, based on commit 481ddaa:

Sandbox Source
@fluentui/react 8 starter Configuration
@fluentui/react-components 9 starter Configuration

@fabricteam
Copy link
Collaborator

fabricteam commented Oct 5, 2021

Perf Analysis (@fluentui/react)

No significant results to display.

All results

Scenario Render type Master Ticks PR Ticks Iterations Status
Avatar mount 1000 999 5000
BaseButton mount 1037 1054 5000
Breadcrumb mount 2785 2781 1000
ButtonNext mount 555 549 5000
Checkbox mount 1718 1691 5000
CheckboxBase mount 1471 1519 5000
ChoiceGroup mount 5354 5243 5000
ComboBox mount 1069 1058 1000
CommandBar mount 10887 10920 1000
ContextualMenu mount 7073 6890 1000
DefaultButton mount 1264 1273 5000
DetailsRow mount 4125 4115 5000
DetailsRowFast mount 4132 4135 5000
DetailsRowNoStyles mount 3918 3913 5000
Dialog mount 2687 2698 1000
DocumentCardTitle mount 193 191 1000
Dropdown mount 3666 3685 5000
FluentProviderNext mount 3523 3442 5000
FluentProviderWithTheme mount 222 221 10
FluentProviderWithTheme virtual-rerender 110 102 10
FluentProviderWithTheme virtual-rerender-with-unmount 257 255 10
FocusTrapZone mount 1964 1950 5000
FocusZone mount 1977 1993 5000
IconButton mount 2002 1979 5000
Label mount 376 382 5000
Layer mount 3337 3318 5000
Link mount 541 537 5000
MakeStyles mount 2011 1976 50000
MenuButton mount 1671 1711 5000
MessageBar mount 2279 2188 5000
Nav mount 3662 3671 1000
OverflowSet mount 1247 1226 5000
Panel mount 2483 2634 1000
Persona mount 950 946 1000
Pivot mount 1586 1642 1000
PrimaryButton mount 1415 1445 5000
Rating mount 8732 8858 5000
SearchBox mount 1514 1515 5000
Shimmer mount 2807 2844 5000
Slider mount 2139 2194 5000
SpinButton mount 5529 5465 5000
Spinner mount 462 459 5000
SplitButton mount 3445 3802 5000
Stack mount 588 576 5000
StackWithIntrinsicChildren mount 1923 1961 5000
StackWithTextChildren mount 5444 5308 5000
SwatchColorPicker mount 11443 11455 5000
Tabs mount 1576 1552 1000
TagPicker mount 2862 2880 5000
TeachingBubble mount 13940 13931 5000
Text mount 493 480 5000
TextField mount 1573 1534 5000
ThemeProvider mount 1314 1302 5000
ThemeProvider virtual-rerender 653 657 5000
ThemeProvider virtual-rerender-with-unmount 2075 2077 5000
Toggle mount 887 896 5000
buttonNative mount 155 151 5000

Perf Analysis (@fluentui/react-northstar)

Perf tests with no regressions
Scenario Current PR Ticks Baseline Ticks Ratio
AttachmentMinimalPerf.default 208 178 1.17:1
AccordionMinimalPerf.default 191 171 1.12:1
RefMinimalPerf.default 266 245 1.09:1
FormMinimalPerf.default 492 456 1.08:1
ReactionMinimalPerf.default 448 416 1.08:1
ButtonMinimalPerf.default 211 198 1.07:1
ImageMinimalPerf.default 442 418 1.06:1
LabelMinimalPerf.default 455 428 1.06:1
FlexMinimalPerf.default 325 311 1.05:1
TreeWith60ListItems.default 210 200 1.05:1
AnimationMinimalPerf.default 467 447 1.04:1
AvatarMinimalPerf.default 223 214 1.04:1
ChatDuplicateMessagesPerf.default 348 334 1.04:1
DialogMinimalPerf.default 846 815 1.04:1
HeaderMinimalPerf.default 434 418 1.04:1
PortalMinimalPerf.default 192 185 1.04:1
SkeletonMinimalPerf.default 429 411 1.04:1
TextMinimalPerf.default 400 384 1.04:1
TreeMinimalPerf.default 905 870 1.04:1
ChatWithPopoverPerf.default 430 417 1.03:1
TableManyItemsPerf.default 2192 2137 1.03:1
VideoMinimalPerf.default 739 720 1.03:1
ChatMinimalPerf.default 760 745 1.02:1
DropdownMinimalPerf.default 3430 3352 1.02:1
HeaderSlotsPerf.default 869 851 1.02:1
InputMinimalPerf.default 1444 1422 1.02:1
LayoutMinimalPerf.default 421 413 1.02:1
SliderMinimalPerf.default 1868 1832 1.02:1
TextAreaMinimalPerf.default 592 580 1.02:1
TooltipMinimalPerf.default 1173 1147 1.02:1
CardMinimalPerf.default 641 635 1.01:1
CarouselMinimalPerf.default 541 534 1.01:1
EmbedMinimalPerf.default 4677 4629 1.01:1
ItemLayoutMinimalPerf.default 1356 1347 1.01:1
ListCommonPerf.default 719 712 1.01:1
ListMinimalPerf.default 570 566 1.01:1
ListNestedPerf.default 646 637 1.01:1
LoaderMinimalPerf.default 764 756 1.01:1
MenuMinimalPerf.default 956 944 1.01:1
MenuButtonMinimalPerf.default 1833 1814 1.01:1
ProviderMinimalPerf.default 1241 1231 1.01:1
RadioGroupMinimalPerf.default 521 514 1.01:1
SegmentMinimalPerf.default 406 403 1.01:1
IconMinimalPerf.default 690 681 1.01:1
ToolbarMinimalPerf.default 1062 1051 1.01:1
BoxMinimalPerf.default 395 395 1:1
ButtonOverridesMissPerf.default 1967 1958 1:1
ButtonSlotsPerf.default 643 640 1:1
ListWith60ListItems.default 717 717 1:1
PopupMinimalPerf.default 632 634 1:1
SplitButtonMinimalPerf.default 4732 4718 1:1
CustomToolbarPrototype.default 4451 4454 1:1
DatepickerMinimalPerf.default 6032 6068 0.99:1
DividerMinimalPerf.default 417 421 0.99:1
GridMinimalPerf.default 391 395 0.99:1
ProviderMergeThemesPerf.default 1800 1815 0.99:1
StatusMinimalPerf.default 775 782 0.99:1
AlertMinimalPerf.default 304 309 0.98:1
CheckboxMinimalPerf.default 2936 3001 0.98:1
AttachmentSlotsPerf.default 1194 1237 0.97:1
RosterPerf.default 1336 1388 0.96:1
TableMinimalPerf.default 438 461 0.95:1
DropdownManyItemsPerf.default 773 824 0.94:1

@layershifter layershifter force-pushed the test/conformance-arg-types branch from b0d22b2 to 7eccf6d Compare October 6, 2021 11:23
* Data attached to open/close events
*/
export type OnOpenChangeData = Pick<PopoverState, 'open'>;
export type OnOpenChangeData = { open: boolean };
Copy link
Member Author

Choose a reason for hiding this comment

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

As I mentioned I had to simplify this to avoid handling of Pick<> which is quite complex

Copy link
Contributor

Choose a reason for hiding this comment

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

I someone uses Pick how easy would it be for them to know that test failures are a result of limitations of conformance tests ?

Copy link
Member Author

Choose a reason for hiding this comment

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

I added additional handling in 481ddaa, now it will throw meaningful errors in such cases.

@layershifter layershifter marked this pull request as ready for review October 6, 2021 12:16
@layershifter layershifter requested review from a team, behowell and khmakoto as code owners October 6, 2021 12:16
Copy link
Member

@ecraig12345 ecraig12345 left a comment

Choose a reason for hiding this comment

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

This is great, thanks! Some minor questions and wording suggestions.

}

function typeToString(typeChecker: ts.TypeChecker, type: ts.Type): ArgumentValue | ArgumentValue[] {
if (isIntrinsicType(type)) {
Copy link
Member

Choose a reason for hiding this comment

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

Maybe a silly question, what's an intrinsic type?

Copy link
Member Author

@layershifter layershifter Oct 18, 2021

Choose a reason for hiding this comment

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

export type TypeC = number;

AST viewer

image

Not sure that it's correct explanation: but they are internal TS types.

Copy link
Member Author

Choose a reason for hiding this comment

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

I also made minor rename in 06ea16b to highlight when we deal with ts.Type vs ts.TypeNode

// "React" types are handled separately to add "React." prefix otherwise it's impossible to distinguish
// "React.MouseEvent" and "MouseEvent" types.

if (/\/node_modules\/@types\/react\//.test(fileName)) {
Copy link
Member

Choose a reason for hiding this comment

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

Do you know for sure that the filename always uses forward slashes?

Copy link
Member Author

@layershifter layershifter Oct 18, 2021

Choose a reason for hiding this comment

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

return parseArgumentType(typeChecker, type.symbol.declarations[0]);
}

if (typeHasSubtypes(type)) {
Copy link
Member

Choose a reason for hiding this comment

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

Maybe another silly question, what's an example of a type with subtypes?

Copy link
Member Author

Choose a reason for hiding this comment

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

The simplest case is below:

export type TypeB = MouseEvent | number;
export type TypeC = number;

export interface AccordionProps {
  onToggle: (b: TypeB) => void;
}

AST viewer

image

(check an Identifier for TypeB)


So it's "a type with union". May be naming should be improved there, any suggestions?


if (typeof valueInUnion === 'string') {
if (valueInUnion === 'Event' || valueInUnion === 'React.SyntheticEvent') {
throw new Error(
Copy link
Member

Choose a reason for hiding this comment

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

I wonder if it would be better to just return an error message rather than throwing in these cases--including the stack from an Error might make things more confusing

Copy link
Member Author

Choose a reason for hiding this comment

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

Probably it's my personal preference from backend background 😀 Technically we can return a message, but then we will need to handle checks during all path:

  const result1 = validateEventArgument(callbackArguments[argumentNames[0]]);
  if(result1) { return result1 }

  const result2 = validateDataArgument(callbackArguments[argumentNames[1]]);
  if (result2) { return result1 }

^ this looks less cleaner for me. Any suggestions?

Copy link
Contributor

Choose a reason for hiding this comment

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

personally I'm a fan of throwing errors too 😀, but the above looks good to me

Copy link
Member

Choose a reason for hiding this comment

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

My concern was less with the control flow (I agree throwing an error is cleaner) and more with the way it will be presented to users through logging, since I don't think the stack from this point would typically be relevant.

Copy link
Member Author

Choose a reason for hiding this comment

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

These errors are handled in the test itself and users will see a proper formatted error message:

image

May be I don't understand something, but I don't see a problem with it 😀

@layershifter layershifter merged commit 1efadb3 into master Oct 20, 2021
@layershifter layershifter deleted the test/conformance-arg-types branch October 20, 2021 10:53
mlp73 pushed a commit to mlp73/fluentui that referenced this pull request Jan 17, 2022
* improve conformance test

* fix lint errors

* improve error messages

* improve error messages

* minor rename

* use arrays

* fix test

* throw errors on complex types

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Implementation of RFC: standardize event handlers arguments

5 participants