From bbda684e652b95f79ec51699c3b6a48fde1a6f18 Mon Sep 17 00:00:00 2001 From: Palash Gupta Date: Tue, 2 May 2023 19:03:48 +0530 Subject: [PATCH] test: some of the test case is added (#2616) Co-authored-by: Vishal Sharma --- .../src/container/TraceDetail/utils.test.ts | 56 +++++++++++ frontend/src/container/TraceDetail/utils.ts | 7 +- frontend/src/hooks/useInterval.test.ts | 93 +++++++++++++++++++ frontend/src/hooks/usePreviousValue.test.tsx | 43 +++++++++ frontend/src/hooks/useUrlQuery.test.tsx | 57 ++++++++++++ 5 files changed, 255 insertions(+), 1 deletion(-) create mode 100644 frontend/src/container/TraceDetail/utils.test.ts create mode 100644 frontend/src/hooks/useInterval.test.ts create mode 100644 frontend/src/hooks/usePreviousValue.test.tsx create mode 100644 frontend/src/hooks/useUrlQuery.test.tsx diff --git a/frontend/src/container/TraceDetail/utils.test.ts b/frontend/src/container/TraceDetail/utils.test.ts new file mode 100644 index 0000000000..4cb20055bf --- /dev/null +++ b/frontend/src/container/TraceDetail/utils.test.ts @@ -0,0 +1,56 @@ +import { ITraceTree } from 'types/api/trace/getTraceItem'; + +import { getTreeLevelsCount } from './utils'; + +describe('traces/getTreeLevelsCount', () => { + const createNode = (id: string, children: ITraceTree[] = []): ITraceTree => ({ + id, + name: '', + value: 0, + time: 0, + startTime: 0, + tags: [], + children, + serviceName: '', + serviceColour: '', + }); + + test('should return 0 for empty tree', () => { + const emptyTree = null; + expect(getTreeLevelsCount((emptyTree as unknown) as ITraceTree)).toBe(0); + }); + + test('should return 1 for a tree with a single node', () => { + const singleNodeTree = createNode('1'); + expect(getTreeLevelsCount(singleNodeTree)).toBe(1); + }); + + test('should return correct depth for a balanced tree', () => { + const tree = createNode('1', [ + createNode('2', [createNode('4'), createNode('5')]), + createNode('3', [createNode('6'), createNode('7')]), + ]); + + expect(getTreeLevelsCount(tree)).toBe(3); + }); + + test('should return correct depth for an unbalanced tree', () => { + const tree = createNode('1', [ + createNode('2', [ + createNode('4', [createNode('8', [createNode('11')])]), + createNode('5'), + ]), + createNode('3', [createNode('6'), createNode('7', [createNode('10')])]), + ]); + + expect(getTreeLevelsCount(tree)).toBe(5); + }); + + test('should return correct depth for a tree with single child nodes', () => { + const tree = createNode('1', [ + createNode('2', [createNode('3', [createNode('4', [createNode('5')])])]), + ]); + + expect(getTreeLevelsCount(tree)).toBe(5); + }); +}); diff --git a/frontend/src/container/TraceDetail/utils.ts b/frontend/src/container/TraceDetail/utils.ts index 1e978f28ae..c907a1e586 100644 --- a/frontend/src/container/TraceDetail/utils.ts +++ b/frontend/src/container/TraceDetail/utils.ts @@ -93,7 +93,12 @@ export const getSortedData = (treeData: ITraceTree): ITraceTree => { }; export const getTreeLevelsCount = (tree: ITraceTree): number => { - let levels = 0; + if (!tree) { + return 0; + } + + let levels = 1; + const traverse = (treeNode: ITraceTree, level: number): void => { if (!treeNode) { return; diff --git a/frontend/src/hooks/useInterval.test.ts b/frontend/src/hooks/useInterval.test.ts new file mode 100644 index 0000000000..c6626b2224 --- /dev/null +++ b/frontend/src/hooks/useInterval.test.ts @@ -0,0 +1,93 @@ +import { act, renderHook } from '@testing-library/react'; + +import useInterval from './useInterval'; + +jest.useFakeTimers(); + +describe('useInterval', () => { + test('calls the callback with a given delay', () => { + const callback = jest.fn(); + const delay = 1000; + + renderHook(() => useInterval(callback, delay)); + + expect(callback).toHaveBeenCalledTimes(0); + + act(() => { + jest.advanceTimersByTime(delay); + }); + + expect(callback).toHaveBeenCalledTimes(1); + + act(() => { + jest.advanceTimersByTime(delay); + }); + + expect(callback).toHaveBeenCalledTimes(2); + }); + + test('does not call the callback if not enabled', () => { + const callback = jest.fn(); + const delay = 1000; + const enabled = false; + + renderHook(() => useInterval(callback, delay, enabled)); + + act(() => { + jest.advanceTimersByTime(delay); + }); + + expect(callback).toHaveBeenCalledTimes(0); + }); + + test('cleans up the interval when unmounted', () => { + const callback = jest.fn(); + const delay = 1000; + + const { unmount } = renderHook(() => useInterval(callback, delay)); + + act(() => { + jest.advanceTimersByTime(delay); + }); + + expect(callback).toHaveBeenCalledTimes(1); + + unmount(); + + act(() => { + jest.advanceTimersByTime(delay); + }); + + expect(callback).toHaveBeenCalledTimes(1); + }); + + test('updates the interval when delay changes', () => { + const callback = jest.fn(); + const initialDelay = 1000; + const newDelay = 2000; + + const { rerender } = renderHook(({ delay }) => useInterval(callback, delay), { + initialProps: { delay: initialDelay }, + }); + + act(() => { + jest.advanceTimersByTime(initialDelay); + }); + + expect(callback).toHaveBeenCalledTimes(1); + + rerender({ delay: newDelay }); + + act(() => { + jest.advanceTimersByTime(initialDelay); + }); + + expect(callback).toHaveBeenCalledTimes(1); + + act(() => { + jest.advanceTimersByTime(newDelay - initialDelay); + }); + + expect(callback).toHaveBeenCalledTimes(2); + }); +}); diff --git a/frontend/src/hooks/usePreviousValue.test.tsx b/frontend/src/hooks/usePreviousValue.test.tsx new file mode 100644 index 0000000000..efc3073af7 --- /dev/null +++ b/frontend/src/hooks/usePreviousValue.test.tsx @@ -0,0 +1,43 @@ +import { renderHook } from '@testing-library/react'; + +import usePreviousValue from './usePreviousValue'; + +describe('usePreviousValue', () => { + test('returns the previous value of a given variable', () => { + const { result, rerender } = renderHook( + ({ value }) => usePreviousValue(value), + { + initialProps: { value: 1 }, + baseElement: document.body, + }, + ); + + expect(result.current).toBeUndefined(); + + rerender({ value: 2 }); + + expect(result.current).toBe(1); + + rerender({ value: 3 }); + + expect(result.current).toBe(2); + }); + + test('works with different types of values', () => { + const { result, rerender } = renderHook( + ({ value }) => usePreviousValue(value), + { + initialProps: { value: 'a' }, + }, + ); + + expect(result.current).toBeUndefined(); + + rerender({ value: 'b' }); + + expect(result.current).toBe('a'); + + rerender({ value: 'c' }); + expect(result.current).toBe('b'); + }); +}); diff --git a/frontend/src/hooks/useUrlQuery.test.tsx b/frontend/src/hooks/useUrlQuery.test.tsx new file mode 100644 index 0000000000..a24edb3360 --- /dev/null +++ b/frontend/src/hooks/useUrlQuery.test.tsx @@ -0,0 +1,57 @@ +import { act, renderHook } from '@testing-library/react'; +import { createMemoryHistory } from 'history'; +import React from 'react'; +import { Router } from 'react-router-dom'; + +import useUrlQuery from './useUrlQuery'; + +describe('useUrlQuery', () => { + test('returns URLSearchParams object for the current URL search', () => { + const history = createMemoryHistory({ + initialEntries: ['/test?param1=value1¶m2=value2'], + }); + + const { result } = renderHook(() => useUrlQuery(), { + wrapper: ({ children }) => {children}, + }); + + expect(result.current.get('param1')).toBe('value1'); + expect(result.current.get('param2')).toBe('value2'); + }); + + test('updates URLSearchParams object when URL search changes', () => { + const history = createMemoryHistory({ + initialEntries: ['/test?param1=value1'], + }); + + const { result, rerender } = renderHook(() => useUrlQuery(), { + wrapper: ({ children }) => {children}, + }); + + expect(result.current.get('param1')).toBe('value1'); + expect(result.current.get('param2')).toBe(null); + + act(() => { + history.push('/test?param1=newValue1¶m2=value2'); + }); + + rerender(); + + expect(result.current.get('param1')).toBe('newValue1'); + expect(result.current.get('param2')).toBe('value2'); + }); + + test('returns empty URLSearchParams object when no query parameters are present', () => { + const history = createMemoryHistory({ + initialEntries: ['/test'], + }); + + const { result } = renderHook(() => useUrlQuery(), { + wrapper: ({ children }) => {children}, + }); + + expect(result.current.toString()).toBe(''); + expect(result.current.get('param1')).toBe(null); + expect(result.current.get('param2')).toBe(null); + }); +});