-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Support memo() and other built-in components (#34)
* Support memo and more component types * Add entry * Add test
- Loading branch information
Showing
21 changed files
with
268 additions
and
15 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
26 changes: 26 additions & 0 deletions
26
packages/react-chain-of-responsibility/src/createChainOfResponsibility.fragment.test.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
/** @jest-environment jsdom */ | ||
/// <reference types="@types/jest" /> | ||
|
||
import { render } from '@testing-library/react'; | ||
import React, { Fragment, type ReactNode } from 'react'; | ||
|
||
import createChainOfResponsibility from './createChainOfResponsibility'; | ||
|
||
type Props = { children?: ReactNode }; | ||
|
||
test('middleware using <Fragment> should render', () => { | ||
// GIVEN: A middleware return a component that would render "Hello, World!". | ||
const { Provider, Proxy } = createChainOfResponsibility<undefined, Props>(); | ||
|
||
// WHEN: Render <Proxy>. | ||
const App = () => ( | ||
<Provider middleware={[() => () => () => Fragment]}> | ||
<Proxy>Hello, World!</Proxy> | ||
</Provider> | ||
); | ||
|
||
const result = render(<App />); | ||
|
||
// THEN: It should render "Hello, World!". | ||
expect(result.container).toHaveProperty('textContent', 'Hello, World!'); | ||
}); |
33 changes: 33 additions & 0 deletions
33
packages/react-chain-of-responsibility/src/createChainOfResponsibility.memo.test.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
/** @jest-environment jsdom */ | ||
/// <reference types="@types/jest" /> | ||
|
||
import { render } from '@testing-library/react'; | ||
import React, { Fragment, memo } from 'react'; | ||
|
||
import createChainOfResponsibility from './createChainOfResponsibility'; | ||
|
||
type Props = { children?: never; text: string }; | ||
|
||
const HelloWorldComponent = memo(({ text }: Props) => <Fragment>{text}</Fragment>); | ||
|
||
test('middleware should render', () => { | ||
// GIVEN: A middleware return a component that would render "Hello, World!". | ||
const { Provider, Proxy } = createChainOfResponsibility<undefined, Props>(); | ||
|
||
// WHEN: Render <Proxy>. | ||
const App = ({ text }: Props) => ( | ||
<Provider middleware={[() => () => () => HelloWorldComponent]}> | ||
<Proxy text={text} /> | ||
</Provider> | ||
); | ||
|
||
const result = render(<App text="Hello, World!" />); | ||
|
||
// THEN: It should render "Hello, World!". | ||
expect(result.container).toHaveProperty('textContent', 'Hello, World!'); | ||
|
||
result.rerender(<App text="Aloha!" />); | ||
|
||
// THEN: It should render "Aloha!". | ||
expect(result.container).toHaveProperty('textContent', 'Aloha!'); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
70 changes: 70 additions & 0 deletions
70
packages/react-chain-of-responsibility/src/isReactComponent.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
import { | ||
type ComponentClass, | ||
type ComponentType, | ||
type Consumer, | ||
type Fragment, | ||
type FunctionComponent, | ||
type Provider | ||
} from 'react'; | ||
|
||
function isConsumer( | ||
// eslint-disable-next-line @typescript-eslint/no-explicit-any | ||
component: any | ||
): component is Consumer<unknown> { | ||
return component?.$$typeof?.toString() === 'Symbol(react.context)'; | ||
} | ||
|
||
function isProvider( | ||
// eslint-disable-next-line @typescript-eslint/no-explicit-any | ||
component: any | ||
): component is Provider<unknown> { | ||
return component?.$$typeof?.toString() === 'Symbol(react.provider)'; | ||
} | ||
|
||
function isFragment( | ||
// eslint-disable-next-line @typescript-eslint/no-explicit-any | ||
component: any | ||
): component is typeof Fragment { | ||
return component?.toString() === 'Symbol(react.fragment)'; | ||
} | ||
|
||
function isFunctionComponent( | ||
// eslint-disable-next-line @typescript-eslint/no-explicit-any | ||
component: any | ||
): component is FunctionComponent { | ||
if (typeof component === 'function') { | ||
return true; | ||
} | ||
|
||
return isPureFunctionComponent(component); | ||
} | ||
|
||
function isPureFunctionComponent( | ||
// eslint-disable-next-line @typescript-eslint/no-explicit-any | ||
component: any | ||
): component is FunctionComponent { | ||
return component?.$$typeof?.toString() === 'Symbol(react.memo)' && isFunctionComponent(component.type); | ||
} | ||
|
||
function isComponentClass( | ||
// eslint-disable-next-line @typescript-eslint/no-explicit-any | ||
component: any | ||
): component is ComponentClass { | ||
return typeof component === 'object' && typeof component?.['render'] === 'function'; | ||
} | ||
|
||
// There are no definitive ways to check if an object is a React component or not. | ||
// We are checking if the object has a render function (classic component). | ||
// Note: "forwardRef()" returns plain object, not class instance. | ||
export default function isReactComponent( | ||
// eslint-disable-next-line @typescript-eslint/no-explicit-any | ||
component: any | ||
): component is ComponentType { | ||
return ( | ||
isFunctionComponent(component) || | ||
isComponentClass(component) || | ||
isFragment(component) || | ||
isConsumer(component) || | ||
isProvider(component) | ||
); | ||
} |
5 changes: 5 additions & 0 deletions
5
packages/react-chain-of-responsibility/src/isReactComponent/isReactComponent.array.test.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
import isReactComponent from '../isReactComponent'; | ||
|
||
test('array should return false', () => { | ||
expect(isReactComponent([])).toBe(false); | ||
}); |
5 changes: 5 additions & 0 deletions
5
...ages/react-chain-of-responsibility/src/isReactComponent/isReactComponent.boolean.test.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
import isReactComponent from '../isReactComponent'; | ||
|
||
test('boolean should return false', () => { | ||
expect(isReactComponent(true)).toBe(false); | ||
}); |
13 changes: 13 additions & 0 deletions
13
...act-chain-of-responsibility/src/isReactComponent/isReactComponent.componentClass.test.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import React, { Component } from 'react'; | ||
|
||
import isReactComponent from '../isReactComponent'; | ||
|
||
test('component class should return true', () => { | ||
class ComponentClass extends Component { | ||
render() { | ||
return <div>Hello, World!</div>; | ||
} | ||
} | ||
|
||
expect(isReactComponent(ComponentClass)).toBe(true); | ||
}); |
10 changes: 10 additions & 0 deletions
10
...ct-chain-of-responsibility/src/isReactComponent/isReactComponent.contextProvider.test.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
import { createContext } from 'react'; | ||
|
||
import isReactComponent from '../isReactComponent'; | ||
|
||
test('context provider should return true', () => { | ||
const Context = createContext(undefined); | ||
|
||
expect(isReactComponent(Context.Consumer)).toBe(true); | ||
expect(isReactComponent(Context.Provider)).toBe(true); | ||
}); |
5 changes: 5 additions & 0 deletions
5
packages/react-chain-of-responsibility/src/isReactComponent/isReactComponent.date.test.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
import isReactComponent from '../isReactComponent'; | ||
|
||
test('date should return false', () => { | ||
expect(isReactComponent(new Date())).toBe(false); | ||
}); |
5 changes: 5 additions & 0 deletions
5
packages/react-chain-of-responsibility/src/isReactComponent/isReactComponent.false.test.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
import isReactComponent from '../isReactComponent'; | ||
|
||
test('false should return false', () => { | ||
expect(isReactComponent(false)).toBe(false); | ||
}); |
7 changes: 7 additions & 0 deletions
7
...ges/react-chain-of-responsibility/src/isReactComponent/isReactComponent.fragment.test.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
import { Fragment } from 'react'; | ||
|
||
import isReactComponent from '../isReactComponent'; | ||
|
||
test('fragment should return true', () => { | ||
expect(isReactComponent(Fragment)).toBe(true); | ||
}); |
9 changes: 9 additions & 0 deletions
9
...esponsibility/src/isReactComponent/isReactComponent.functionComponent.forwardRef.test.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
import React, { forwardRef } from 'react'; | ||
|
||
import isReactComponent from '../isReactComponent'; | ||
|
||
test('function component with forwardRef should return true', () => { | ||
const FunctionComponent = forwardRef(() => <div>Hello, World!</div>); | ||
|
||
expect(isReactComponent(FunctionComponent)).toBe(true); | ||
}); |
11 changes: 11 additions & 0 deletions
11
...n-of-responsibility/src/isReactComponent/isReactComponent.functionComponent.memo.test.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
import React, { memo } from 'react'; | ||
|
||
import isReactComponent from '../isReactComponent'; | ||
|
||
test('function component should return true', () => { | ||
const FunctionComponent = memo(() => <div>Hello, World!</div>); | ||
|
||
FunctionComponent.displayName = 'FunctionComponent'; | ||
|
||
expect(isReactComponent(FunctionComponent)).toBe(true); | ||
}); |
9 changes: 9 additions & 0 deletions
9
...-chain-of-responsibility/src/isReactComponent/isReactComponent.functionComponent.test.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
import React from 'react'; | ||
|
||
import isReactComponent from '../isReactComponent'; | ||
|
||
test('function component should return true', () => { | ||
const FunctionComponent = () => <div>Hello, World!</div>; | ||
|
||
expect(isReactComponent(FunctionComponent)).toBe(true); | ||
}); |
5 changes: 5 additions & 0 deletions
5
packages/react-chain-of-responsibility/src/isReactComponent/isReactComponent.null.test.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
import isReactComponent from '../isReactComponent'; | ||
|
||
test('null should return false', () => { | ||
expect(isReactComponent(null)).toBe(false); | ||
}); |
5 changes: 5 additions & 0 deletions
5
packages/react-chain-of-responsibility/src/isReactComponent/isReactComponent.number.test.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
import isReactComponent from '../isReactComponent'; | ||
|
||
test('number should return false', () => { | ||
expect(isReactComponent(0)).toBe(false); | ||
}); |
5 changes: 5 additions & 0 deletions
5
packages/react-chain-of-responsibility/src/isReactComponent/isReactComponent.object.test.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
import isReactComponent from '../isReactComponent'; | ||
|
||
test('object should return false', () => { | ||
expect(isReactComponent({})).toBe(false); | ||
}); |
13 changes: 13 additions & 0 deletions
13
...chain-of-responsibility/src/isReactComponent/isReactComponent.pureComponentClass.test.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import React, { PureComponent } from 'react'; | ||
|
||
import isReactComponent from '../isReactComponent'; | ||
|
||
test('component class should return true', () => { | ||
class ComponentClass extends PureComponent { | ||
render() { | ||
return <div>Hello, World!</div>; | ||
} | ||
} | ||
|
||
expect(isReactComponent(ComponentClass)).toBe(true); | ||
}); |
5 changes: 5 additions & 0 deletions
5
...es/react-chain-of-responsibility/src/isReactComponent/isReactComponent.undefined.test.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
import isReactComponent from '../isReactComponent'; | ||
|
||
test('undefined should return false', () => { | ||
expect(isReactComponent(undefined)).toBe(false); | ||
}); |