-
-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
test: added test cases for helper functions and zustand store
- Loading branch information
1 parent
0df57db
commit 20dfaeb
Showing
13 changed files
with
1,296 additions
and
459 deletions.
There are no files selected for viewing
File renamed without changes.
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 @@ | ||
import '@testing-library/jest-native/extend-expect'; |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
import { TreeNode, __FlattenedTreeNode__ } from "../types/treeView.types"; | ||
|
||
export const tree3d2b = [ | ||
{ | ||
"id": "1", | ||
"name": "node1", | ||
"children": [ | ||
{ | ||
"id": "1.1", | ||
"name": "node1.1", | ||
"children": [ | ||
{ | ||
"id": "1.1.1", | ||
"name": "node1.1.1" | ||
}, | ||
{ | ||
"id": "1.1.2", | ||
"name": "node1.1.2" | ||
} | ||
] | ||
}, | ||
{ | ||
"id": "1.2", | ||
"name": "node1.2", | ||
"children": [ | ||
{ | ||
"id": "1.2.1", | ||
"name": "node1.2.1" | ||
}, | ||
{ | ||
"id": "1.2.2", | ||
"name": "node1.2.2" | ||
} | ||
] | ||
} | ||
] | ||
}, | ||
{ | ||
"id": "2", | ||
"name": "node2", | ||
"children": [ | ||
{ | ||
"id": "2.1", | ||
"name": "node2.1", | ||
"children": [ | ||
{ | ||
"id": "2.1.1", | ||
"name": "node2.1.1" | ||
}, | ||
{ | ||
"id": "2.1.2", | ||
"name": "node2.1.2" | ||
} | ||
] | ||
}, | ||
{ | ||
"id": "2.2", | ||
"name": "node2.2", | ||
"children": [ | ||
{ | ||
"id": "2.2.1", | ||
"name": "node2.2.1" | ||
}, | ||
{ | ||
"id": "2.2.2", | ||
"name": "node2.2.2" | ||
} | ||
] | ||
} | ||
] | ||
} | ||
]; | ||
|
||
export function generateTree( | ||
depth: number, | ||
breadth: number, | ||
prefix: string = '' | ||
): TreeNode[] { | ||
let nodes: TreeNode[] = []; | ||
|
||
for (let i = 1; i <= breadth; i++) { | ||
let node: TreeNode = { | ||
id: `${prefix}${i}`, | ||
name: `node${prefix}${i}` | ||
}; | ||
|
||
if (depth > 1) { | ||
node.children = generateTree(depth - 1, breadth, `${prefix}${i}.`); | ||
} | ||
|
||
nodes.push(node); | ||
} | ||
|
||
return nodes; | ||
} | ||
|
||
export function generateExpectedFlatTree( | ||
nodes: TreeNode[], | ||
expandedIds: Set<string>, | ||
level: number = 0 | ||
): __FlattenedTreeNode__[] { | ||
let flattened: __FlattenedTreeNode__[] = []; | ||
for (let node of nodes) { | ||
flattened.push({ ...node, level: level }); | ||
if (node.children && expandedIds.has(node.id)) { | ||
flattened = [ | ||
...flattened, | ||
...generateExpectedFlatTree(node.children, expandedIds, level + 1) | ||
]; | ||
} | ||
} | ||
return flattened; | ||
} | ||
|
||
export function createRandomNumberSet() { | ||
let randomNumbers = new Set<string>(); | ||
|
||
while (randomNumbers.size < 10) { | ||
// Random number between 0 and 99 | ||
let randomNumber = Math.floor(Math.random() * 100); | ||
randomNumbers.add(randomNumber.toString()); | ||
} | ||
|
||
return randomNumbers; | ||
} |
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,24 @@ | ||
import { act } from '@testing-library/react-native'; | ||
import { StateCreator } from 'zustand'; | ||
|
||
const { create: actualCreate } = jest.requireActual('zustand'); | ||
|
||
// a variable to hold reset functions for all stores declared in the app | ||
const storeResetFns = new Set<() => void>(); | ||
|
||
// when creating a store, we get its initial state, create a reset function and add it in the set | ||
export const create = <S>(createState: StateCreator<S>) => { | ||
const store = actualCreate(createState); | ||
const initialState = store.getState(); | ||
storeResetFns.add(() => store.setState(initialState, true)); | ||
return store; | ||
}; | ||
|
||
// Reset all stores after each test run | ||
beforeEach(async () => { | ||
await act(() => | ||
storeResetFns.forEach(resetFn => { | ||
resetFn(); | ||
}) | ||
); | ||
}); |
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,157 @@ | ||
jest.mock('zustand'); | ||
|
||
import { useTreeViewStore } from '../store/treeView.store'; | ||
import { tree3d2b } from "../__mocks__/generateTree.mock"; | ||
import { | ||
collapseAll, | ||
expandAll, | ||
handleToggleExpand, | ||
initializeNodeMaps | ||
} from '../helpers'; | ||
import { act } from 'react-test-renderer'; | ||
import { TreeNode } from '../types/treeView.types'; | ||
|
||
describe('expandAll', () => { | ||
beforeEach(() => { | ||
useTreeViewStore.setState(useTreeViewStore.getState(), true); | ||
|
||
// Setup mock tree | ||
useTreeViewStore.getState().updateInitialTreeViewData(tree3d2b); | ||
initializeNodeMaps(tree3d2b); | ||
}); | ||
|
||
it('calls expandAll on initial tree(all collapsed)', () => { | ||
act(() => { | ||
expandAll(); | ||
}); | ||
|
||
const { expanded, nodeMap } = useTreeViewStore.getState(); | ||
|
||
// Convert nodeMap.keys() iterator to a Set for comparison | ||
const nodeKeys = new Set(nodeMap.keys()); | ||
expect(expanded).toEqual(nodeKeys); | ||
}); | ||
|
||
it('expands all node in tree with some nodes which are already expanded', () => { | ||
act(() => { | ||
handleToggleExpand('1'); | ||
handleToggleExpand('2'); | ||
handleToggleExpand('1.1'); | ||
handleToggleExpand('1.2'); | ||
handleToggleExpand('1.1'); | ||
|
||
expandAll(); | ||
}); | ||
|
||
const { expanded, nodeMap } = useTreeViewStore.getState(); | ||
|
||
// Convert nodeMap.keys() iterator to a Set for comparison | ||
const nodeKeys = new Set(nodeMap.keys()); | ||
expect(expanded).toEqual(nodeKeys); | ||
}); | ||
}); | ||
|
||
describe('collapseAll', () => { | ||
beforeEach(() => { | ||
useTreeViewStore.setState(useTreeViewStore.getState(), true); | ||
|
||
// Setup mock tree | ||
useTreeViewStore.getState().updateInitialTreeViewData(tree3d2b); | ||
initializeNodeMaps(tree3d2b); | ||
}); | ||
|
||
it('calls collapseAll on initial tree(all collapsed)', () => { | ||
act(() => { | ||
collapseAll(); | ||
}); | ||
|
||
const { expanded } = useTreeViewStore.getState(); | ||
expect(expanded).toEqual(new Set<string>()); | ||
}); | ||
|
||
it('collapses all node in tree with some nodes which are already expanded', () => { | ||
act(() => { | ||
handleToggleExpand('1'); | ||
handleToggleExpand('2'); | ||
handleToggleExpand('1.1'); | ||
handleToggleExpand('1.2'); | ||
handleToggleExpand('1.1'); | ||
|
||
collapseAll(); | ||
}); | ||
|
||
const { expanded } = useTreeViewStore.getState(); | ||
|
||
expect(expanded).toEqual(new Set<string>()); | ||
}); | ||
}); | ||
|
||
describe('handleToggleExpand', () => { | ||
beforeEach(() => { | ||
useTreeViewStore.setState(useTreeViewStore.getState(), true); | ||
}); | ||
|
||
test('handleToggleExpand correctly toggles the expanded state of a tree node', () => { | ||
const initialData: TreeNode[] = [ | ||
{ | ||
id: '1', | ||
name: 'Node 1', | ||
children: [ | ||
{ | ||
id: '1.1', | ||
name: 'Node 1.1' | ||
}, | ||
{ | ||
id: '1.2', | ||
name: 'Node 1.2', | ||
children: [{ | ||
id: '1.2.1', | ||
name: 'Node 1.2.1' | ||
}] | ||
}, | ||
], | ||
}, | ||
{ | ||
id: '2', | ||
name: 'Node 2' | ||
}, | ||
]; | ||
|
||
act(() => { | ||
useTreeViewStore.getState().updateInitialTreeViewData(initialData); | ||
initializeNodeMaps(initialData); | ||
}); | ||
|
||
act(() => { | ||
handleToggleExpand('1'); | ||
}); | ||
|
||
// Node '1' should now be expanded | ||
let { expanded } = useTreeViewStore.getState(); | ||
expect(expanded.has('1')).toBeTruthy(); | ||
|
||
act(() => { | ||
handleToggleExpand('1.2'); | ||
}); | ||
|
||
// Node '1.2' should now be expanded, Node '1'(parent) should remain expanded | ||
expanded = useTreeViewStore.getState().expanded; | ||
expect(expanded.has('1.2')).toBeTruthy(); | ||
expect(expanded.has('1')).toBeTruthy(); | ||
|
||
act(() => { | ||
handleToggleExpand('1'); | ||
handleToggleExpand('2'); | ||
}); | ||
|
||
// Node '1' and its descendants should now be collapsed but Node '2' should remain expanded | ||
expanded = useTreeViewStore.getState().expanded; | ||
|
||
expect(expanded.has('1')).toBeFalsy(); | ||
expect(expanded.has('1.1')).toBeFalsy(); | ||
expect(expanded.has('1.2')).toBeFalsy(); | ||
expect(expanded.has('1.2.1')).toBeFalsy(); | ||
|
||
expect(expanded.has('2')).toBeTruthy(); | ||
}); | ||
}); |
Oops, something went wrong.