@@ -3,7 +3,7 @@ import React from 'react';
33import { render } from '@testing-library/react' ;
44import { parse } from 'react-docgen' ;
55import PropsRenderer , { columns , getRowKey } from './PropsRenderer' ;
6- import { unquote , getType , showSpaces , PropDescriptorWithFlow } from './util' ;
6+ import { unquote , getType , showSpaces , PropDescriptor } from './util' ;
77
88const propsToArray = ( props : any ) => Object . keys ( props ) . map ( name => ( { ...props [ name ] , name } ) ) ;
99
@@ -16,7 +16,7 @@ const getText = (node: { innerHTML: string }): string =>
1616 . trim ( ) ;
1717
1818// Test renderers with clean readable snapshot diffs
19- export default function ColumnsRenderer ( { props } : { props : PropDescriptorWithFlow [ ] } ) {
19+ export default function ColumnsRenderer ( { props } : { props : PropDescriptor [ ] } ) {
2020 return (
2121 < >
2222 { props . map ( ( row , rowIdx ) => (
@@ -58,11 +58,12 @@ function renderJs(propTypes: string[], defaultProps: string[] = []) {
5858 return render ( < ColumnsRenderer props = { propsToArray ( props . props ) } /> ) ;
5959}
6060
61- function renderFlow ( propsType : string [ ] , defaultProps : string [ ] = [ ] ) {
61+ function renderFlow ( propsType : string [ ] , defaultProps : string [ ] = [ ] , preparations : string [ ] = [ ] ) {
6262 const props = parse (
6363 `
6464 // @flow
6565 import * as React from 'react';
66+ ${ preparations . join ( ';' ) }
6667 type Props = {
6768 ${ propsType . join ( ',' ) }
6869 };
@@ -84,6 +85,36 @@ function renderFlow(propsType: string[], defaultProps: string[] = []) {
8485 return render ( < ColumnsRenderer props = { propsToArray ( props . props ) } /> ) ;
8586}
8687
88+ function renderTypeScript (
89+ propsType : string [ ] ,
90+ defaultProps : string [ ] = [ ] ,
91+ preparations : string [ ] = [ ]
92+ ) {
93+ const props = parse (
94+ `
95+ import * as React from 'react';
96+ ${ preparations . join ( ';' ) }
97+ type Props = {
98+ ${ propsType . join ( ';' ) }
99+ };
100+ export default class Cmpnt extends React.Component<Props> {
101+ static defaultProps = {
102+ ${ defaultProps . join ( ',' ) }
103+ }
104+ render() {
105+ }
106+ }
107+ ` ,
108+ undefined ,
109+ undefined ,
110+ { filename : 'Component.tsx' }
111+ ) ;
112+ if ( Array . isArray ( props ) ) {
113+ return render ( < div /> ) ;
114+ }
115+ return render ( < ColumnsRenderer props = { propsToArray ( props . props ) } /> ) ;
116+ }
117+
87118describe ( 'PropsRenderer' , ( ) => {
88119 test ( 'should render a table' , async ( ) => {
89120 const { findAllByRole } = render (
@@ -509,94 +540,107 @@ describe('props columns', () => {
509540 ` ) ;
510541 } ) ;
511542
512- test ( 'should render type string' , ( ) => {
513- const { container } = renderFlow ( [ 'foo: string' ] ) ;
514-
515- expect ( getText ( container ) ) . toMatchInlineSnapshot ( `
516- "Prop name: foo
517- Type: string
518- Default: Required
519- Description:"
520- ` ) ;
521- } ) ;
522-
523- test ( 'should render optional type string' , ( ) => {
524- const { container } = renderFlow ( [ 'foo?: string' ] ) ;
525-
526- expect ( getText ( container ) ) . toMatchInlineSnapshot ( `
527- "Prop name: foo
528- Type: string
529- Default:
530- Description:"
531- ` ) ;
532- } ) ;
533-
534- test ( 'should render type string with a default value' , ( ) => {
535- const { container } = renderFlow ( [ 'foo?: string' ] , [ 'foo: "bar"' ] ) ;
536-
537- expect ( getText ( container ) ) . toMatchInlineSnapshot ( `
538- "Prop name: foo
539- Type: string
540- Default: bar
541- Description:"
542- ` ) ;
543- } ) ;
544-
545- test ( 'should render literal type' , ( ) => {
546- const { container } = renderFlow ( [ 'foo?: "bar"' ] ) ;
547-
548- expect ( getText ( container ) ) . toMatchInlineSnapshot ( `
549- "Prop name: foo
550- Type: \\"bar\\"
551- Default:
552- Description:"
553- ` ) ;
554- } ) ;
555-
556- test ( 'should render object type with body in tooltip' , ( ) => {
557- const { getByText } = renderFlow ( [ 'foo: { bar: string }' ] ) ;
558-
559- expect ( getByText ( 'object' ) . title ) . toMatchInlineSnapshot ( `"{ bar: string }"` ) ;
560- } ) ;
561-
562- test ( 'should render function type with body in tooltip' , ( ) => {
563- const { getByText } = renderFlow ( [ 'foo: () => void' ] ) ;
564-
565- expect ( getByText ( 'function' ) . title ) . toMatchInlineSnapshot ( `"() => void"` ) ;
566- } ) ;
567-
568- test ( 'should render union type with body in tooltip' , ( ) => {
569- const { getByText } = renderFlow ( [ 'foo: "bar" | number' ] ) ;
570-
571- expect ( getByText ( 'union' ) . title ) . toMatchInlineSnapshot ( `"\\"bar\\" | number"` ) ;
572- } ) ;
573-
574- test ( 'should render enum type when union of literals' , ( ) => {
575- const { container } = renderFlow ( [ 'foo: "bar" | "baz"' ] ) ;
576-
577- expect ( getText ( container ) ) . toMatchInlineSnapshot ( `
578- "Prop name: foo
579- Type: enum
580- Default: Required
581- Description:"
582- ` ) ;
583- } ) ;
584-
585- test ( 'should render tuple type with body in tooltip' , ( ) => {
586- const { getByText } = renderFlow ( [ 'foo: ["bar", number]' ] ) ;
587-
588- expect ( getByText ( 'tuple' ) . title ) . toMatchInlineSnapshot ( `"[\\"bar\\", number]"` ) ;
589- } ) ;
590-
591- test ( 'should render custom class type' , ( ) => {
592- const { container } = renderFlow ( [ 'foo: React.ReactNode' ] ) ;
593-
594- expect ( getText ( container ) ) . toMatchInlineSnapshot ( `
595- "Prop name: foo
596- Type: React.ReactNode
597- Default: Required
598- Description:"
599- ` ) ;
543+ describe . each ( [
544+ [
545+ 'flowType' ,
546+ renderFlow ,
547+ { enum : { declaration : "type MyEnum = 'One' | 'Two'" , expect : { type : 'enum' } } } ,
548+ ] ,
549+ [
550+ 'TypeScript' ,
551+ renderTypeScript ,
552+ { enum : { declaration : 'enum MyEnum { One, Two }' , expect : { type : 'MyEnum' } } } ,
553+ ] ,
554+ ] ) ( '%s' , ( _ , renderFn , options ) => {
555+ test ( 'should render type string' , ( ) => {
556+ const { container } = renderFn ( [ 'foo: string' ] ) ;
557+
558+ expect ( getText ( container ) ) . toMatchInlineSnapshot ( `
559+ "Prop name: foo
560+ Type: string
561+ Default: Required
562+ Description:"
563+ ` ) ;
564+ } ) ;
565+
566+ test ( 'should render optional type string' , ( ) => {
567+ const { container } = renderFn ( [ 'foo?: string' ] ) ;
568+
569+ expect ( getText ( container ) ) . toMatchInlineSnapshot ( `
570+ "Prop name: foo
571+ Type: string
572+ Default:
573+ Description:"
574+ ` ) ;
575+ } ) ;
576+
577+ test ( 'should render type string with a default value' , ( ) => {
578+ const { container } = renderFn ( [ 'foo?: string' ] , [ 'foo: "bar"' ] ) ;
579+
580+ expect ( getText ( container ) ) . toMatchInlineSnapshot ( `
581+ "Prop name: foo
582+ Type: string
583+ Default: bar
584+ Description:"
585+ ` ) ;
586+ } ) ;
587+
588+ test ( 'should render object type with body in tooltip' , ( ) => {
589+ const { getByText } = renderFn ( [ 'foo: { bar: string }' ] ) ;
590+
591+ expect ( getByText ( 'object' ) . title ) . toMatchInlineSnapshot ( `"{ bar: string }"` ) ;
592+ } ) ;
593+
594+ test ( 'should render function type with body in tooltip' , ( ) => {
595+ const { getByText } = renderFn ( [ 'foo: () => void' ] ) ;
596+
597+ expect ( getByText ( 'function' ) . title ) . toMatchInlineSnapshot ( `"() => void"` ) ;
598+ } ) ;
599+
600+ test ( 'should render union type with body in tooltip' , ( ) => {
601+ const { getByText } = renderFn ( [ 'foo: "bar" | number' ] ) ;
602+
603+ expect ( getByText ( 'union' ) . title ) . toMatchInlineSnapshot ( `"\\"bar\\" | number"` ) ;
604+ } ) ;
605+
606+ test ( 'should render enum type' , ( ) => {
607+ const { container } = renderFn ( [ 'foo: MyEnum' ] , [ ] , [ options . enum . declaration ] ) ;
608+
609+ expect ( getText ( container ) ) . toMatchInlineSnapshot ( `
610+ "Prop name: foo
611+ Type: ${ options . enum . expect . type }
612+ Default: Required
613+ Description:"
614+ ` ) ;
615+ } ) ;
616+
617+ test ( 'should render tuple type with body in tooltip' , ( ) => {
618+ const { getByText } = renderFn ( [ 'foo: ["bar", number]' ] ) ;
619+
620+ expect ( getByText ( 'tuple' ) . title ) . toMatchInlineSnapshot ( `"[\\"bar\\", number]"` ) ;
621+ } ) ;
622+
623+ test ( 'should render custom class type' , ( ) => {
624+ const { container } = renderFn ( [ 'foo: React.ReactNode' ] ) ;
625+
626+ expect ( getText ( container ) ) . toMatchInlineSnapshot ( `
627+ "Prop name: foo
628+ Type: React.ReactNode
629+ Default: Required
630+ Description:"
631+ ` ) ;
632+ } ) ;
633+
634+ test ( 'should render unknown when a relevant prop type is not assigned' , ( ) => {
635+ const { container } = renderFn ( [ ] , [ 'color: "pink"' ] ) ;
636+
637+ expect ( getText ( container ) ) . toMatchInlineSnapshot ( `
638+ "Prop name: color
639+ Type:
640+ Default: pink
641+ Description:"
642+ ` ) ;
643+ } ) ;
600644 } ) ;
601645} ) ;
602646
@@ -618,13 +662,28 @@ describe('unquote', () => {
618662} ) ;
619663
620664describe ( 'getType' , ( ) => {
621- test ( 'should return .type or .flowType property' , ( ) => {
665+ test ( 'should return not .type but .flowType property' , ( ) => {
622666 const result = getType ( {
623667 type : 'foo' ,
624668 flowType : 'bar' ,
625669 } as any ) ;
626670 expect ( result ) . toBe ( 'bar' ) ;
627671 } ) ;
672+
673+ test ( 'should return not .type but .tsType property' , ( ) => {
674+ const result = getType ( {
675+ type : 'foo' ,
676+ tsType : 'bar' ,
677+ } as any ) ;
678+ expect ( result ) . toBe ( 'bar' ) ;
679+ } ) ;
680+
681+ test ( 'should return .type property' , ( ) => {
682+ const result = getType ( {
683+ type : 'foo' ,
684+ } as any ) ;
685+ expect ( result ) . toBe ( 'foo' ) ;
686+ } ) ;
628687} ) ;
629688
630689describe ( 'showSpaces' , ( ) => {
0 commit comments