From 9df4e896767d0e8001a1f77ec5111d5c74358cfc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martynas=20=C5=BDilinskas?= Date: Tue, 18 Apr 2017 21:18:04 +0300 Subject: [PATCH] react-dom package update with test-utils (#15868) * Create index.d.ts `react-addons-test-utils` package moved to `react-dom/test-utils. [Reference](https://facebook.github.io/react/docs/test-utils.html) Added missing function `isElement()`. Added jsdocs comments from react documentation. * Update index.d.ts * Added react-dom tests. * Fixed one function return. Added test-utils tests. * Remade structure. * Fixed header. * Remade from tsx -> ts. * Remade folder structure. * Moved to a single test file. * Updated header. * Added tslint.json. * Fixed index.d.ts * Removed trailing spaces. * no-redundant-modifiers index.d.ts fix. * Fixed tslint errors. * tslint extends dtslint/dt.json and fixed ReactTestUtils. * Fixed header version. * Removed consecutive blank line. * Removed JSDocs tags without description. * Fixed ReactDOM export as global. --- types/react-dom/index.d.ts | 106 +++++------ types/react-dom/react-dom-tests.ts | 144 +++++++++++++++ types/react-dom/server.d.ts | 7 - types/react-dom/server/index.d.ts | 24 +++ types/react-dom/test-utils/index.d.ts | 242 ++++++++++++++++++++++++++ types/react-dom/tsconfig.json | 4 +- types/react-dom/tslint.json | 3 + 7 files changed, 471 insertions(+), 59 deletions(-) create mode 100644 types/react-dom/react-dom-tests.ts delete mode 100644 types/react-dom/server.d.ts create mode 100644 types/react-dom/server/index.d.ts create mode 100644 types/react-dom/test-utils/index.d.ts create mode 100644 types/react-dom/tslint.json diff --git a/types/react-dom/index.d.ts b/types/react-dom/index.d.ts index 00520fc6ed..6adb9da76b 100644 --- a/types/react-dom/index.d.ts +++ b/types/react-dom/index.d.ts @@ -1,63 +1,67 @@ -// Type definitions for React (react-dom) 0.14 +// Type definitions for React (react-dom) 15.5 // Project: http://facebook.github.io/react/ -// Definitions by: Asana , AssureSign , Microsoft +// Definitions by: Asana , AssureSign , Microsoft , MartynasZilinskas // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped // TypeScript Version: 2.1 export as namespace ReactDOM; -export = ReactDOM; -import { ReactInstance, Component, ComponentState, - ReactElement, SFCElement, CElement, - DOMAttributes, DOMElement } from 'react'; +import { + ReactInstance, Component, ComponentState, + ReactElement, SFCElement, CElement, + DOMAttributes, DOMElement +} from 'react'; -declare namespace ReactDOM { - function findDOMNode(instance: ReactInstance): E; - function findDOMNode(instance: ReactInstance): Element; +export function findDOMNode(instance: ReactInstance): E; +export function findDOMNode(instance: ReactInstance): Element; - function render

, T extends Element>( - element: DOMElement, - container: Element | null, - callback?: (element: T) => any): T; - function render

( - element: SFCElement

, - container: Element | null, - callback?: () => any): void; - function render>( - element: CElement, - container: Element | null, - callback?: (component: T) => any): T; - function render

( - element: ReactElement

, - container: Element | null, - callback?: (component?: Component | Element) => any): Component | Element | void; +export function render

, T extends Element>( + element: DOMElement, + container: Element | null, + callback?: (element: T) => any +): T; +export function render

( + element: SFCElement

, + container: Element | null, + callback?: () => any +): void; +export function render>( + element: CElement, + container: Element | null, + callback?: (component: T) => any +): T; +export function render

( + element: ReactElement

, + container: Element | null, + callback?: (component?: Component | Element) => any +): Component | Element | void; +export function render

( + parentComponent: Component, + element: SFCElement

, + container: Element, + callback?: () => any +): void; - function unmountComponentAtNode(container: Element): boolean; +export function unmountComponentAtNode(container: Element): boolean; - var version: string; +export const version: string; - function unstable_batchedUpdates(callback: (a: A, b: B) => any, a: A, b: B): void; - function unstable_batchedUpdates(callback: (a: A) => any, a: A): void; - function unstable_batchedUpdates(callback: () => any): void; +export function unstable_batchedUpdates(callback: (a: A, b: B) => any, a: A, b: B): void; +export function unstable_batchedUpdates(callback: (a: A) => any, a: A): void; +export function unstable_batchedUpdates(callback: () => any): void; - function unstable_renderSubtreeIntoContainer

, T extends Element>( - parentComponent: Component, - element: DOMElement, - container: Element, - callback?: (element: T) => any): T; - function unstable_renderSubtreeIntoContainer>( - parentComponent: Component, - element: CElement, - container: Element, - callback?: (component: T) => any): T; - function render

( - parentComponent: Component, - element: SFCElement

, - container: Element, - callback?: () => any): void; - function unstable_renderSubtreeIntoContainer

( - parentComponent: Component, - element: ReactElement

, - container: Element, - callback?: (component?: Component | Element) => any): Component | Element | void; -} +export function unstable_renderSubtreeIntoContainer

