From 7f4cdee62819f02b85cdf9cdc4279aeed0fe1ef4 Mon Sep 17 00:00:00 2001 From: Vincent Siao Date: Tue, 2 Dec 2014 18:11:15 -0800 Subject: [PATCH] ReactClass -> ComponentClass; add tests to react-tests.ts --- react/react-addons-tests.ts | 12 +- react/react-tests.ts | 198 +++++++++++++++------- react/react.d.ts | 317 ++++++++++++++++++------------------ 3 files changed, 308 insertions(+), 219 deletions(-) diff --git a/react/react-addons-tests.ts b/react/react-addons-tests.ts index d89c383bfe..1de8255f19 100644 --- a/react/react-addons-tests.ts +++ b/react/react-addons-tests.ts @@ -8,18 +8,26 @@ React.addons.TestUtils.Simulate.click(node); React.addons.TestUtils.Simulate.change(node); React.addons.TestUtils.Simulate.keyDown(node, {key: "Enter"}); +interface GreetingProps { + name: string; +} +interface GreetingState { + morning: boolean; +} +interface GreetingInstance extends React.ComponentInstance { +} var Greeting = React.createClass({displayName: 'Greeting', getInitialState: function() { return {morning: true}; }, render: function() { - var me = >this; + var me = this; return React.DOM.div(null, (me.state.morning ? "Hello" : "Goodbye "), me.props.name); } }); var root = React.addons.TestUtils.renderIntoDocument(React.createElement(Greeting, {name: "John"})); -var greeting = React.addons.TestUtils.findRenderedComponentWithType(root, Greeting); +var greeting = React.addons.TestUtils.findRenderedComponentWithType(root, Greeting); greeting.setState({ morning: false }); diff --git a/react/react-tests.ts b/react/react-tests.ts index 5d1743cbb5..fb0d6eebc3 100644 --- a/react/react-tests.ts +++ b/react/react-tests.ts @@ -1,64 +1,152 @@ /// import React = require("react"); +interface Props { + hello: string; + world?: string; + foo: number; + bar: boolean; +} + +interface State { + inputValue?: string; + seconds?: number; +} + +interface MyComponentInstance extends React.ComponentInstance { + reset(): void; +} + +var props: Props = { + hello: "world", + foo: 42, + bar: true +}; + +var container: Element; +var INPUT_REF: string = "input"; + +// +// Top-Level API +// -------------------------------------------------------------------------- + +var reactClass: React.ComponentClass = React.createClass({ + getDefaultProps: () => { + return { + hello: undefined, + world: "peace", + foo: undefined, + bar: undefined + }; + }, + getInitialState: () => { + return { + inputValue: "React.js", + seconds: 0 + }; + }, + reset: () => { + this.replaceState(this.getInitialState()); + }, + render: () => { + return React.DOM.div(null, + React.DOM.input({ + ref: INPUT_REF, + value: this.state.inputValue + })); + } +}); + +var reactElement: React.ReactElement = + React.createElement(reactClass, props); + +var reactFactory: React.Factory = + React.createFactory(reactClass); + +var reactInstance: React.Instance = + React.render(reactElement, container); + +var unmounted: boolean = React.unmountComponentAtNode(container); +var str: string = React.renderToString(reactElement); +var markup: string = React.renderToStaticMarkup(reactElement); +var notValid: boolean = React.isValidElement(props); // false +var isValid = React.isValidElement(reactElement); // true +React.initializeTouchEvents(true); + +// +// React Elements +// -------------------------------------------------------------------------- + +var type = reactElement.type; +var elementProps: Props = reactElement.props; +var key = reactElement.key; +var ref: string = reactElement.ref; +var factoryElement: React.ReactElement = reactFactory(elementProps); + +// +// React Components +// -------------------------------------------------------------------------- + +var displayName: string = reactClass.displayName; +var defaultProps: Props = reactClass.getDefaultProps(); +var propTypes: React.ValidationMap = reactClass.propTypes; + +// +// Component API +// -------------------------------------------------------------------------- + +var htmlElement: Element = reactInstance.getDOMNode(); +var divElement: HTMLDivElement = reactInstance.getDOMNode(); +var isMounted: boolean = reactInstance.isMounted(); +reactInstance.setProps(elementProps); +reactInstance.replaceProps(props); + +var componentInstance: React.ComponentInstance = + >reactInstance; +var initialState: State = componentInstance.state; +componentInstance.setState({ inputValue: "!!!" }); +componentInstance.replaceState({ inputValue: "???", seconds: 60 }); +componentInstance.forceUpdate(); + +var inputRef: React.Instance = + componentInstance.refs[INPUT_REF]; +var value: string = inputRef.getDOMNode().value; + +var myComponentInstance = componentInstance; +myComponentInstance.reset(); + +// +// PropTypes +// -------------------------------------------------------------------------- + var PropTypesSpecification: React.ComponentSpec = { propTypes: { - // You can declare that a prop is a specific JS primitive. By default, these - // are all optional. optionalArray: React.PropTypes.array, optionalBool: React.PropTypes.bool, optionalFunc: React.PropTypes.func, optionalNumber: React.PropTypes.number, optionalObject: React.PropTypes.object, optionalString: React.PropTypes.string, - - // Anything that can be rendered: numbers, strings, components or an array - // containing these types. optionalNode: React.PropTypes.node, - - // A React element optionalElement: React.PropTypes.element, - - // You can also declare that a prop is an instance of a class. This uses - // JS's instanceof operator. optionalMessage: React.PropTypes.instanceOf(Date), - - // You can ensure that your prop is limited to specific values by treating - // it as an enum. - optionalEnum: React.PropTypes.oneOf(['News', 'Photos']), - - // An object that could be one of many types + optionalEnum: React.PropTypes.oneOf(["News", "Photos"]), optionalUnion: React.PropTypes.oneOfType([ React.PropTypes.string, React.PropTypes.number, React.PropTypes.instanceOf(Date) ]), - - // An array of a certain type optionalArrayOf: React.PropTypes.arrayOf(React.PropTypes.number), - - // An object with property values of a certain type optionalObjectOf: React.PropTypes.objectOf(React.PropTypes.number), - - // An object taking on a particular shape optionalObjectWithShape: React.PropTypes.shape({ color: React.PropTypes.string, fontSize: React.PropTypes.number }), - - // You can chain any of the above with `isRequired` to make sure a warning - // is shown if the prop isn't provided. requiredFunc: React.PropTypes.func.isRequired, - - // A value of any data type requiredAny: React.PropTypes.any.isRequired, - - // You can also specify a custom validator. It should return an Error - // object if the validation fails. Don't `console.warn` or throw, as this - // won't work inside `oneOfType`. customProp: function(props: any, propName: string, componentName: string) { if (!/matchme/.test(props[propName])) { - return new Error('Validation failed!'); + return new Error("Validation failed!"); } return null; } @@ -68,47 +156,41 @@ var PropTypesSpecification: React.ComponentSpec = { } }; -React.createClass(PropTypesSpecification); +// +// Example from http://facebook.github.io/react/ +// -------------------------------------------------------------------------- -var mountNode: Element; - -interface HelloMessageProps { - name: string; +interface TimerState { + secondsElapsed: number; } - -var HelloMessage = React.createClass({ - displayName: 'HelloMessage', - render: function() { - return React.DOM.div(null, "Hello ", (>this).props.name); - } -}); - -var HelloMessageFactory = React.createFactory(HelloMessage) -React.render(HelloMessageFactory({ name: "John" }), mountNode) - -var Timer = React.createClass({displayName: 'Timer', - getInitialState: function() { - return {secondsElapsed: 0}; +interface TimerInstance extends React.ComponentInstance<{}, TimerState> { +} +var Timer = React.createClass({ + displayName: "Timer", + getInitialState: () => { + return { secondsElapsed: 0 }; }, - tick: function() { - var me = >this; + tick: () => { + var me = this; me.setState({ secondsElapsed: me.state.secondsElapsed + 1 }); }, - componentDidMount: function() { + componentDidMount: () => { this.interval = setInterval(this.tick, 1000); }, - componentWillUnmount: function() { + componentWillUnmount: () => { clearInterval(this.interval); }, - render: function() { + render: () => { + var me = this; return React.DOM.div( null, "Seconds Elapsed: ", - (>this).state.secondsElapsed + me.state.secondsElapsed ); } }); - +var mountNode: Element; React.render(React.createElement(Timer, null), mountNode); + diff --git a/react/react.d.ts b/react/react.d.ts index 8a8589203c..2d17c2223a 100644 --- a/react/react.d.ts +++ b/react/react.d.ts @@ -37,7 +37,7 @@ declare module React { // React Elements // ---------------------------------------------------------------------- - // type ReactType = ReactClass | string; + // type ReactType = ComponentClass | string; interface ReactElement

