Skip to content

Commit

Permalink
test(typings): additional tests for typings and fixes (#1624)
Browse files Browse the repository at this point in the history
* test(typings): additional tests for typings and fixes

* test(typings): update option name
  • Loading branch information
layershifter authored and levithomason committed May 6, 2017
1 parent 40cef9a commit 7dc8aff
Show file tree
Hide file tree
Showing 16 changed files with 86 additions and 12 deletions.
2 changes: 2 additions & 0 deletions src/addons/Confirm/Confirm.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import * as React from 'react';
import { ModalProps } from '../../modules/Modal';

export interface ConfirmProps extends ModalProps {
[key: string]: any;

/** The cancel button text. */
cancelButton?: any;

Expand Down
6 changes: 3 additions & 3 deletions src/addons/Portal/Portal.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,12 +64,12 @@ class Portal extends Component {
/** The node where the portal should mount. */
mountNode: PropTypes.any,

/** Milliseconds to wait before closing on mouse leave */
mouseLeaveDelay: PropTypes.number,

/** Milliseconds to wait before opening on mouse over */
mouseEnterDelay: PropTypes.number,

/** Milliseconds to wait before closing on mouse leave */
mouseLeaveDelay: PropTypes.number,

/**
* Called when a close event happens
*
Expand Down
1 change: 1 addition & 0 deletions src/addons/Select/Select.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { default as DropdownItem } from '../../modules/Dropdown/DropdownItem';
import { default as DropdownMenu } from '../../modules/Dropdown/DropdownMenu';

export interface SelectProps extends DropdownProps {
[key: string]: any;
}

interface SelectComponent extends React.StatelessComponent<SelectProps> {
Expand Down
3 changes: 3 additions & 0 deletions src/collections/Form/FormCheckbox.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ export interface FormCheckboxProps extends FormFieldProps, CheckboxProps {

/** A FormField control prop. */
control?: any;

/** HTML input type, either checkbox or radio. */
type?: 'checkbox' | 'radio';
}

declare const FormCheckbox: React.StatelessComponent<FormCheckboxProps>;
Expand Down
3 changes: 3 additions & 0 deletions src/collections/Form/FormRadio.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ export interface FormRadioProps extends FormFieldProps, RadioProps {

/** A FormField control prop. */
control?: any;

/** HTML input type, either checkbox or radio. */
type?: 'checkbox' | 'radio';
}

declare const FormRadio: React.StatelessComponent<FormRadioProps>;
Expand Down
1 change: 1 addition & 0 deletions src/collections/Table/TableFooter.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import * as React from 'react';
import { TableHeaderProps } from './TableHeader';

export interface TableFooterProps extends TableHeaderProps {
[key: string]: any;
}

declare const TableFooter: React.StatelessComponent<TableFooterProps>;
Expand Down
2 changes: 2 additions & 0 deletions src/elements/List/ListIcon.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import { SemanticVERTICALALIGNMENTS } from '../..';
import { IconProps } from '../Icon';

export interface ListIconProps extends IconProps {
[key: string]: any;

/** Additional classes. */
className?: string;

Expand Down
35 changes: 35 additions & 0 deletions src/modules/Popup/Popup.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,38 @@ export interface PopupProps extends PortalProps {
/** Event triggering the popup. */
on?: 'hover' | 'click' | 'focus';

/**
* Called when a close event happens.
*
* @param {SyntheticEvent} event - React's original SyntheticEvent.
* @param {object} data - All props.
*/
onClose?: (event: React.MouseEvent<HTMLElement>, data: PopupProps) => void;

/**
* Called when the portal is mounted on the DOM.
*
* @param {null}
* @param {object} data - All props.
*/
onMount?: (nothing: null, data: PopupProps) => void;

/**
* Called when an open event happens.
*
* @param {SyntheticEvent} event - React's original SyntheticEvent.
* @param {object} data - All props.
*/
onOpen?: (event: React.MouseEvent<HTMLElement>, data: PopupProps) => void;

/**
* Called when the portal is unmounted from the DOM.
*
* @param {null}
* @param {object} data - All props.
*/
onUnmount?: (nothing: null, data: PopupProps) => void;

/** Position for the popover. */
position?: 'top left' | 'top right' |
'bottom right' | 'bottom left' |
Expand All @@ -52,6 +84,9 @@ export interface PopupProps extends PortalProps {
/** Custom Popup style. */
style?: Object;

/** Element to be rendered in-place where the popup is defined. */
trigger?: React.ReactNode;

/** Popup width. */
wide?: boolean | 'very';
}
Expand Down
2 changes: 1 addition & 1 deletion src/views/Statistic/StatisticGroup.d.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import * as React from 'react';

import { SemanticCOLORS, SemanticWIDTHS } from '../..';
import { StatisticSizeProp } from './Statictic';
import { StatisticSizeProp } from './Statistic';

export interface StatisticGroupProps {
[key: string]: any;
Expand Down
3 changes: 3 additions & 0 deletions test/specs/addons/Portal/Portal-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import PropTypes from 'prop-types'
import React from 'react'
import { unmountComponentAtNode } from 'react-dom'

import * as common from 'test/specs/commonTests'
import { domEvent, sandbox } from 'test/utils'
import Portal from 'src/addons/Portal/Portal'

Expand All @@ -25,6 +26,8 @@ describe('Portal', () => {
if (attachTo) document.body.removeChild(attachTo)
})

common.hasValidTypings(Portal)

it('propTypes.children should be required', () => {
Portal.propTypes.children.should.equal(PropTypes.node.isRequired)
})
Expand Down
4 changes: 3 additions & 1 deletion test/specs/collections/Form/FormFieldCheckbox-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ import Checkbox from 'src/modules/Checkbox/Checkbox'
import * as common from 'test/specs/commonTests'

describe('FormCheckbox', () => {
common.isConformant(FormCheckbox)
common.isConformant(FormCheckbox, {
ignoredTypingsProps: ['type'],
})

it('renders a FormField with a Checkbox control', () => {
shallow(<FormCheckbox />)
Expand Down
4 changes: 3 additions & 1 deletion test/specs/collections/Form/FormFieldRadio-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ import FormRadio from 'src/collections/Form/FormRadio'
import * as common from 'test/specs/commonTests'

describe('FormRadio', () => {
common.isConformant(FormRadio)
common.isConformant(FormRadio, {
ignoredTypingsProps: ['type'],
})

it('renders a FormField with a Radio control', () => {
shallow(<FormRadio />)
Expand Down
15 changes: 11 additions & 4 deletions test/specs/commonTests/hasValidTypings.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import componentInfo from './componentInfo'
import {
getNodes,
getInterfaces,
hasAnySignature,
requireTs,
} from './tsHelpers'

Expand All @@ -14,6 +15,7 @@ import {
* @param {Object} [extractedInfo={}]
* @param {Object} [extractedInfo._meta={}] The meta information about Component
* @param {Object} [options={}]
* @param {array} [options.ignoredTypingsProps=[]] Props that will be ignored in tests.
* @param {Object} [options.requiredProps={}] Props required to render Component without errors or warnings.
*/
export default (Component, extractedInfo, options = {}) => {
Expand All @@ -22,7 +24,7 @@ export default (Component, extractedInfo, options = {}) => {
filenameWithoutExt,
filePath,
} = extractedInfo || _.find(componentInfo, i => i.constructorName === Component.prototype.constructor.name)
const { requiredProps } = options
const { ignoredTypingsProps = [], requiredProps } = options

const tsFile = filenameWithoutExt + '.d.ts'
const tsContent = requireTs(path.join(path.dirname(filePath), tsFile))
Expand Down Expand Up @@ -50,18 +52,23 @@ export default (Component, extractedInfo, options = {}) => {
})

describe('props', () => {
const { props: interfaceProps } = interfaceObject
const { props } = interfaceObject

it('has any signature', () => {
hasAnySignature(tsNodes).should.to.equal(true)
})

it('are correctly defined', () => {
const componentPropTypes = _.get(Component, 'propTypes')
const componentProps = _.keys(componentPropTypes)
const interfaceProps = _.without(_.map(props, 'name'), ...ignoredTypingsProps)

componentProps.should.to.deep.equal(_.map(interfaceProps, 'name'))
componentProps.should.to.deep.equal(interfaceProps)
})

it('only necessary are required', () => {
const componentRequired = _.keys(requiredProps)
const interfaceRequired = _.filter(interfaceProps, ['required', true])
const interfaceRequired = _.filter(props, ['required', true])

componentRequired.should.to.deep.equal(_.map(interfaceRequired, 'name'))
})
Expand Down
1 change: 1 addition & 0 deletions test/specs/commonTests/isConformant.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { consoleUtil, sandbox, syntheticEvent } from 'test/utils'
* Assert Component conforms to guidelines that are applicable to all components.
* @param {React.Component|Function} Component A component that should conform.
* @param {Object} [options={}]
* @param {array} [options.ignoredTypingsProps=[]] Props that will be ignored in typings tests.
* @param {Object} [options.eventTargets={}] Map of events and the child component to target.
* @param {Object} [options.requiredProps={}] Props required to render Component without errors or warnings.
*/
Expand Down
15 changes: 13 additions & 2 deletions test/specs/commonTests/tsHelpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,12 @@ import {
SyntaxKind,
} from 'typescript'

const isAnyKeyword = ({ kind }) => kind === SyntaxKind.AnyKeyword
const isIndexSignature = ({ kind }) => kind === SyntaxKind.IndexSignature
const isInterface = ({ kind }) => kind === SyntaxKind.InterfaceDeclaration

const isExportModifier = ({ kind }) => kind === SyntaxKind.ExportKeyword

const isPropertySignature = ({ kind }) => kind === SyntaxKind.PropertySignature
const isStringKeyword = ({ kind }) => kind === SyntaxKind.StringKeyword

const getProps = members => {
const props = _.filter(members, isPropertySignature)
Expand Down Expand Up @@ -47,6 +48,16 @@ export const getInterfaces = nodes => {
}))
}

export const hasAnySignature = nodes => {
const signatures = _.filter(nodes, isIndexSignature)

return _.some(signatures, ({ parameters, type: rightType }) => {
const { name: { text }, type } = _.head(parameters)

return isAnyKeyword(rightType) && isStringKeyword(type) && text === 'key'
})
}

export const requireTs = tsPath => {
try {
return require(`!raw-loader!../../../src/${tsPath}`)
Expand Down
1 change: 1 addition & 0 deletions test/specs/modules/Popup/Popup-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ describe('Popup', () => {
})

common.hasSubComponents(Popup, [PopupHeader, PopupContent])
common.hasValidTypings(Popup)

// Heads up!
//
Expand Down

0 comments on commit 7dc8aff

Please sign in to comment.