Skip to content

Commit

Permalink
feat #81 - Address PR Comments, rebase dev
Browse files Browse the repository at this point in the history
  • Loading branch information
sam-dassana committed Sep 18, 2020
1 parent af50432 commit f2b8bc7
Show file tree
Hide file tree
Showing 9 changed files with 117 additions and 44 deletions.
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,10 @@
},
"jest": {
"coveragePathIgnorePatterns": [
".stories.tsx"
".stories.tsx",
"fixtures/*",
"types.ts",
"components/index.ts"
]
},
"browserslist": {
Expand Down
1 change: 1 addition & 0 deletions src/__snapshots__/storybook.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -1080,6 +1080,7 @@ exports[`Storyshots Tree Default 1`] = `
"onLeaveStart": [Function],
}
}
onCheck={[Function]}
selectable={false}
showIcon={false}
treeData={
Expand Down
2 changes: 2 additions & 0 deletions src/components/Tree/Tree.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import { action } from '@storybook/addon-actions'
import React from 'react'
import treeData0 from './fixtures/0_sample_data'
import { Meta, Story } from '@storybook/react/types-6-0'
import Tree, { TreeProps } from './index'

export default {
argTypes: {
onCheck: { defaultValue: action('onCheck') },
treeData: {
table: {
type: {
Expand Down
35 changes: 16 additions & 19 deletions src/components/Tree/TreeSkeleton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,21 @@ import React, { FC, Fragment, Key } from 'react'

const useStyles = createUseStyles({
skeletonLabel: {
marginLeft: '5px'
marginLeft: 5
},
skeletonTreeNode: {
alignItems: 'center',
display: 'flex',
marginLeft: props =>
props.nestLevel ? `${props.nestLevel * 20}px` : 0,
paddingBottom: '10px'
marginLeft: props => (props.nestLevel ? props.nestLevel * 20 : 0),
paddingBottom: 10
}
})

interface SkeletonTreeNodeProps {
nestLevel?: number
}

const SkeletonTreeNode: FC<SkeletonTreeNodeProps> = (
export const SkeletonTreeNode: FC<SkeletonTreeNodeProps> = (
props: SkeletonTreeNodeProps
) => {
const classes = useStyles(props)
Expand All @@ -38,26 +37,24 @@ const SkeletonTreeNode: FC<SkeletonTreeNodeProps> = (
)
}

const generateTreeBlock = (i: Key) => {
return (
<Fragment key={i}>
<SkeletonTreeNode />
<SkeletonTreeNode nestLevel={1} />
{times(random(1, 3), (j: number) => (
<SkeletonTreeNode key={j} nestLevel={2} />
))}
</Fragment>
)
}
const generateTreeBlock = (i: Key) => (
<Fragment key={i}>
<SkeletonTreeNode />
<SkeletonTreeNode nestLevel={1} />
{times(random(1, 3), (j: number) => (
<SkeletonTreeNode key={j} nestLevel={2} />
))}
</Fragment>
)

interface TreeSkeletonProps {
blockCount: number
}

const TreeSkeleton: FC<TreeSkeletonProps> = ({
blockCount
}: TreeSkeletonProps) => {
return <div>{times(blockCount, i => generateTreeBlock(i))}</div>
}
}: TreeSkeletonProps) => (
<div>{times(blockCount, i => generateTreeBlock(i))}</div>
)

export default TreeSkeleton
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
import { processTreeData } from './utils'
import { processTreeData } from '../utils'
import React from 'react'
import Tree from './index'
import treeData0 from './fixtures/0_sample_data'
import TreeSkeleton from './TreeSkeleton'
import Tree from '../index'
import treeData0 from '../fixtures/0_sample_data'
import TreeSkeleton from '../TreeSkeleton'
import { mount, ReactWrapper, shallow, ShallowWrapper } from 'enzyme'

const mockOnCheck = jest.fn()

let wrapper: ReactWrapper | ShallowWrapper

beforeEach(() => {
wrapper = mount(<Tree treeData={treeData0} />)
wrapper = mount(<Tree onCheck={mockOnCheck} treeData={treeData0} />)
})

describe('Tree', () => {
Expand All @@ -18,6 +20,16 @@ describe('Tree', () => {
expect(tree).toHaveLength(1)
})

it('correctly passes treeData props if the props exist', () => {
wrapper = mount(
<Tree onCheck={mockOnCheck} treeData={[{ id: 0, name: 'test' }]} />
)

expect(wrapper.find(Tree).props().treeData).toMatchObject([
{ id: 0, name: 'test' }
])
})

describe('loading', () => {
it('renders a TreeSkeleton if loading prop is passed as true', () => {
wrapper = shallow(<Tree loading />)
Expand Down Expand Up @@ -62,11 +74,3 @@ describe('utils - processTreeData', () => {
expect(processTreeData([])).toMatchObject([])
})
})

describe('TreeSkeleton', () => {
it('renders', () => {
wrapper = mount(<TreeSkeleton blockCount={3} />)

expect(wrapper.find(TreeSkeleton)).toHaveLength(1)
})
})
47 changes: 47 additions & 0 deletions src/components/Tree/__tests__/TreeSkeleton.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import React from 'react'
import { mount, ReactWrapper } from 'enzyme'
import TreeSkeleton, { SkeletonTreeNode } from '../TreeSkeleton'

declare global {
// eslint-disable-next-line @typescript-eslint/no-namespace
namespace jest {
interface Matchers<R> {
toBeWithinRange(a: number, b: number): R
}
}
}

expect.extend({
toBeWithinRange(received, floor, ceiling) {
const pass = received >= floor && received <= ceiling
if (pass) {
return {
message: () =>
`expected ${received} not to be within range ${floor} - ${ceiling}`,
pass: true
}
} else {
return {
message: () =>
`expected ${received} to be within range ${floor} - ${ceiling}`,
pass: false
}
}
}
})

let wrapper: ReactWrapper

beforeEach(() => {
wrapper = mount(<TreeSkeleton blockCount={3} />)
})

describe('TreeSkeleton', () => {
it('renders', () => {
expect(wrapper.find(TreeSkeleton)).toHaveLength(1)
})

it('renders correct number of SkeletonTreeNodes within range', () => {
expect(wrapper.find(SkeletonTreeNode).length).toBeWithinRange(9, 15)
})
})
26 changes: 25 additions & 1 deletion src/components/Tree/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,25 @@ export interface TreeNodeType {
children?: TreeNodeType[]
}

interface CheckedNodesType {
checked: (string | number)[]
halfChecked: (string | number)[]
}

type OnCheckHandler = (
checked: CheckedNodesType | (string | number)[],
info: Record<string, any>
) => void

interface PartialTreeProps extends CommonComponentProps {
/**
* Array of nested objects of type - TreeNodeType to be passed to Tree
*/
treeData: TreeNodeType[]
/**
* Callback that runs when element is checked
*/
onCheck: OnCheckHandler
/**
* Number of blocks of skeleton loaders to show if loading is true. Each block will have between 3-5 nodes of variable width
*/
Expand All @@ -42,12 +56,22 @@ export type TreeProps = LoadingTreeProps | DataTreeProps

const Tree: FC<TreeProps> = ({
dataTag,
onCheck,
treeData,
loading = false,
skeletonBlockCount = 3
}: TreeProps) => {
const mappedTreeData = processTreeData(treeData)

let controlledCmpProps = {}

if (onCheck) {
controlledCmpProps = {
onCheck,
treeData: mappedTreeData
}
}

return loading ? (
<TreeSkeleton blockCount={skeletonBlockCount} />
) : (
Expand All @@ -56,7 +80,7 @@ const Tree: FC<TreeProps> = ({
checkable
defaultExpandAll
selectable={false}
treeData={mappedTreeData}
{...controlledCmpProps}
{...getDataTestAttributeProp('tree', dataTag)}
/>
)
Expand Down
13 changes: 4 additions & 9 deletions src/storybook.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,8 @@ import initStoryshots, {
const componentsToShallowRender = ['Tree']

initStoryshots({
test: data => {
if (componentsToShallowRender.includes(data.context.kind)) {
return shallowSnapshot({
...data
})
}

return snapshot(data)
}
test: data =>
componentsToShallowRender.includes(data.context.kind)
? shallowSnapshot(data)
: snapshot(data)
})

0 comments on commit f2b8bc7

Please sign in to comment.