Skip to content

Commit

Permalink
fix: issue#540 (#549)
Browse files Browse the repository at this point in the history
  • Loading branch information
JohnIsOnTheRoad authored and janryWang committed Dec 26, 2019
1 parent 6e78905 commit 4ae1759
Show file tree
Hide file tree
Showing 9 changed files with 328 additions and 86 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
"start": "node ./scripts/docs.js start -i docs",
"sort-api": "node ./scripts/sort-api-table.js",
"test": "npm run lint && jest",
"test:sc": "jest --watch packages/react-shared-components/src/__tests__/*.spec.tsx",
"test:core": "jest --watch packages/core/src/__tests__/*.spec.ts",
"test:hook": "jest --watch packages/react/src/__tests__/*.spec.tsx",
"test:renderer": "jest --watch packages/react-schema-renderer/src/__tests__/*.spec.tsx",
Expand Down
83 changes: 5 additions & 78 deletions packages/react-shared-components/src/ArrayList.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import React, { createContext, useContext, Fragment, useMemo } from 'react'
import { isNum, isFn, toArr } from '@uform/shared'
import { IArrayList, IArrayListProps } from './types'

const ArrayContext = createContext<IArrayListProps>({})
import React, { Fragment } from 'react'
import { IArrayList } from './types'
import { ArrayContext } from './context'
import { useArrayList } from './hooks/useArrayList'
import { useComponent } from './hooks/useComponent'