, T extends Element>( + parentComponent: Component, + element: DOMElement, + container: Element, + callback?: (element: T) => any): T; +export function unstable_renderSubtreeIntoContainer>( + parentComponent: Component, + element: CElement, + container: Element, + callback?: (component: T) => any): T; +export function unstable_renderSubtreeIntoContainer

( + parentComponent: Component, + element: ReactElement

, + container: Element, + callback?: (component?: Component | Element) => any): Component | Element | void; diff --git a/types/react-dom/react-dom-tests.ts b/types/react-dom/react-dom-tests.ts new file mode 100644 index 0000000000..c38f307a4e --- /dev/null +++ b/types/react-dom/react-dom-tests.ts @@ -0,0 +1,144 @@ +import * as React from 'react'; +import * as ReactDOM from 'react-dom'; +import * as ReactDOMServer from 'react-dom/server'; +import * as ReactTestUtils from 'react-dom/test-utils'; + +declare function describe(desc: string, f: () => void): void; +declare function it(desc: string, f: () => void): void; + +class TestComponent extends React.Component<{}, {}> { } + +describe('ReactDOM', () => { + it('render', () => { + let rootElement = document.createElement('div'); + ReactDOM.render(React.createElement('div'), rootElement); + }); + + it('unmounts', () => { + let rootElement = document.createElement('div'); + ReactDOM.render(React.createElement('div'), rootElement); + ReactDOM.unmountComponentAtNode(rootElement); + }); + + it('find dom node', () => { + let rootElement = document.createElement('div'); + ReactDOM.render(React.createElement('div'), rootElement); + ReactDOM.findDOMNode(rootElement); + }); +}); + +describe('ReactDOMServer', () => { + it('renderToString', () => { + const content: string = ReactDOMServer.renderToString(React.createElement('div')); + }); + + it('renderToStaticMarkup', () => { + const content: string = ReactDOMServer.renderToStaticMarkup(React.createElement('div')); + }); +}); + +describe('React dom test utils', () => { + it('Simulate', () => { + const element = document.createElement('div'); + const dom = ReactDOM.render( + React.createElement('input', { type: 'text' }), + element + ) as Element; + const node = ReactDOM.findDOMNode(dom) as HTMLInputElement; + + node.value = 'giraffe'; + ReactTestUtils.Simulate.change(node); + ReactTestUtils.Simulate.keyDown(node, { key: "Enter", keyCode: 13, which: 13 }); + }); + + it('renderIntoDocument', () => { + const element = React.createElement('input', { type: 'text' }); + ReactTestUtils.renderIntoDocument(element); + }); + + it('mockComponent', () => { + ReactTestUtils.mockComponent(TestComponent, 'div'); + }); + + it('isElement', () => { + const element = React.createElement(TestComponent); + const isReactElement: boolean = ReactTestUtils.isElement(element); + }); + + it('isElementOfType', () => { + const element = React.createElement(TestComponent); + const isReactElement: boolean = ReactTestUtils.isElementOfType(element, TestComponent); + }); + + it('isDOMComponent', () => { + const element = React.createElement('div'); + const instance = ReactTestUtils.renderIntoDocument(element) as HTMLDivElement; + const isDOMElement: boolean = ReactTestUtils.isDOMComponent(instance); + }); + + it('isCompositeComponent', () => { + const element = React.createElement(TestComponent); + const instance = ReactTestUtils.renderIntoDocument(element) as TestComponent; + const isCompositeComponent: boolean = ReactTestUtils.isCompositeComponent(instance); + }); + + it('isCompositeComponentWithType', () => { + const element = React.createElement(TestComponent); + const instance = ReactTestUtils.renderIntoDocument(element) as TestComponent; + const isCompositeComponent: boolean = ReactTestUtils.isCompositeComponentWithType(instance, TestComponent); + }); + + it('findAllInRenderedTree', () => { + const component = ReactTestUtils.renderIntoDocument(React.createElement(TestComponent)); + ReactTestUtils.findAllInRenderedTree(component, (i: React.ReactInstance) => true); + }); + + it('scryRenderedDOMComponentsWithClass', () => { + const component = ReactTestUtils.renderIntoDocument(React.createElement(TestComponent)); + ReactTestUtils.scryRenderedDOMComponentsWithClass(component, 'class'); + }); + + it('findRenderedDOMComponentWithClass', () => { + const component = ReactTestUtils.renderIntoDocument(React.createElement(TestComponent)); + ReactTestUtils.findRenderedDOMComponentWithClass(component, 'class'); + }); + + it('scryRenderedDOMComponentsWithTag', () => { + const component = ReactTestUtils.renderIntoDocument(React.createElement(TestComponent)); + ReactTestUtils.scryRenderedDOMComponentsWithTag(component, 'div'); + }); + + it('findRenderedDOMComponentWithTag', () => { + const component = ReactTestUtils.renderIntoDocument(React.createElement(TestComponent)); + ReactTestUtils.findRenderedDOMComponentWithTag(component, 'tag'); + }); + + it('scryRenderedComponentsWithType', () => { + const component = ReactTestUtils.renderIntoDocument(React.createElement(TestComponent)); + ReactTestUtils.scryRenderedComponentsWithType(component, TestComponent); + }); + + it('findRenderedComponentWithType', () => { + const component = ReactTestUtils.renderIntoDocument(React.createElement(TestComponent)); + ReactTestUtils.findRenderedComponentWithType(component, TestComponent); + }); + + describe('Shallow Rendering', () => { + it('createRenderer', () => { + const component = React.createElement(TestComponent); + const shallowRenderer = ReactTestUtils.createRenderer(); + }); + + it('shallowRenderer.render', () => { + const component = React.createElement(TestComponent); + const shallowRenderer = ReactTestUtils.createRenderer(); + shallowRenderer.render(component); + }); + + it('shallowRenderer.getRenderOutput', () => { + const component = React.createElement(TestComponent); + const shallowRenderer = ReactTestUtils.createRenderer(); + shallowRenderer.getRenderOutput(); + }); + }); +}); diff --git a/types/react-dom/server.d.ts b/types/react-dom/server.d.ts deleted file mode 100644 index 3efae69e0c..0000000000 --- a/types/react-dom/server.d.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { ReactElement } from 'react'; - -export function renderToString(element: ReactElement): string; -export function renderToStaticMarkup(element: ReactElement): string; -export var version: string; - -export as namespace ReactDOMServer; \ No newline at end of file diff --git a/types/react-dom/server/index.d.ts b/types/react-dom/server/index.d.ts new file mode 100644 index 0000000000..7d45ecbeee --- /dev/null +++ b/types/react-dom/server/index.d.ts @@ -0,0 +1,24 @@ +import { ReactElement } from 'react'; + +/** + * Render a React element to its initial HTML. This should only be used on the server. + * React will return an HTML string. You can use this method to generate HTML on the server + * and send the markup down on the initial request for faster page loads and to allow search + * engines to crawl your pages for SEO purposes. + * + * If you call `ReactDOM.render()` on a node that already has this server-rendered markup, + * React will preserve it and only attach event handlers, allowing you + * to have a very performant first-load experience. + */ +export function renderToString(element: ReactElement): string; + +/** + * Similar to `renderToString`, except this doesn't create extra DOM attributes + * such as `data-reactid`, that React uses internally. This is useful if you want + * to use React as a simple static page generator, as stripping away the extra + * attributes can save lots of bytes. + */ +export function renderToStaticMarkup(element: ReactElement): string; +export const version: string; + +export as namespace ReactDOMServer; diff --git a/types/react-dom/test-utils/index.d.ts b/types/react-dom/test-utils/index.d.ts new file mode 100644 index 0000000000..3153b3dba7 --- /dev/null +++ b/types/react-dom/test-utils/index.d.ts @@ -0,0 +1,242 @@ +import { + AbstractView, Component, ComponentClass, + ReactElement, ReactInstance, ClassType, + DOMElement, SFCElement, CElement, + ReactHTMLElement, DOMAttributes, SFC +} from 'react'; + +import * as ReactTestUtils from "."; + +export interface OptionalEventProperties { + bubbles?: boolean; + cancelable?: boolean; + currentTarget?: EventTarget; + defaultPrevented?: boolean; + eventPhase?: number; + isTrusted?: boolean; + nativeEvent?: Event; + preventDefault?(): void; + stopPropagation?(): void; + target?: EventTarget; + timeStamp?: Date; + type?: string; +} + +export interface SyntheticEventData extends OptionalEventProperties { + altKey?: boolean; + button?: number; + buttons?: number; + clientX?: number; + clientY?: number; + changedTouches?: TouchList; + charCode?: boolean; + clipboardData?: DataTransfer; + ctrlKey?: boolean; + deltaMode?: number; + deltaX?: number; + deltaY?: number; + deltaZ?: number; + detail?: number; + getModifierState?(key: string): boolean; + key?: string; + keyCode?: number; + locale?: string; + location?: number; + metaKey?: boolean; + pageX?: number; + pageY?: number; + relatedTarget?: EventTarget; + repeat?: boolean; + screenX?: number; + screenY?: number; + shiftKey?: boolean; + targetTouches?: TouchList; + touches?: TouchList; + view?: AbstractView; + which?: number; +} + +export type EventSimulator = (element: Element | Component, eventData?: SyntheticEventData) => void; + +export interface MockedComponentClass { + new (): any; +} + +export interface ShallowRenderer { + /** + * After `shallowRenderer.render()` has been called, returns shallowly rendered output. + */ + getRenderOutput>(): E; + /** + * After `shallowRenderer.render()` has been called, returns shallowly rendered output. + */ + getRenderOutput(): ReactElement; + /** + * Similar to `ReactDOM.render` but it doesn't require DOM and only renders a single level deep. + */ + render(element: ReactElement, context?: any): void; + unmount(): void; +} + +/** + * Simulate an event dispatch on a DOM node with optional `eventData` event data. + * `Simulate` has a method for every event that React understands. + */ +export namespace Simulate { + const blur: EventSimulator; + const change: EventSimulator; + const click: EventSimulator; + const copy: EventSimulator; + const cut: EventSimulator; + const doubleClick: EventSimulator; + const drag: EventSimulator; + const dragEnd: EventSimulator; + const dragEnter: EventSimulator; + const dragExit: EventSimulator; + const dragLeave: EventSimulator; + const dragOver: EventSimulator; + const dragStart: EventSimulator; + const drop: EventSimulator; + const focus: EventSimulator; + const input: EventSimulator; + const keyDown: EventSimulator; + const keyPress: EventSimulator; + const keyUp: EventSimulator; + const mouseDown: EventSimulator; + const mouseEnter: EventSimulator; + const mouseLeave: EventSimulator; + const mouseMove: EventSimulator; + const mouseOut: EventSimulator; + const mouseOver: EventSimulator; + const mouseUp: EventSimulator; + const paste: EventSimulator; + const scroll: EventSimulator; + const submit: EventSimulator; + const touchCancel: EventSimulator; + const touchEnd: EventSimulator; + const touchMove: EventSimulator; + const touchStart: EventSimulator; + const wheel: EventSimulator; +} + +/** + * Render a React element into a detached DOM node in the document. __This function requires a DOM__. + */ +export function renderIntoDocument( + element: DOMElement): T; +export function renderIntoDocument( + element: SFCElement): void; +export function renderIntoDocument>( + element: CElement): T; +export function renderIntoDocument

