UNPKG

react-docgen-typescript

Version:

[![Build Status](https://github.com/styleguidist/react-docgen-typescript/actions/workflows/nodejs.yml/badge.svg)](https://github.com/styleguidist/react-docgen-typescript/actions/workflows/nodejs.yml)

1,132 lines 65.1 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var chai_1 = require("chai"); var fs = require("fs"); var path = require("path"); var ts = require("typescript"); var parser_1 = require("../parser"); var testUtils_1 = require("./testUtils"); describe('parser', function () { it('should parse simple react class component', function () { (0, testUtils_1.check)('Column', { Column: { prop1: { type: 'string', required: false }, prop2: { type: 'number' }, prop3: { type: '() => void' }, prop4: { type: '"option1" | "option2" | "option3"' } } }); }); it('should parse simple react class component with console.log inside', function () { (0, testUtils_1.check)('ColumnWithLog', { Column: { prop1: { type: 'string', required: false }, prop2: { type: 'number' }, prop3: { type: '() => void' }, prop4: { type: '"option1" | "option2" | "option3"' } } }); }); it('should parse simple react class component as default export', function () { (0, testUtils_1.check)('ColumnWithDefaultExport', { Column: { prop1: { type: 'string', required: false }, prop2: { type: 'number' }, prop3: { type: '() => void' }, prop4: { type: '"option1" | "option2" | "option3"' } } }); }); describe('file path', function () { it('should return the correct filepath for a parsed component', function () { var results = (0, parser_1.parse)([(0, testUtils_1.fixturePath)('FilePathCheck')]); results.forEach(function (result) { chai_1.assert.equal(result.filePath, path.resolve('src/__tests__/data/FilePathCheck.tsx')); }); }); it('should return the correct filepath for multiple parsed components', function () { var results = (0, parser_1.parse)([ (0, testUtils_1.fixturePath)('FilePathCheck'), (0, testUtils_1.fixturePath)('Column'), (0, testUtils_1.fixturePath)('ColumnWithDefaultExportOnly') ]); var paths = [ path.resolve('src/__tests__/data/FilePathCheck.tsx'), path.resolve('src/__tests__/data/Column.tsx'), path.resolve('src/__tests__/data/ColumnWithDefaultExportOnly.tsx') ]; results.forEach(function (result, index) { chai_1.assert.equal(result.filePath, paths[index]); }); }); }); it('should parse mulitple files', function () { var result = (0, parser_1.parse)([ (0, testUtils_1.fixturePath)('Column'), (0, testUtils_1.fixturePath)('ColumnWithDefaultExportOnly') ]); (0, testUtils_1.checkComponent)(result, { Column: {}, ColumnWithDefaultExportOnly: {} }, false); }); it('should parse simple react class component as default export only', function () { (0, testUtils_1.check)('ColumnWithDefaultExportOnly', { ColumnWithDefaultExportOnly: { prop1: { type: 'string', required: false }, prop2: { type: 'number' }, prop3: { type: '() => void' }, prop4: { type: '"option1" | "option2" | "option3"' } } }); }); it('should parse simple react class component as default anonymous export', function () { (0, testUtils_1.check)('ColumnWithDefaultAnonymousExportOnly', { ColumnWithDefaultAnonymousExportOnly: { prop1: { type: 'string', required: false }, prop2: { type: 'number' }, prop3: { type: '() => void' }, prop4: { type: '"option1" | "option2" | "option3"' } } }); }); it('should parse simple react class component with state', function () { (0, testUtils_1.check)('AppMenu', { AppMenu: { menu: { type: 'any' } } }); }); it('should parse simple react class component with picked properties', function () { (0, testUtils_1.check)('ColumnWithPick', { Column: { prop1: { type: 'string', required: false }, prop2: { type: 'number' }, propx: { type: 'number' } } }); }); it('should parse component with props with external type', function () { (0, testUtils_1.check)('ColumnWithPropsWithExternalType', { ColumnWithPropsWithExternalType: { prop1: { type: 'string', required: false }, prop2: { type: 'number' }, prop3: { type: 'MyExternalType' } } }); }); it('should parse HOCs', function () { (0, testUtils_1.check)('ColumnHigherOrderComponent', { ColumnExternalHigherOrderComponent: { prop1: { type: 'string' } }, ColumnHigherOrderComponent1: { prop1: { type: 'string' } }, ColumnHigherOrderComponent2: { prop1: { type: 'string' } }, RowExternalHigherOrderComponent: { prop1: { type: 'string' } }, RowHigherOrderComponent1: { prop1: { type: 'string' } }, RowHigherOrderComponent2: { prop1: { type: 'string' } } }); }); it('should parse component with inherited properties HtmlAttributes<any>', function () { (0, testUtils_1.check)('ColumnWithHtmlAttributes', { Column: { // tslint:disable:object-literal-sort-keys prop1: { type: 'string', required: false }, prop2: { type: 'number' }, // HtmlAttributes defaultChecked: { type: 'boolean', required: false, description: '' } // ... // tslint:enable:object-literal-sort-keys } }, false); }); it('should parse component without exported props interface', function () { (0, testUtils_1.check)('ColumnWithoutExportedProps', { Column: { prop1: { type: 'string', required: false }, prop2: { type: 'number' } } }); }); it('should parse functional component exported as const', function () { (0, testUtils_1.check)('ConstExport', { Row: { prop1: { type: 'string', required: false }, prop2: { type: 'number' } }, // TODO: this wasn't there before, i would guess that that's correct test: {} }, false); }); it('should parse react component with properties defined in external file', function () { (0, testUtils_1.check)('ExternalPropsComponent', { ExternalPropsComponent: { prop1: { type: 'string' } } }); }); it('should parse static sub components', function () { (0, testUtils_1.check)('StatelessStaticComponents', { StatelessStaticComponents: { myProp: { type: 'string' } }, 'StatelessStaticComponents.Label': { title: { type: 'string' } } }); }); it('should parse static sub components on class components', function () { (0, testUtils_1.check)('ColumnWithStaticComponents', { Column: { prop1: { type: 'string' } }, 'Column.Label': { title: { type: 'string' } }, 'Column.SubLabel': {} }); }); it('should parse react component with properties extended from an external .tsx file', function () { (0, testUtils_1.check)('ExtendsExternalPropsComponent', { ExtendsExternalPropsComponent: { prop1: { type: 'number', required: false, description: 'prop1' }, prop2: { type: 'string', required: false, description: 'prop2' } } }); }); it('should parse react component with properties defined as type', function () { (0, testUtils_1.check)('FlippableImage', { FlippableImage: { isFlippedX: { type: 'boolean', required: false }, isFlippedY: { type: 'boolean', required: false } } }, false); }); it('should parse react component with const definitions', function () { (0, testUtils_1.check)('InlineConst', { MyComponent: { foo: { type: 'any' } } }); }); it('should parse default interface export', function () { (0, testUtils_1.check)('ExportsDefaultInterface', { Component: { foo: { type: 'any' } } }); }); it('should parse react component that exports a prop type const', function () { (0, testUtils_1.check)('ExportsPropTypeShape', { ExportsPropTypes: { foo: { type: 'any' } } }); }); it('should parse react component that exports a prop type thats imported', function () { (0, testUtils_1.check)('ExportsPropTypeImport', { ExportsPropTypes: { foo: { type: 'any' } } }); }); // see issue #132 (https://github.com/styleguidist/react-docgen-typescript/issues/132) it('should determine the parent fileName relative to the project directory', function () { (0, testUtils_1.check)('ExportsPropTypeImport', { ExportsPropTypes: { foo: { parent: { fileName: 'react-docgen-typescript/src/__tests__/data/ExportsPropTypeImport.tsx', name: 'ExportsPropTypesProps' }, type: 'any' } } }, true); }); describe('component with default props', function () { var expectation = { ComponentWithDefaultProps: { sampleDefaultFromJSDoc: { defaultValue: 'hello', description: 'sample with default value', required: true, type: '"hello" | "goodbye"' }, sampleFalse: { defaultValue: false, required: false, type: 'boolean' }, sampleNull: { type: 'null', required: false, defaultValue: null }, sampleNumber: { type: 'number', required: false, defaultValue: -1 }, sampleObject: { defaultValue: "{ a: '1', b: 2, c: true, d: false, e: undefined, f: null, g: { a: '1' } }", required: false, type: '{ [key: string]: any; }' }, sampleString: { defaultValue: 'hello', required: false, type: 'string' }, sampleTrue: { type: 'boolean', required: false, defaultValue: true }, sampleUndefined: { defaultValue: 'undefined', required: false, type: 'any' } } }; it('should parse defined props', function () { (0, testUtils_1.check)('ComponentWithDefaultProps', expectation); }); it('should parse referenced props', function () { (0, testUtils_1.check)('ComponentWithReferencedDefaultProps', expectation); }); }); describe('component with @type jsdoc tag', function () { var expectation = { ComponentWithTypeJsDocTag: { sampleTypeFromJSDoc: { description: 'sample with custom type', required: true, type: 'string' } } }; it('should parse defined props', function () { (0, testUtils_1.check)('ComponentWithTypeJsDocTag', expectation); }); }); it('should parse react PureComponent', function () { (0, testUtils_1.check)('PureRow', { Row: { prop1: { type: 'string', required: false }, prop2: { type: 'number' } } }); }); it('should parse react PureComponent - regression test', function () { (0, testUtils_1.check)('Regression_v0_0_12', { Zoomable: { originX: { type: 'number' }, originY: { type: 'number' }, scaleFactor: { type: 'number' } } }, false); }); it('should parse react functional component', function () { (0, testUtils_1.check)('Row', { Row: { prop1: { type: 'string', required: false }, prop2: { type: 'number' } } }); }); it('should parse react stateless component', function () { (0, testUtils_1.check)('Stateless', { Stateless: { myProp: { type: 'string' } } }); }); it('should get name for default export', function () { (0, testUtils_1.check)('ForwardRefDefaultExport', { ForwardRefDefaultExport: { myProp: { type: 'string' } } }, false); }); it('should get name for default export 2', function () { (0, testUtils_1.check)('ForwardRefDefaultExportAtExport', { ForwardRefDefaultExport: { myProp: { type: 'string' } } }, false); }); it('should component where last line is a comment', function () { (0, testUtils_1.check)('ExportObject', { Baz: { baz: { description: '', type: 'string' } }, Bar: { foo: { description: '', type: 'string' } }, FooBar: { foobar: { description: '', type: 'string' } } }); }); it('should parse react stateless component with intersection props', function () { (0, testUtils_1.check)('StatelessIntersectionProps', { StatelessIntersectionProps: { moreProp: { type: 'number' }, myProp: { type: 'string' } } }); }); it('should parse react stateless component default props when declared as a normal function', function () { (0, testUtils_1.check)('FunctionDeclarationDefaultProps', { FunctionDeclarationDefaultProps: { id: { defaultValue: 1, description: '', required: false, type: 'number' } } }); }); it('should parse react stateless component default props when declared as a normal function inside forwardRef', function () { (0, testUtils_1.check)('ForwardRefDefaultValues', { ForwardRefDefaultValues: { myProp: { defaultValue: "I'm default", description: 'myProp description', type: 'string', required: false } } }, false, 'ForwardRefDefaultValues description'); }); it('should parse react stateless component with external intersection props', function () { (0, testUtils_1.check)('StatelessIntersectionExternalProps', { StatelessIntersectionExternalProps: { myProp: { type: 'string' }, prop1: { type: 'string', required: false } } }); }); it('should parse react stateless component with generic intersection props', function () { (0, testUtils_1.check)('StatelessIntersectionGenericProps', { StatelessIntersectionGenericProps: { myProp: { type: 'string' } } }); }); it('should parse react stateless component with intersection + union props', function () { (0, testUtils_1.check)('SimpleUnionIntersection', { SimpleUnionIntersection: { bar: { type: 'string', description: '' }, baz: { type: 'string', description: '' }, foo: { type: 'string', description: '' } } }); }); it('should parse react stateless component with intersection + union overlap props', function () { (0, testUtils_1.check)('SimpleDiscriminatedUnionIntersection', { SimpleDiscriminatedUnionIntersection: { bar: { type: '"one" | "other"', description: '' }, baz: { type: 'number', description: '' }, foo: { type: 'string', description: '' }, test: { type: 'number', description: '' } } }); }); it('should parse react stateless component with generic intersection + union overlap props - simple', function () { (0, testUtils_1.check)('SimpleGenericUnionIntersection', { SimpleGenericUnionIntersection: { as: { type: 'unknown', description: '' }, foo: { description: 'The foo prop should not repeat the description', required: false, type: '"red" | "blue"' }, gap: { description: 'The space between children\nYou cannot use gap when using a "space" justify property', required: false, type: 'number' }, hasWrap: { type: 'boolean', description: '', required: false } } }); }); it('should parse react stateless component with generic intersection + union overlap props', function () { (0, testUtils_1.check)('ComplexGenericUnionIntersection', { ComplexGenericUnionIntersection: { as: { type: 'ElementType<any>', required: false, description: 'Render the component as another component' }, align: { description: 'The flex "align" property', required: false, type: '"stretch" | "center" | "flex-start" | "flex-end"' }, justify: { description: "Use flex 'center' | 'flex-start' | 'flex-end' | 'stretch' with\na gap between each child.\nUse flex 'space-between' | 'space-around' | 'space-evenly' and\nflex will space the children.", required: false, type: '"stretch" | "center" | "flex-start" | "flex-end" | "space-between" | "space-around" | "space-evenly"' }, gap: { description: 'The space between children\nYou cannot use gap when using a "space" justify property', required: false, type: 'string | number' } } }); }); it('should parse react stateless component with generic intersection + union + omit overlap props', function () { (0, testUtils_1.check)('ComplexGenericUnionIntersectionWithOmit', { ComplexGenericUnionIntersectionWithOmit: { as: { type: 'ElementType<any>', required: false, description: 'Render the component as another component' }, align: { description: 'The flex "align" property', required: false, type: '"center" | "flex-start" | "flex-end" | "stretch"' }, justify: { description: "Use flex 'center' | 'flex-start' | 'flex-end' | 'stretch' with\na gap between each child.\nUse flex 'space-between' | 'space-around' | 'space-evenly' and\nflex will space the children.", required: false, type: '"center" | "flex-start" | "flex-end" | "stretch" | "space-between" | "space-around" | "space-evenly"' }, gap: { description: 'The space between children\nYou cannot use gap when using a "space" justify property', required: false, type: 'string | number' } } }); }); it('should parse react stateful component with intersection props', function () { (0, testUtils_1.check)('StatefulIntersectionProps', { StatefulIntersectionProps: { moreProp: { type: 'number' }, myProp: { type: 'string' } } }); }); it('should parse react stateful component with external intersection props', function () { (0, testUtils_1.check)('StatefulIntersectionExternalProps', { StatefulIntersectionExternalProps: { myProp: { type: 'string' }, prop1: { type: 'string', required: false } } }); }); it('should parse react stateful component (wrapped in HOC) with intersection props', function () { (0, testUtils_1.check)('HOCIntersectionProps', { HOCIntersectionProps: { injected: { type: 'boolean' }, myProp: { type: 'string' } } }); }); describe('stateless component with default props', function () { var expectation = { StatelessWithDefaultProps: { sampleDefaultFromJSDoc: { defaultValue: 'hello', description: 'sample with default value', required: true, type: '"hello" | "goodbye"' }, sampleEnum: { defaultValue: 'enumSample.HELLO', required: false, type: 'enumSample' }, sampleFalse: { defaultValue: false, required: false, type: 'boolean' }, sampleNull: { type: 'null', required: false, defaultValue: null }, sampleNumber: { type: 'number', required: false, defaultValue: -1 }, sampleObject: { defaultValue: "{ a: '1', b: 2, c: true, d: false, e: undefined, f: null, g: { a: '1' } }", required: false, type: '{ [key: string]: any; }' }, sampleString: { defaultValue: 'hello', required: false, type: 'string' }, sampleTrue: { type: 'boolean', required: false, defaultValue: true }, sampleUndefined: { defaultValue: undefined, required: false, type: 'any' } } }; it('should parse defined props', function () { (0, testUtils_1.check)('StatelessWithDefaultProps', expectation); }); it('should parse props with shorthands', function () { (0, testUtils_1.check)('StatelessShorthandDefaultProps', { StatelessShorthandDefaultProps: { onCallback: { defaultValue: null, description: 'onCallback description', required: false, type: '() => void' }, regularProp: { defaultValue: 'foo', description: 'regularProp description', required: false, type: 'string' }, shorthandProp: { defaultValue: 123, description: 'shorthandProp description', required: false, type: 'number' } } }); }); it('supports destructuring', function () { (0, testUtils_1.check)('StatelessWithDestructuredProps', expectation); }); it('supports destructuring for arrow functions', function () { (0, testUtils_1.check)('StatelessWithDestructuredPropsArrow', expectation); }); it('supports typescript 3.0 style defaulted props', function () { (0, testUtils_1.check)('StatelessWithDefaultPropsTypescript3', expectation); }); }); it('should parse components with unioned types', function () { (0, testUtils_1.check)('OnlyDefaultExportUnion', { OnlyDefaultExportUnion: { content: { description: 'The content', type: 'string' } } }); }); it('should parse components with unioned types when re-exported as named export', function () { (0, testUtils_1.check)('OnlyDefaultExportUnionAsExport', { OnlyDefaultExportUnion: { content: { description: 'The content', type: 'string' } } }, true, 'OnlyDefaultExportUnion description'); }); it('should parse jsdocs with the @default tag and no description', function () { (0, testUtils_1.check)('StatelessWithDefaultOnlyJsDoc', { StatelessWithDefaultOnlyJsDoc: { myProp: { defaultValue: 'hello', description: '', type: 'string' } } }); }); it('should parse functional component component defined as function', function () { (0, testUtils_1.check)('FunctionDeclaration', { Jumbotron: { prop1: { type: 'string', required: true } } }); }); it('should parse functional component component defined as const', function () { (0, testUtils_1.check)('FunctionalComponentAsConst', { Jumbotron: { prop1: { type: 'string', required: true } } }); }); it('should parse functional component defined as const with default value assignments in immediately destructured props', function () { (0, testUtils_1.check)('FunctionalComponentWithDesctructuredProps', { FunctionalComponentWithDesctructuredProps: { prop1: { type: 'Property1Type', required: false, defaultValue: 'hello' }, prop2: { type: '"goodbye" | "farewell"', required: false, defaultValue: 'goodbye' }, prop3: { type: 'number', required: false, defaultValue: 10 }, prop4: { type: 'string', required: false, defaultValue: 'this is a string' }, prop5: { type: 'boolean', required: false, defaultValue: true } } }); }); it('should parse functional component defined as const with default value (imported from a separate file) assignments in immediately destructured props', function () { (0, testUtils_1.check)('FunctionalComponentWithDesctructuredPropsAndImportedConstants', { FunctionalComponentWithDesctructuredPropsAndImportedConstants: { prop1: { type: 'Property1Type', required: false, defaultValue: 'hello' }, prop2: { type: '"goodbye" | "farewell"', required: false, defaultValue: 'goodbye' }, prop3: { type: 'number', required: false, defaultValue: 10 }, prop4: { type: 'string', required: false, defaultValue: 'this is a string' }, prop5: { type: 'boolean', required: false, defaultValue: true } } }); }); it('should parse functional component component defined as const', function () { (0, testUtils_1.check)('FunctionDeclarationVisibleName', { 'Awesome Jumbotron': { prop1: { type: 'string', required: true } } }); }); it('should parse React.SFC component defined as const', function () { (0, testUtils_1.check)('ReactSFCAsConst', { Jumbotron: { prop1: { type: 'string', required: true } } }); }); it('should parse functional component component defined as function as default export', function () { (0, testUtils_1.check)('FunctionDeclarationAsDefaultExport', { Jumbotron: { prop1: { type: 'string', required: true } } }); }); it('should parse functional component component thats been wrapped in React.memo', function () { (0, testUtils_1.check)('FunctionDeclarationAsDefaultExportWithMemo', { Jumbotron: { prop1: { type: 'string', required: true } } }); }); it('should parse JSDoc correctly', function () { (0, testUtils_1.check)('JSDocWithParam', { JSDocWithParam: { prop1: { type: 'string', required: true } } }, true, 'JSDocWithParamProps description\n\nNOTE: If a parent element of this control is `overflow: hidden` then the\nballoon may not show up.'); }); it('should parse functional component component defined as const as default export', function () { (0, testUtils_1.check)('FunctionalComponentAsConstAsDefaultExport', { // in this case the component name is taken from the file name FunctionalComponentAsConstAsDefaultExport: { prop1: { type: 'string', required: true } } }, true, 'Jumbotron description'); }); it('should parse React.SFC component defined as const as default export', function () { (0, testUtils_1.check)('ReactSFCAsConstAsDefaultExport', { // in this case the component name is taken from the file name ReactSFCAsConstAsDefaultExport: { prop1: { type: 'string', required: true } } }, true, 'Jumbotron description'); }); it('should parse functional component component defined as const as named export', function () { (0, testUtils_1.check)('FunctionalComponentAsConstAsNamedExport', { // in this case the component name is taken from the file name Jumbotron: { prop1: { type: 'string', required: true } } }, true, 'Jumbotron description'); }); it('should parse React.SFC component defined as const as named export', function () { (0, testUtils_1.check)('ReactSFCAsConstAsNamedExport', { // in this case the component name is taken from the file name Jumbotron: { prop1: { type: 'string', required: true } } }, true, 'Jumbotron description'); }); describe('displayName', function () { it('should be taken from stateless component `displayName` property (using named export)', function () { var parsed = (0, parser_1.parse)((0, testUtils_1.fixturePath)('StatelessDisplayName'))[0]; chai_1.assert.equal(parsed.displayName, 'StatelessDisplayName'); }); it('should be taken from stateful component `displayName` property (using named export)', function () { var parsed = (0, parser_1.parse)((0, testUtils_1.fixturePath)('StatefulDisplayName'))[0]; chai_1.assert.equal(parsed.displayName, 'StatefulDisplayName'); }); it('should be taken from stateless component `displayName` property (using default export)', function () { var parsed = (0, parser_1.parse)((0, testUtils_1.fixturePath)('StatelessDisplayNameDefaultExport'))[0]; chai_1.assert.equal(parsed.displayName, 'StatelessDisplayNameDefaultExport'); }); it("should be taken from stateless component `displayName` property (using default export) even if file name doesn't match", function () { var parsed = (0, parser_1.parse)((0, testUtils_1.fixturePath)('StatelessDisplayNameDefaultExportDifferentFilename'))[0]; chai_1.assert.equal(parsed.displayName, 'ThisNameIsNotTheSameAsThisFilename'); }); it('should be taken from stateful component `displayName` property (using default export)', function () { var parsed = (0, parser_1.parse)((0, testUtils_1.fixturePath)('StatefulDisplayNameDefaultExport'))[0]; chai_1.assert.equal(parsed.displayName, 'StatefulDisplayNameDefaultExport'); }); it('should be taken from named export when default export is an HOC', function () { var parsed = (0, parser_1.parse)((0, testUtils_1.fixturePath)('StatelessDisplayNameHOC'))[0]; chai_1.assert.equal(parsed.displayName, 'StatelessDisplayName'); }); it('should be taken from named export when default export is an HOC', function () { var parsed = (0, parser_1.parse)((0, testUtils_1.fixturePath)('StatefulDisplayNameHOC'))[0]; chai_1.assert.equal(parsed.displayName, 'StatefulDisplayName'); }); it('should be taken from stateless component folder name if file name is "index"', function () { var parsed = (0, parser_1.parse)((0, testUtils_1.fixturePath)('StatelessDisplayNameFolder/index'))[0]; chai_1.assert.equal(parsed.displayName, 'StatelessDisplayNameFolder'); }); it('should be taken from stateful component folder name if file name is "index"', function () { var parsed = (0, parser_1.parse)((0, testUtils_1.fixturePath)('StatefulDisplayNameFolder/index'))[0]; chai_1.assert.equal(parsed.displayName, 'StatefulDisplayNameFolder'); }); }); describe('Parser options', function () { describe('Property filtering', function () { describe('children', function () { it('should ignore property "children" if not explicitly documented', function () { (0, testUtils_1.check)('Column', { Column: { prop1: { type: 'string', required: false }, prop2: { type: 'number' }, prop3: { type: '() => void' }, prop4: { type: '"option1" | "option2" | "option3"' } } }, true); }); it('should not ignore any property that is documented explicitly', function () { (0, testUtils_1.check)('ColumnWithAnnotatedChildren', { Column: { children: { description: 'children description', required: false, type: 'ReactNode' }, prop1: { type: 'string', required: false }, prop2: { type: 'number' }, prop3: { type: '() => void' }, prop4: { type: '"option1" | "option2" | "option3"' } } }, true); }); }); describe('propsFilter method', function () { it('should apply filter function and filter components accordingly', function () { var propFilter = function (prop, component) { return prop.name !== 'prop1'; }; (0, testUtils_1.check)('Column', { Column: { prop2: { type: 'number' }, prop3: { type: '() => void' }, prop4: { type: '"option1" | "option2" | "option3"' } } }, true, undefined, { propFilter: propFilter }); }); it('should apply filter function and filter components accordingly', function () { var propFilter = function (prop, component) { if (component.name === 'Column') { return prop.name !== 'prop1'; } return true; }; (0, testUtils_1.check)('Column', { Column: { prop2: { type: 'number' }, prop3: { type: '() => void' }, prop4: { type: '"option1" | "option2" | "option3"' } } }, true, undefined, { propFilter: propFilter }); (0, testUtils_1.check)('AppMenu', { AppMenu: { menu: { type: 'any' } } }, true, undefined, { propFilter: propFilter }); }); it('should allow filtering by parent interface', function () { var propFilter = function (prop, component) { if (prop.parent == null) { return true; } return (prop.parent.fileName.indexOf('@types/react') < 0 && prop.parent.name !== 'HTMLAttributes'); }; (0, testUtils_1.check)('ColumnWithHtmlAttributes', { Column: { prop1: { type: 'string', required: false }, prop2: { type: 'number' } } }, true, undefined, { propFilter: propFilter }); }); }); it('should collect all `onClick prop` parent declarations', function (done) { chai_1.assert.doesNotThrow(function () { (0, parser_1.withDefaultConfig)({ propFilter: function (prop) { if (prop.name === 'onClick') { chai_1.assert.deepEqual(prop.declarations, [ { fileName: 'react-docgen-typescript/node_modules/@types/react/index.d.ts', name: 'DOMAttributes' }, { fileName: 'react-docgen-typescript/src/__tests__/data/ButtonWithOnClickComponent.tsx', name: 'TypeLiteral' } ]); done(); } return true; } }).parse((0, testUtils_1.fixturePath)('ButtonWithOnClickComponent')); }); }); it('should allow filtering by parent declarations', function () { var propFilter = function (prop) { if (prop.declarations !== undefined && prop.declarations.length > 0) { var hasPropAdditionalDescription = prop.declarations.find(function (declaration) { return !declaration.fileName.includes('@types/react'); }); return Boolean(hasPropAdditionalDescription); } return true; }; (0, testUtils_1.check)('ButtonWithOnClickComponent', { ButtonWithOnClickComponent: { onClick: { type: 'MouseEventHandler<HTMLButtonElement>', required: false, description: 'onClick event handler' } } }, true, '', { propFilter: propFilter }); }); describe('skipPropsWithName', function () { it('should skip a single property in skipPropsWithName', function () { var propFilter = { skipPropsWithName: 'prop1' }; (0, testUtils_1.check)('Column', { Column: { prop2: { type: 'number' }, prop3: { type: '() => void' }, prop4: { type: '"option1" | "option2" | "option3"' } } }, true, undefined, { propFilter: propFilter }); }); it('should skip multiple properties in skipPropsWithName', function () { var propFilter = { skipPropsWithName: ['prop1', 'prop2'] }; (0, testUtils_1.check)('Column', { Column: { prop3: { type: '() => void' }, prop4: { type: '"option1" | "option2" | "option3"' } } }, true, undefined, { propFilter: propFilter }); }); }); describe('skipPropsWithoutDoc', function () { it('should skip a properties without documentation', function () { var propFilter = { skipPropsWithoutDoc: false }; (0, testUtils_1.check)('ColumnWithUndocumentedProps', { Column: { prop1: { type: 'string', required: false }, prop2: { type: 'number' } } }, true, undefined, { propFilter: propFilter }); }); }); }); it('should defaultProps in variable', function () { (0, testUtils_1.check)('SeparateDefaultProps', { SeparateDefaultProps: { disabled: { description: '', required: false, defaultValue: false, type: 'boolean' }, id: { description: '', required: false, defaultValue: 123, type: 'number' } } }); }); it('should defaultProps accessed variable', function () { (0, testUtils_1.check)('SeparateDefaultPropsIndividual', { SeparateDefaultPropsIndividual: { disabled: { description: '', required: false, defaultValue: false, type: 'boolean' }, id: { description: '', required: false, defaultValue: 123, type: 'number' } } }); }); describe('Extracting literal values from enums', function () { it('extracts literal values from enum', function () { (0, testUtils_1.check)('ExtractLiteralValuesFromEnum', { ExtractLiteralValuesFromEnum: { sampleBoolean: { type: 'boolean' }, sampleEnum: { raw: 'sampleEnum', type: 'enum', value: [ { value: '"one"', description: '', fullComment: '', tags: {} }, { value: '"two"', description: '', fullComment: '', tags: {} }, { value: '"three"', description: '', fullComment: '', tags: {} } ] }, sampleString: { type: 'string' } } }, true, null, { shouldExtractLiteralValuesFromEnum: true }); }); it('Should infer types from constraint type (generic with extends)', function () { (0, testUtils_1.check)('GenericWithExtends', { GenericWithExtends: { sampleUnionProp: { raw: 'SampleUnion', type: 'enum', value: [ { value: '"value 1"' }, { value: '"value 2"' }, { value: '"value 3"' }, { value: '"value 4"' }, { value: '"value n"' } ] }, sampleEnumProp: { raw: 'SampleEnum', type: 'enum', value: [ { value: '0', description: '', fullComment: '', tags: {} }, { value: '1', description: '', fullComment: '', tags: {} }, { value: '"c"', description: '', fullComment: '', tags: {} } ] }, sampleUnionNonGeneric: { type: 'SampleUnionNonGeneric' }, sampleObjectProp: { type: 'SampleObject' }, sampleNumberProp: { type: 'number' }, sampleGenericArray: { type: 'number[]' }, sampleGenericObject: { type: '{ prop1: number; }' }, sampleInlineObject: { type: '{ propA: string; }' } } }, true, null, { shouldExtractLiteralValuesFromEnum: true }); }); }); describe('Extracting values from unions', function () { it('extracts all values from union', function () { (0, testUtils_1.check)('ExtractLiteralValuesFromUnion', { ExtractLiteralValuesFromUnion: { sampleComplexUnion: { raw: 'number | "string1" | "string2"', type: 'enum', value: [ { value: 'number' }, { value: '"string1"' }, { value: '"string2"' } ] } } }, false, null, { shouldExtractValuesFromUnion: true }); }); it('extracts numbers from a union', function () { (0, testUtils_1.check)('ExtractLiteralValuesFromUnion', { ExtractLiteralValuesFromUnion: { sampleNumberUnion: { raw: '1 | 2 | 3', type: 'enum', value: [{ value: '1' }, { value: '2' }, { value: '3' }] } } }, false, null, { shouldExtractValuesFromUnion: true }); }); it('extracts numbers and strings from a mixed union', function () { (0, testUtils_1.check)('ExtractLiteralValuesFromUnion', { ExtractLiteralValuesFromUnion: { sampleMixedUnion: { raw: '"string1" | "string2" | 1 | 2', type: 'enum', value: [ { value: '"strin