{ type: any; // ReactType @@ -54,22 +54,21 @@ declare module React { // React Nodes // ---------------------------------------------------------------------- - // Typescript 1.4 (Union types, aliases) // type ReactText = string | number; - // type ReactFragment = ReactNode[]; - // type ReactNode = ReactElement | ReactFragment | ReactText; + // type Fragment = ReactNode[]; + // type ReactNode = ReactElement | Fragment | ReactText; // // React Components // ---------------------------------------------------------------------- - interface ReactStatics

{ + interface ComponentStatics

{ displayName?: string; getDefaultProps?(): P; - propTypes?: React.ValidationMap

; + propTypes?: ValidationMap

; } - interface ReactClass

extends ReactStatics

{ + interface ComponentClass

extends ComponentStatics

{ // Deprecated in 0.12. See http://fb.me/react-legacyfactory // new(props: P): ReactElement

; // (props: P): ReactElement

; @@ -83,19 +82,19 @@ declare module React { (props?: P, ...children: any/*ReactNode*/[]): ReactElement

; } - interface ComponentFactory

extends Factory

{} interface HTMLFactory extends Factory {} interface SVGFactory extends Factory {} + interface ComponentFactory

extends Factory

{} // // Top-Level API // ---------------------------------------------------------------------- interface TopLevelAPI { - createClass

(spec: ComponentSpec): ReactClass

; + createClass

(spec: ComponentSpec): ComponentClass

; createElement

(type: any/*ReactType*/, props: P, ...children: any/*ReactNode*/[]): ReactElement

; createFactory

(type: any/*ReactType*/): Factory

; - render

(element: ReactElement

, container: Element, callback?: () => void): ReactInstance

; + render

(element: ReactElement

, container: Element, callback?: () => void): Instance

; unmountComponentAtNode(container: Element): boolean; renderToString(element: ReactElement): string; renderToStaticMarkup(element: ReactElement): string; @@ -107,7 +106,7 @@ declare module React { // Component API // ---------------------------------------------------------------------- - interface ReactInstance

{ + interface Instance

{ // Use this overload to cast the returned element to a more specific type. // Eg: var name = this.refs['name'].getDOMNode().value; getDOMNode(): TElement; @@ -119,13 +118,13 @@ declare module React { replaceProps(nextProps: P, callback?: () => void): void; } - interface ComponentInstance extends ReactInstance

{ + interface ComponentInstance extends Instance

{ state: S; setState(nextState: S, callback?: () => void): void; replaceState(nextState: S, callback?: () => void): void; forceUpdate(callback?: () => void): void; refs: { - [key: string]: ReactInstance

+ [key: string]: Instance

}; } @@ -133,7 +132,7 @@ declare module React { // Component Specs and Lifecycle // ---------------------------------------------------------------------- - interface Mixin extends ReactStatics

{ + interface Mixin extends ComponentStatics

{ mixins?: Mixin; statics?: { [key: string]: any; @@ -407,7 +406,7 @@ declare module React { itemType?: string; // React-specific Attributes - dangerouslySetInnerHTML: { + dangerouslySetInnerHTML?: { __html: string }; } @@ -464,136 +463,136 @@ declare module React { interface ReactDOM { // HTML - a: React.HTMLFactory; - abbr: React.HTMLFactory; - address: React.HTMLFactory; - area: React.HTMLFactory; - article: React.HTMLFactory; - aside: React.HTMLFactory; - audio: React.HTMLFactory; - b: React.HTMLFactory; - base: React.HTMLFactory; - bdi: React.HTMLFactory; - bdo: React.HTMLFactory; - big: React.HTMLFactory; - blockquote: React.HTMLFactory; - body: React.HTMLFactory; - br: React.HTMLFactory; - button: React.HTMLFactory; - canvas: React.HTMLFactory; - caption: React.HTMLFactory; - cite: React.HTMLFactory; - code: React.HTMLFactory; - col: React.HTMLFactory; - colgroup: React.HTMLFactory; - data: React.HTMLFactory; - datalist: React.HTMLFactory; - dd: React.HTMLFactory; - del: React.HTMLFactory; - details: React.HTMLFactory; - dfn: React.HTMLFactory; - dialog: React.HTMLFactory; - div: React.HTMLFactory; - dl: React.HTMLFactory; - dt: React.HTMLFactory; - em: React.HTMLFactory; - embed: React.HTMLFactory; - fieldset: React.HTMLFactory; - figcaption: React.HTMLFactory; - figure: React.HTMLFactory; - footer: React.HTMLFactory; - form: React.HTMLFactory; - h1: React.HTMLFactory; - h2: React.HTMLFactory; - h3: React.HTMLFactory; - h4: React.HTMLFactory; - h5: React.HTMLFactory; - h6: React.HTMLFactory; - head: React.HTMLFactory; - header: React.HTMLFactory; - hr: React.HTMLFactory; - html: React.HTMLFactory; - i: React.HTMLFactory; - iframe: React.HTMLFactory; - img: React.HTMLFactory; - input: React.HTMLFactory; - ins: React.HTMLFactory; - kbd: React.HTMLFactory; - keygen: React.HTMLFactory; - label: React.HTMLFactory; - legend: React.HTMLFactory; - li: React.HTMLFactory; - link: React.HTMLFactory; - main: React.HTMLFactory; - map: React.HTMLFactory; - mark: React.HTMLFactory; - menu: React.HTMLFactory; - menuitem: React.HTMLFactory; - meta: React.HTMLFactory; - meter: React.HTMLFactory; - nav: React.HTMLFactory; - noscript: React.HTMLFactory; - object: React.HTMLFactory; - ol: React.HTMLFactory; - optgroup: React.HTMLFactory; - option: React.HTMLFactory; - output: React.HTMLFactory; - p: React.HTMLFactory; - param: React.HTMLFactory; - pre: React.HTMLFactory; - progress: React.HTMLFactory; - q: React.HTMLFactory; - rp: React.HTMLFactory; - rt: React.HTMLFactory; - ruby: React.HTMLFactory; - s: React.HTMLFactory; - samp: React.HTMLFactory; - script: React.HTMLFactory; - section: React.HTMLFactory; - select: React.HTMLFactory; - small: React.HTMLFactory; - source: React.HTMLFactory; - span: React.HTMLFactory; - strong: React.HTMLFactory; - style: React.HTMLFactory; - sub: React.HTMLFactory; - summary: React.HTMLFactory; - sup: React.HTMLFactory; - table: React.HTMLFactory; - tbody: React.HTMLFactory; - td: React.HTMLFactory; - textarea: React.HTMLFactory; - tfoot: React.HTMLFactory; - th: React.HTMLFactory; - thead: React.HTMLFactory; - time: React.HTMLFactory; - title: React.HTMLFactory; - tr: React.HTMLFactory; - track: React.HTMLFactory; - u: React.HTMLFactory; - ul: React.HTMLFactory; - "var": React.HTMLFactory; - video: React.HTMLFactory; - wbr: React.HTMLFactory; + a: HTMLFactory; + abbr: HTMLFactory; + address: HTMLFactory; + area: HTMLFactory; + article: HTMLFactory; + aside: HTMLFactory; + audio: HTMLFactory; + b: HTMLFactory; + base: HTMLFactory; + bdi: HTMLFactory; + bdo: HTMLFactory; + big: HTMLFactory; + blockquote: HTMLFactory; + body: HTMLFactory; + br: HTMLFactory; + button: HTMLFactory; + canvas: HTMLFactory; + caption: HTMLFactory; + cite: HTMLFactory; + code: HTMLFactory; + col: HTMLFactory; + colgroup: HTMLFactory; + data: HTMLFactory; + datalist: HTMLFactory; + dd: HTMLFactory; + del: HTMLFactory; + details: HTMLFactory; + dfn: HTMLFactory; + dialog: HTMLFactory; + div: HTMLFactory; + dl: HTMLFactory; + dt: HTMLFactory; + em: HTMLFactory; + embed: HTMLFactory; + fieldset: HTMLFactory; + figcaption: HTMLFactory; + figure: HTMLFactory; + footer: HTMLFactory; + form: HTMLFactory; + h1: HTMLFactory; + h2: HTMLFactory; + h3: HTMLFactory; + h4: HTMLFactory; + h5: HTMLFactory; + h6: HTMLFactory; + head: HTMLFactory; + header: HTMLFactory; + hr: HTMLFactory; + html: HTMLFactory; + i: HTMLFactory; + iframe: HTMLFactory; + img: HTMLFactory; + input: HTMLFactory; + ins: HTMLFactory; + kbd: HTMLFactory; + keygen: HTMLFactory; + label: HTMLFactory; + legend: HTMLFactory; + li: HTMLFactory; + link: HTMLFactory; + main: HTMLFactory; + map: HTMLFactory; + mark: HTMLFactory; + menu: HTMLFactory; + menuitem: HTMLFactory; + meta: HTMLFactory; + meter: HTMLFactory; + nav: HTMLFactory; + noscript: HTMLFactory; + object: HTMLFactory; + ol: HTMLFactory; + optgroup: HTMLFactory; + option: HTMLFactory; + output: HTMLFactory; + p: HTMLFactory; + param: HTMLFactory; + pre: HTMLFactory; + progress: HTMLFactory; + q: HTMLFactory; + rp: HTMLFactory; + rt: HTMLFactory; + ruby: HTMLFactory; + s: HTMLFactory; + samp: HTMLFactory; + script: HTMLFactory; + section: HTMLFactory; + select: HTMLFactory; + small: HTMLFactory; + source: HTMLFactory; + span: HTMLFactory; + strong: HTMLFactory; + style: HTMLFactory; + sub: HTMLFactory; + summary: HTMLFactory; + sup: HTMLFactory; + table: HTMLFactory; + tbody: HTMLFactory; + td: HTMLFactory; + textarea: HTMLFactory; + tfoot: HTMLFactory; + th: HTMLFactory; + thead: HTMLFactory; + time: HTMLFactory; + title: HTMLFactory; + tr: HTMLFactory; + track: HTMLFactory; + u: HTMLFactory; + ul: HTMLFactory; + "var": HTMLFactory; + video: HTMLFactory; + wbr: HTMLFactory; // SVG - circle: React.SVGFactory; - defs: React.SVGFactory; - ellipse: React.SVGFactory; - g: React.SVGFactory; - line: React.SVGFactory; - linearGradient: React.SVGFactory; - mask: React.SVGFactory; - path: React.SVGFactory; - pattern: React.SVGFactory; - polygon: React.SVGFactory; - polyline: React.SVGFactory; - radialGradient: React.SVGFactory; - rect: React.SVGFactory; - stop: React.SVGFactory; - svg: React.SVGFactory; - text: React.SVGFactory; - tspan: React.SVGFactory; + circle: SVGFactory; + defs: SVGFactory; + ellipse: SVGFactory; + g: SVGFactory; + line: SVGFactory; + linearGradient: SVGFactory; + mask: SVGFactory; + path: SVGFactory; + pattern: SVGFactory; + polygon: SVGFactory; + polyline: SVGFactory; + radialGradient: SVGFactory; + rect: SVGFactory; + stop: SVGFactory; + svg: SVGFactory; + text: SVGFactory; + tspan: SVGFactory; } // @@ -654,11 +653,11 @@ declare module React { interface TransitionGroupProps { component?: any; // ReactType - childFactory?: (child: React.ReactElement) => React.ReactElement; + childFactory?: (child: ReactElement) => ReactElement; } - interface CSSTransitionGroup extends React.ReactClass {} - interface TransitionGroup extends React.ReactClass {} + interface CSSTransitionGroup extends ComponentClass {} + interface TransitionGroup extends ComponentClass {} // // React.addons (Mixins) @@ -669,11 +668,11 @@ declare module React { requestChange(newValue: T): void; } - interface LinkedStateMixin extends React.Mixin { + interface LinkedStateMixin extends Mixin { linkState(key: string): ReactLink; } - interface PureRenderMixin extends React.Mixin { + interface PureRenderMixin extends Mixin { } // @@ -738,28 +737,28 @@ declare module React { }; } - // Alias for ReactTestUtils - interface Instance

extends React.ReactInstance

{} - interface ReactTestUtils { Simulate: Simulate; - renderIntoDocument

(element: React.ReactElement

): Instance

; + renderIntoDocument

(element: ReactElement

): Instance

; mockComponent(mocked: MockedComponent, mockTagName?: string): ReactTestUtils; - isElementOfType(element: React.ReactElement, type: any/*ReactType*/): boolean; + + isElementOfType(element: ReactElement, type: any/*ReactType*/): boolean; isDOMComponent(instance: Instance): boolean; isCompositeComponent(instance: Instance): boolean; - isCompositeComponentWithType(instance: Instance, type: React.ReactClass): boolean; + isCompositeComponentWithType(instance: Instance, type: ComponentClass): boolean; isTextComponent(instance: Instance): boolean; + findAllInRenderedTree(tree: Instance, fn: (i: Instance) => boolean): Instance; + scryRenderedDOMComponentsWithClass(tree: Instance, className: string): Instance[]; findRenderedDOMComponentWithClass(tree: Instance, className: string): Instance; + scryRenderedDOMComponentsWithTag(tree: Instance, tagName: string): Instance[]; findRenderedDOMComponentWithTag(tree: Instance, tagName: string): Instance; - scryRenderedComponentsWithType( - tree: Instance, type: React.ReactClass

): React.ComponentInstance[]; - findRenderedComponentWithType( - tree: Instance, type: React.ReactClass

): React.ComponentInstance; + + scryRenderedComponentsWithType

(tree: Instance, type: ComponentClass

): Instance

[]; + findRenderedComponentWithType

(tree: Instance, type: ComponentClass

): Instance

; } interface SyntheticEventData { @@ -863,7 +862,7 @@ declare module React { batchedUpdates(callback: () => void): void; classSet(cx: { [key: string]: boolean }): string; - cloneWithProps

(element: React.ReactElement

, props: P): React.ReactElement

; + cloneWithProps

(element: ReactElement

, props: P): ReactElement

; update(value: any[], spec: UpdateArraySpec): any[]; update(value: {}, spec: UpdateSpec): any;