From cb87928dbf054460aa8806d9e8976c83701737ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sampo=20Kivist=C3=B6?= Date: Sun, 20 Oct 2024 17:18:23 +0300 Subject: [PATCH] Converted more tests to typescript, improved createElement typings and small perf improvement there --- ...{components.spec.js => components.spec.ts} | 49 +++++++++++----- ...omponents.spec.jsx => components.spec.tsx} | 0 ...spec.js => createElement.fragment.spec.ts} | 41 +++++++++++--- ...eElement.spec.js => createElement.spec.ts} | 14 +++-- .../{creation.spec.js => creation.spec.ts} | 0 packages/inferno-create-element/src/index.ts | 56 ++++++++++--------- 6 files changed, 106 insertions(+), 54 deletions(-) rename packages/inferno-create-element/__tests__/{components.spec.js => components.spec.ts} (96%) rename packages/inferno-create-element/__tests__/{components.spec.jsx => components.spec.tsx} (100%) rename packages/inferno-create-element/__tests__/{createElement.fragment.spec.js => createElement.fragment.spec.ts} (97%) rename packages/inferno-create-element/__tests__/{createElement.spec.js => createElement.spec.ts} (92%) rename packages/inferno-create-element/__tests__/{creation.spec.js => creation.spec.ts} (100%) diff --git a/packages/inferno-create-element/__tests__/components.spec.js b/packages/inferno-create-element/__tests__/components.spec.ts similarity index 96% rename from packages/inferno-create-element/__tests__/components.spec.js rename to packages/inferno-create-element/__tests__/components.spec.ts index c120d6bda..4f6381525 100644 --- a/packages/inferno-create-element/__tests__/components.spec.js +++ b/packages/inferno-create-element/__tests__/components.spec.ts @@ -19,7 +19,7 @@ describe('Components (non-JSX)', () => { }); if (typeof global !== 'undefined' && !global.usingJSDOM) { - class BasicComponent1 extends Component { + class BasicComponent1 extends Component<{name: string, title: string}> { render() { const template = (name, title) => createElement( @@ -147,7 +147,7 @@ describe('Components (non-JSX)', () => { ); }); - class BasicComponent1b extends Component { + class BasicComponent1b extends Component<{isChecked: boolean, title: string}> { render() { const template = (isChecked, title) => createElement( @@ -219,7 +219,7 @@ describe('Components (non-JSX)', () => { expect(container.querySelector('input').checked).toBe(false); }); - class BasicComponent1c extends Component { + class BasicComponent1c extends Component<{isEnabled: boolean, title: string, type: string}> { render() { const template = (isEnabled, title, type) => createElement( @@ -300,7 +300,7 @@ describe('Components (non-JSX)', () => { ); }); - class BasicComponent1d extends Component { + class BasicComponent1d extends Component<{isDisabled: boolean, title: string}> { render() { const template = (isDisabled, title) => createElement( @@ -401,7 +401,7 @@ describe('Components (non-JSX)', () => { expect(container.innerHTML).toBe(''); }); - class BasicComponent2 extends Component { + class BasicComponent2 extends Component<{name: string, title: string, children: any}> { render() { const template = (name, title, children) => createElement( @@ -485,7 +485,7 @@ describe('Components (non-JSX)', () => { } } - class BasicComponent3 extends Component { + class BasicComponent3 extends Component<{styles: any, title: string}> { render() { const template = (styles, title) => createElement( @@ -797,7 +797,13 @@ describe('Components (non-JSX)', () => { let componentWillMountCount; let template; - class ComponentLifecycleCheck extends Component { + interface CounterState { + counter: number; + } + + class ComponentLifecycleCheck extends Component { + state: CounterState; + constructor() { super(null); this.state = { @@ -841,7 +847,12 @@ describe('Components (non-JSX)', () => { let template; let update; - class ComponentLifecycleCheck extends Component { + interface CounterState { + counter: number; + } + + class ComponentLifecycleCheck extends Component { + state: CounterState; constructor() { super(null); this.state = { @@ -914,7 +925,7 @@ describe('Components (non-JSX)', () => { return createElement('h2', null, 'small'); }; - class ConditionalComponent extends Component { + class ConditionalComponent extends Component<{condition: boolean}> { render() { return createElement('div', null, [ this.props.condition ? tpl3625453295() : tpl4021787591(), @@ -956,7 +967,12 @@ describe('Components (non-JSX)', () => { return createElement(v0, null); }; - class ValueComponent extends Component { + interface ValueState { + organizations: {name: string, key: string|number}[] + } + class ValueComponent extends Component { + state: ValueState; + constructor(props) { super(props); this.state = { @@ -1053,7 +1069,7 @@ describe('Components (non-JSX)', () => { 'The title is abc', ); - render(template(BasicStatelessComponent1), container); + render(template(BasicStatelessComponent1, undefined), container); expect(container.firstChild.childNodes.length).toBe(1); expect(container.firstChild.firstChild.getAttribute('class')).toBe( 'basic', @@ -1066,7 +1082,7 @@ describe('Components (non-JSX)', () => { 'The title is ', ); - render(template(BasicStatelessComponent1), container); + render(template(BasicStatelessComponent1, undefined), container); expect(container.firstChild.childNodes.length).toBe(1); expect(container.firstChild.firstChild.getAttribute('class')).toBe( 'basic', @@ -1098,6 +1114,9 @@ describe('Components (non-JSX)', () => { }; class TEST extends Component { + // @ts-ignore it does not understand meaning of call(this) + private makeVisible: () => void; + constructor(props) { super(props); this.state = { @@ -1183,7 +1202,7 @@ describe('Components (non-JSX)', () => { render() { /* eslint new-cap:0 */ return BaseView( - this.toggle, + undefined, function () { return this.state.list.map(function (result) { return Looper(result); @@ -1267,7 +1286,7 @@ describe('Components (non-JSX)', () => { } } - class Message extends Component { + class Message extends Component<{text: string}> { render() { return createElement('div', null, [ this.props.text, @@ -1276,7 +1295,7 @@ describe('Components (non-JSX)', () => { } } - class MessageList extends Component { + class MessageList extends Component<{messages: {text: string}[]}> { getChildContext() { return { color: 'purple' }; } diff --git a/packages/inferno-create-element/__tests__/components.spec.jsx b/packages/inferno-create-element/__tests__/components.spec.tsx similarity index 100% rename from packages/inferno-create-element/__tests__/components.spec.jsx rename to packages/inferno-create-element/__tests__/components.spec.tsx diff --git a/packages/inferno-create-element/__tests__/createElement.fragment.spec.js b/packages/inferno-create-element/__tests__/createElement.fragment.spec.ts similarity index 97% rename from packages/inferno-create-element/__tests__/createElement.fragment.spec.js rename to packages/inferno-create-element/__tests__/createElement.fragment.spec.ts index 1a0c12e80..647b602d3 100644 --- a/packages/inferno-create-element/__tests__/createElement.fragment.spec.js +++ b/packages/inferno-create-element/__tests__/createElement.fragment.spec.ts @@ -5,6 +5,7 @@ import { Fragment, render, rerender, + VNode, } from 'inferno'; import { createElement } from 'inferno-create-element'; import { ChildFlags } from 'inferno-vnode-flags'; @@ -522,7 +523,7 @@ describe('CreateElement (non-JSX)', () => { let mountCounter = 0; let unmountCounter = 0; - const FoobarCom = class FoobarCom extends Component { + const FoobarCom = class FoobarCom extends Component<{node: HTMLDivElement}> { componentWillMount() { mountCounter++; } @@ -556,6 +557,7 @@ describe('CreateElement (non-JSX)', () => { first: 'first', mid: 'MID', last: createElement('div', null, 'Why?'), + changeOrder: false }), ), container, @@ -593,6 +595,7 @@ describe('CreateElement (non-JSX)', () => { first: 'first', mid: 'MID', last: createElement('div', null, 'Why?'), + changeOrder: false, }), ), container, @@ -1013,7 +1016,7 @@ describe('CreateElement (non-JSX)', () => { return createElement('div', null, 'Ok'); } - let content = [null]; + let content: (VNode|null)[] = [null]; render( createElement( @@ -1051,7 +1054,7 @@ describe('CreateElement (non-JSX)', () => { return createElement('div', null, 'Ok'); } - let content = []; + let content: (VNode|null)[] = []; render( createElement( @@ -1137,7 +1140,7 @@ describe('CreateElement (non-JSX)', () => { } }; - let nodes = []; + let nodes: (VNode|null)[] = []; render(createElement(Fragment, null, nodes), container); @@ -1308,10 +1311,20 @@ describe('CreateElement (non-JSX)', () => { it('Should mount fragment children to correct position Github #1412', () => { const f = (...xs) => createFragment(xs, 0); - class Articles extends Component { + interface ArticlesState { + articles: string[]; + sections: string[]; + } + + class Articles extends Component { + state: ArticlesState; + constructor() { super(); - this.state = { articles: ['id2', 'id3'], sections: ['id0', 'id1'] }; + this.state = { + articles: ['id2', 'id3'], + sections: ['id0', 'id1'] + }; } componentDidMount() { @@ -1371,7 +1384,13 @@ describe('CreateElement (non-JSX)', () => { it('Should re-mount fragment children to correct position when edge is component', () => { const f = (...xs) => createFragment(xs, 0); - class Articles extends Component { + interface ArticlesState { + articles: string[]; + sections: string[]; + } + + class Articles extends Component { + state: ArticlesState; constructor() { super(); this.state = { articles: ['id2', 'id3'], sections: ['id0', 'id1'] }; @@ -1452,7 +1471,13 @@ describe('CreateElement (non-JSX)', () => { it('Should append more fragment children to correct position when edge is component', () => { const f = (...xs) => createFragment(xs, 0); - class Articles extends Component { + interface ArticlesState { + articles: string[]; + sections: string[]; + } + + class Articles extends Component { + state: ArticlesState; constructor() { super(); this.state = { articles: ['id2', 'id3'], sections: ['id0', 'id1'] }; diff --git a/packages/inferno-create-element/__tests__/createElement.spec.js b/packages/inferno-create-element/__tests__/createElement.spec.ts similarity index 92% rename from packages/inferno-create-element/__tests__/createElement.spec.js rename to packages/inferno-create-element/__tests__/createElement.spec.ts index 00ba2897f..3bc7bc4bc 100644 --- a/packages/inferno-create-element/__tests__/createElement.spec.js +++ b/packages/inferno-create-element/__tests__/createElement.spec.ts @@ -1,5 +1,6 @@ -import { Component, createRef, forwardRef, Fragment, render } from 'inferno'; +import {Component, createRef, forwardRef, Fragment, Inferno, type RefObject, render} from 'inferno'; import { createElement } from 'inferno-create-element'; +import SFC = Inferno.SFC; describe('CreateElement (non-JSX)', () => { let container; @@ -146,10 +147,10 @@ describe('CreateElement (non-JSX)', () => { }); it('Should handle node with refs', (done) => { - let myRef = 'myRef'; + let myRef: any = 'myRef'; const app = () => { - const node = () => + const node: SFC = () => createElement('a', { ref: (c) => (myRef = c), }); @@ -199,7 +200,8 @@ describe('CreateElement (non-JSX)', () => { }); it('Should be possible to forward createRef', () => { - const FancyButton = forwardRef((props, ref) => + // TODO: Investigate how these refs should be typed + const FancyButton = forwardRef((props, ref: any) => createElement( 'button', { ref, className: 'FancyButton' }, @@ -210,6 +212,8 @@ describe('CreateElement (non-JSX)', () => { expect(FancyButton.render).toBeDefined(); class Hello extends Component { + btn: RefObject; + constructor(props) { super(props); @@ -222,7 +226,7 @@ describe('CreateElement (non-JSX)', () => { } render() { - return createElement(FancyButton, { ref: this.btn }, 'Click me!'); + return createElement(FancyButton, { ref: this.btn as any }, 'Click me!'); } } diff --git a/packages/inferno-create-element/__tests__/creation.spec.js b/packages/inferno-create-element/__tests__/creation.spec.ts similarity index 100% rename from packages/inferno-create-element/__tests__/creation.spec.js rename to packages/inferno-create-element/__tests__/creation.spec.ts diff --git a/packages/inferno-create-element/src/index.ts b/packages/inferno-create-element/src/index.ts index 34240f400..ac8deb423 100644 --- a/packages/inferno-create-element/src/index.ts +++ b/packages/inferno-create-element/src/index.ts @@ -1,4 +1,5 @@ import { + type Component, createComponentVNode, createFragment, createVNode, @@ -6,6 +7,7 @@ import { type Inferno, type Key, type Props, + type Refs, type VNode, } from 'inferno'; import { @@ -16,31 +18,21 @@ import { } from 'inferno-shared'; import { ChildFlags, VNodeFlags } from 'inferno-vnode-flags'; -const componentHooks = { - onComponentDidAppear: 1, - onComponentDidMount: 1, - onComponentDidUpdate: 1, - onComponentShouldUpdate: 1, - onComponentWillDisappear: 1, - onComponentWillMount: 1, - onComponentWillUnmount: 1, - onComponentWillUpdate: 1, -}; - -/** - * Creates virtual node - * @param {string|Function|Component} type Type of node - * @param {object=} props Optional props for virtual node - * @param {...{object}=} _children Optional children for virtual node - * @returns {VNode} new virtual node - */ export function createElement

( - type: string | Inferno.ComponentClass

| Inferno.StatelessComponent

, + type: + | string + | Inferno.ComponentClass

+ | Inferno.StatelessComponent

> + | typeof Component, props?: (P & Props

) | null, ..._children: any[] ): VNode; export function createElement

( - type: string | Inferno.ComponentClass

| Inferno.StatelessComponent

, + type: + | string + | Inferno.ComponentClass

+ | Inferno.StatelessComponent

> + | typeof Component, props?: (P & Props

) | null, _children?: any, ): VNode { @@ -109,13 +101,25 @@ export function createElement

( key = props.key; } else if (prop === 'ref') { ref = props.ref; - } else if ((componentHooks as any)[prop] === 1) { - if (!ref) { - ref = {}; - } - ref[prop] = props[prop]; } else { - newProps[prop] = props[prop]; + switch (prop) { + case 'onComponentDidAppear': + case 'onComponentDidMount': + case 'onComponentDidUpdate': + case 'onComponentShouldUpdate': + case 'onComponentWillDisappear': + case 'onComponentWillMount': + case 'onComponentWillUnmount': + case 'onComponentWillUpdate': + if (!ref) { + ref = {}; + } + ref[prop] = props[prop]; + break; + default: + newProps[prop] = props[prop]; + break; + } } } }