( + element: ReactElement

): Component | Element | void; + +/** + * Pass a mocked component module to this method to augment it with useful methods that allow it to + * be used as a dummy React component. Instead of rendering as usual, the component will become + * a simple `

` (or other tag if `mockTagName` is provided) containing any provided children. + */ +export function mockComponent( + mocked: MockedComponentClass, mockTagName?: string): typeof ReactTestUtils; + +/** + * Returns `true` if `element` is any React element. + */ +export function isElement(element: any): boolean; + +/** + * Returns `true` if `element` is a React element whose type is of a React `componentClass`. + */ +export function isElementOfType( + element: ReactElement, type: string): element is ReactHTMLElement; +/** + * Returns `true` if `element` is a React element whose type is of a React `componentClass`. + */ +export function isElementOfType

, T extends Element>( + element: ReactElement, type: string): element is DOMElement; +/** + * Returns `true` if `element` is a React element whose type is of a React `componentClass`. + */ +export function isElementOfType

( + element: ReactElement, type: SFC

): element is SFCElement

; +/** + * Returns `true` if `element` is a React element whose type is of a React `componentClass`. + */ +export function isElementOfType, C extends ComponentClass

>( + element: ReactElement, type: ClassType): element is CElement; + +/** + * Returns `true` if `instance` is a DOM component (such as a `

` or ``). + */ +export function isDOMComponent(instance: ReactInstance): instance is Element; +/** + * Returns `true` if `instance` is a user-defined component, such as a class or a function. + */ +export function isCompositeComponent(instance: ReactInstance): instance is Component; +/** + * Returns `true` if `instance` is a component whose type is of a React `componentClass`. + */ +export function isCompositeComponentWithType, C extends ComponentClass>( + instance: ReactInstance, type: ClassType): boolean; + +/** + * Traverse all components in `tree` and accumulate all components where + * `test(component)` is `true`. This is not that useful on its own, but it's used + * as a primitive for other test utils. + */ +export function findAllInRenderedTree( + root: Component, + fn: (i: ReactInstance) => boolean): ReactInstance[]; + +/** + * Finds all DOM elements of components in the rendered tree that are + * DOM components with the class name matching `className`. + */ +export function scryRenderedDOMComponentsWithClass( + root: Component, + className: string): Element[]; +/** + * Like `scryRenderedDOMComponentsWithClass()` but expects there to be one result, + * and returns that one result, or throws exception if there is any other + * number of matches besides one. + */ +export function findRenderedDOMComponentWithClass( + root: Component, + className: string): Element; + +/** + * Finds all DOM elements of components in the rendered tree that are + * DOM components with the tag name matching `tagName`. + */ +export function scryRenderedDOMComponentsWithTag( + root: Component, + tagName: string): Element[]; +/** + * Like `scryRenderedDOMComponentsWithTag()` but expects there to be one result, + * and returns that one result, or throws exception if there is any other + * number of matches besides one. + */ +export function findRenderedDOMComponentWithTag( + root: Component, + tagName: string): Element; + +/** + * Finds all instances of components with type equal to `componentClass`. + */ +export function scryRenderedComponentsWithType, C extends ComponentClass<{}>>( + root: Component, + type: ClassType): T[]; + +/** + * Same as `scryRenderedComponentsWithType()` but expects there to be one result + * and returns that one result, or throws exception if there is any other + * number of matches besides one. + */ +export function findRenderedComponentWithType, C extends ComponentClass<{}>>( + root: Component, + type: ClassType): T; + +/** + * Call this in your tests to create a shallow renderer. + */ +export function createRenderer(): ShallowRenderer; diff --git a/types/react-dom/tsconfig.json b/types/react-dom/tsconfig.json index cb69f55d94..c93c6f8195 100644 --- a/types/react-dom/tsconfig.json +++ b/types/react-dom/tsconfig.json @@ -1,7 +1,9 @@ { "files": [ "index.d.ts", - "server.d.ts" + "react-dom-tests.ts", + "server/index.d.ts", + "test-utils/index.d.ts" ], "compilerOptions": { "module": "commonjs", diff --git a/types/react-dom/tslint.json b/types/react-dom/tslint.json new file mode 100644 index 0000000000..e60c15844f --- /dev/null +++ b/types/react-dom/tslint.json @@ -0,0 +1,3 @@ +{ + "extends": "dtslint/dt.json" +} \ No newline at end of file