export const ArrayList: IArrayList = props => {
return (
Expand All @@ -12,79 +12,6 @@ export const ArrayList: IArrayList = props => {
)
}

const useArrayList = (index: number = 0) => {
const {
value,
disabled,
editable,
minItems,
maxItems,
renders,
...props
} = useContext(ArrayContext)

const renderWith = (
name: string,
render: (node: any) => React.ReactElement,
wrapper: any
) => {
let children: any
if (renders && renders[name]) {
if (isFn(renders[name]) || renders[name].styledComponentId) {
children = renders[name](context.currentIndex)
} else {
children = render(renders[name])
}
} else {
children = render(renders[name])
}
if (isFn(wrapper)) {
return wrapper({ ...context, children }) || <Fragment />
}
return children || <Fragment />
}

const newValue = toArr(value)

const isEmpty = !newValue || (newValue && newValue.length <= 0)
const isDisable = disabled || editable === false
const allowMoveUp = newValue && newValue.length > 1 && !isDisable
const allowMoveDown = newValue && newValue.length > 1 && !isDisable
const allowRemove = isNum(minItems) ? newValue.length > minItems : !isDisable
const allowAddition = isNum(maxItems)
? newValue.length <= maxItems
: !isDisable

const context = {
...props,
currentIndex: index,
isEmpty,
isDisable,
allowRemove,
allowAddition,
allowMoveDown,
allowMoveUp,
renderWith
}

return context
}

const useComponent = (name: string) => {
const { components } = useContext(ArrayContext)
return useMemo(() => {
if (isFn(components[name]) || components[name].styledComponentId)
return components[name]
return (props: {}) => {
return React.isValidElement(components[name]) ? (
React.cloneElement(components[name], props)
) : (
<Fragment />
)
}
}, [])
}

const createButtonCls = (props: any = {}, hasText: any) => {
return {
className: `${hasText ? 'has-text' : ''} ${props.className || ''}`
Expand Down
11 changes: 3 additions & 8 deletions packages/react-shared-components/src/PreviewText.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,7 @@
import React, { useContext, createContext } from 'react'
import React, { useContext } from 'react'
import { isFn, isEqual } from '@uform/shared'
import { IPreviewTextProps } from './types'

export interface PreviewTextConfigProps {
previewPlaceholder?: string | ((props: IPreviewTextProps) => string)
}

const PreviewTextContext = createContext<PreviewTextConfigProps>({})
import { IPreviewTextProps, PreviewTextConfigProps } from './types'
import { PreviewTextContext } from './context'

export const PreviewText: React.FC<IPreviewTextProps> & {
ConfigProvider: React.Context<PreviewTextConfigProps>['Provider']
Expand Down
11 changes: 11 additions & 0 deletions packages/react-shared-components/src/__tests__/index.spec.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// import React from 'react'
// import { ArrayContext } from '../context'
// import { useArrayList } from '../hooks/useArrayList'
// import { IArrayList } from '../types'
// import { render } from '@testing-library/react'

describe('react shared component', () => {
test('basic', () => {

})
})
218 changes: 218 additions & 0 deletions packages/react-shared-components/src/__tests__/useArrayList.spec.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,218 @@
import React, { Fragment } from 'react'
import ReactDOMServer from 'react-dom/server'
import { ArrayContext } from '../context'
import { useArrayList } from '../hooks/useArrayList'
import { renderHook } from '@testing-library/react-hooks'

const ArrayWrapper = props => {
return (
<ArrayContext.Provider value={props}>
{props.children}
</ArrayContext.Provider>
)
}

describe('useArrayList', () => {
test('default index', () => {
const { result: defaultResult } = renderHook(() => useArrayList(), {
wrapper: props => <ArrayWrapper value={[]} {...props} />
})
expect(defaultResult.current.currentIndex).toEqual(0)

const { result } = renderHook(() => useArrayList(2), {
wrapper: props => <ArrayWrapper value={[]} {...props} />
})
expect(result.current.currentIndex).toEqual(2)
})

test('empty', () => {
const { result: emptyResult } = renderHook(() => useArrayList(), {
wrapper: props => <ArrayWrapper value={[]} {...props} />
})
expect(emptyResult.current.isEmpty).toEqual(true)

const { result: validResult } = renderHook(() => useArrayList(), {
wrapper: props => <ArrayWrapper value={[{}]} {...props} />
})
expect(validResult.current.isEmpty).toEqual(false)
})

test('disabled', () => {
const { result: basic } = renderHook(() => useArrayList(), {
wrapper: props => <ArrayWrapper {...props} />
})
expect(basic.current.isDisable).toEqual(false)

const { result: disabledResult } = renderHook(() => useArrayList(), {
wrapper: props => <ArrayWrapper disabled {...props} />
})
expect(disabledResult.current.isDisable).toEqual(true)

const { result: editableResult } = renderHook(() => useArrayList(), {
wrapper: props => <ArrayWrapper editable={false} {...props} />
})
expect(editableResult.current.isDisable).toEqual(true)
})

test('allow-*', () => {
const { result: emptyResult } = renderHook(() => useArrayList(), {
wrapper: props => <ArrayWrapper value={[]} {...props} />
})
expect(emptyResult.current.allowRemove).toEqual(true)
expect(emptyResult.current.allowAddition).toEqual(true)
expect(emptyResult.current.allowMoveDown).toEqual(false)
expect(emptyResult.current.allowMoveUp).toEqual(false)

const { result: oneResult } = renderHook(() => useArrayList(), {
wrapper: props => <ArrayWrapper value={[{}]} {...props} />
})
expect(oneResult.current.allowRemove).toEqual(true)
expect(oneResult.current.allowAddition).toEqual(true)
expect(oneResult.current.allowMoveDown).toEqual(false)
expect(oneResult.current.allowMoveUp).toEqual(false)

const { result: twoResult } = renderHook(() => useArrayList(), {
wrapper: props => <ArrayWrapper value={[{}, {}]} {...props} />
})
expect(twoResult.current.allowRemove).toEqual(true)
expect(twoResult.current.allowAddition).toEqual(true)
expect(twoResult.current.allowMoveDown).toEqual(true)
expect(twoResult.current.allowMoveUp).toEqual(true)
})

test('disabled and allow-*', () => {
const { result: disabledResult } = renderHook(() => useArrayList(), {
wrapper: props => <ArrayWrapper disabled value={[{}, {}]} {...props} />
})
expect(disabledResult.current.allowRemove).toEqual(false)
expect(disabledResult.current.allowAddition).toEqual(false)
expect(disabledResult.current.allowMoveDown).toEqual(false)
expect(disabledResult.current.allowMoveUp).toEqual(false)
})

test('render', () => {
// common renders
const { result: basicResult } = renderHook(() => useArrayList(), {
wrapper: props => (
<ArrayWrapper
renders={{
test: 123
}}
{...props}
/>
)
})

const result = basicResult.current.renderWith(
'test',
node => <Fragment>{node}</Fragment>,
null
)
expect(ReactDOMServer.renderToStaticMarkup(result)).toEqual('123')

// jsx renders
const { result: jsxResult } = renderHook(() => useArrayList(), {
wrapper: props => (
<ArrayWrapper
renders={{
test: <div>123</div>
}}
{...props}
/>
)
})

const resultJSX = jsxResult.current.renderWith(
'test',
node => <Fragment>{node}</Fragment>,
null
)
expect(ReactDOMServer.renderToStaticMarkup(resultJSX)).toEqual(
'<div>123</div>'
)

// function renders
const { result: funcResult } = renderHook(() => useArrayList(), {
wrapper: props => (
<ArrayWrapper
renders={{
test: idx => `currentIndex:${idx}`
}}
{...props}
/>
)
})

const resultFunc = funcResult.current.renderWith(
'test',
node => <Fragment>{node}</Fragment>,
null
)
expect(ReactDOMServer.renderToStaticMarkup(resultFunc)).toEqual(
`currentIndex:0`
)

// function wrapper
const { result: wrapperResult } = renderHook(() => useArrayList(), {
wrapper: props => (
<ArrayWrapper
renders={{
test: idx => `currentIndex:${idx}`
}}
{...props}
/>
)
})

const resultWrapper = wrapperResult.current.renderWith(
'test',
node => <Fragment>{node}</Fragment>,
props => {
const {
children,
isEmpty,
isDisable,
currentIndex,
allowAddition,
allowRemove,
allowMoveDown,
allowMoveUp
} = props
// context passed
expect(isEmpty).toEqual(true)
expect(isDisable).toEqual(false)
expect(currentIndex).toEqual(0)
expect(allowRemove).toEqual(true)
expect(allowAddition).toEqual(true)
expect(allowMoveDown).toEqual(false)
expect(allowMoveUp).toEqual(false)

return <div>{children}</div>
}
)
expect(ReactDOMServer.renderToStaticMarkup(resultWrapper)).toEqual(
`<div>currentIndex:0</div>`
)

// empty function wrapper
const { result: wrapperResult2 } = renderHook(() => useArrayList(), {
wrapper: props => (
<ArrayWrapper
renders={{
test: idx => `currentIndex:${idx}`
}}
{...props}
/>
)
})

const resultWrapper2 = wrapperResult2.current.renderWith(
'test',
node => <Fragment>{node}</Fragment>,
props => {
// do nothing...
}
)
expect(ReactDOMServer.renderToStaticMarkup(resultWrapper2)).toEqual('')
})
})
5 changes: 5 additions & 0 deletions packages/react-shared-components/src/context.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { createContext } from 'react'
import { IArrayListProps, PreviewTextConfigProps } from './types'

export const PreviewTextContext = createContext<PreviewTextConfigProps>({})
export const ArrayContext = createContext<IArrayListProps>({})
Loading

0 comments on commit 4ae1759

Please sign in to comment.