From 7f5454656f1d1f1210927b9760fa7564d852c271 Mon Sep 17 00:00:00 2001 From: anju <20214315.anju@gmail.com> Date: Mon, 28 Oct 2024 22:35:43 +0530 Subject: [PATCH 1/5] added unit testcases for useToastsInternal --- .../hooks/internal/useToastsInternal.test.tsx | 152 ++++++++++++++++++ 1 file changed, 152 insertions(+) create mode 100644 __tests__/hooks/internal/useToastsInternal.test.tsx diff --git a/__tests__/hooks/internal/useToastsInternal.test.tsx b/__tests__/hooks/internal/useToastsInternal.test.tsx new file mode 100644 index 00000000..db9039a5 --- /dev/null +++ b/__tests__/hooks/internal/useToastsInternal.test.tsx @@ -0,0 +1,152 @@ +// Import required testing utilities and hooks +import { renderHook, act } from '@testing-library/react-hooks'; +import { useToastInternal } from '../../../src/hooks/internal/useToastsInternal'; +import { useSettingsContext } from '../../../src/context/SettingsContext'; +import { useToastsContext } from '../../../src/context/ToastsContext'; +import { useRcbEventInternal } from '../../../src/hooks/internal/useRcbEventInternal'; +import { RcbEvent } from '../../../src/constants/RcbEvent'; +import { generateSecureUUID } from '../../../src/utils/idGenerator'; + +// Mock dependencies used in the tests +jest.mock('../../../src/context/SettingsContext'); +jest.mock('../../../src/context/ToastsContext'); +jest.mock('../../../src/hooks/internal/useRcbEventInternal'); +jest.mock('../../../src/utils/idGenerator', () => ({ + generateSecureUUID: jest.fn(), +})); + +describe('useToastInternal', () => { + let mockSettingsContext: any; + let mockToastsContext: any; + let mockRcbEventInternal: any; + + beforeEach(() => { + // Set up mock settings and contexts before each test + mockSettingsContext = { + settings: { + toast: { maxCount: 3, forbidOnMax: true }, + event: { + rcbShowToast: true, + rcbDismissToast: true, + } + } + }; + (useSettingsContext as jest.Mock).mockReturnValue(mockSettingsContext); + + mockToastsContext = { + toasts: [], + setToasts: jest.fn(), + }; + (useToastsContext as jest.Mock).mockReturnValue(mockToastsContext); + + mockRcbEventInternal = { + callRcbEvent: jest.fn(), + }; + (useRcbEventInternal as jest.Mock).mockReturnValue(mockRcbEventInternal); + + (generateSecureUUID as jest.Mock).mockReturnValue('mocked-uuid'); + }); + + afterEach(() => { + // Clear mocks after each test + jest.clearAllMocks(); + }); + + it('should add a new toast when not exceeding maxCount', () => { + // Test adding a toast when maxCount is not reached + mockRcbEventInternal.callRcbEvent.mockReturnValue({ defaultPrevented: false, + data: { toast: { id: 'mocked-uuid', content: 'New toast content', timeout: undefined } + } }); + const { result } = renderHook(() => useToastInternal()); + act(() => { + result.current.showToast('New toast content'); + }); + expect(generateSecureUUID).toHaveBeenCalled(); + expect(mockToastsContext.setToasts).toHaveBeenCalledWith(expect.any(Function)); + + // Verify that the toast was added + const setToastsFn = mockToastsContext.setToasts.mock.calls[0][0]; + const newToasts = setToastsFn([]); + expect(newToasts).toEqual([{ id: 'mocked-uuid', content: 'New toast content', timeout: undefined }]); + }); + + it('should not add a new toast if maxCount is reached and forbidOnMax is true', () => { + // Test forbidding new toast if maxCount is reached + mockToastsContext.toasts = [{ id: '1' }, { id: '2' }, { id: '3' }]; + const { result } = renderHook(() => useToastInternal()); + const toastId = result.current.showToast('Toast content'); + expect(toastId).toBeNull(); + expect(mockToastsContext.setToasts).not.toHaveBeenCalled(); + }); + + it('should remove the oldest toast and add a new one if maxCount is reached but forbidOnMax is false', () => { + // Test replacing oldest toast if maxCount reached and forbidOnMax is false + mockSettingsContext.settings.toast.forbidOnMax = false; + mockToastsContext.toasts = [{ id: '1' }, { id: '2' }, { id: '3' }]; + mockRcbEventInternal.callRcbEvent.mockReturnValue({ + defaultPrevented: false, data: { toast: { id: 'mocked-uuid', + content: 'New toast content', timeout: undefined } + } }); + const { result } = renderHook(() => useToastInternal()); + act(() => { + result.current.showToast('New toast content'); + }); + expect(mockToastsContext.setToasts).toHaveBeenCalledWith(expect.any(Function)); + + // Verify the oldest toast was removed and new one added + const setToastsFn = mockToastsContext.setToasts.mock.calls[0][0]; + const newToasts = setToastsFn([{ id: '1' }, { id: '2' }, { id: '3' }]); + expect(newToasts).toEqual([ + { id: '2' }, + { id: '3' }, + { id: 'mocked-uuid', content: 'New toast content', timeout: undefined }, + ]); + }); + + it('should dismiss a toast by id', () => { + // Test dismissing a toast by ID + const toast = { id: 'toast-1', content: 'Toast to dismiss' }; + mockToastsContext.toasts = [toast]; + mockRcbEventInternal.callRcbEvent.mockReturnValue({ defaultPrevented: false }); + const { result } = renderHook(() => useToastInternal()); + act(() => { + result.current.dismissToast('toast-1'); + }); + expect(mockToastsContext.setToasts).toHaveBeenCalledWith(expect.any(Function)); + + // Verify toast was dismissed + const setToastsFn = mockToastsContext.setToasts.mock.calls[0][0]; + const updatedToasts = setToastsFn([toast]); + expect(updatedToasts).toEqual([]); + }); + + it('should not dismiss a toast if the id is not found', () => { + // Test no dismissal if ID not found + mockToastsContext.toasts = [{ id: 'toast-2', content: 'Another toast' }]; + const { result } = renderHook(() => useToastInternal()); + const resultId = result.current.dismissToast('invalid-id'); + expect(resultId).toBeNull(); + expect(mockToastsContext.setToasts).not.toHaveBeenCalled(); + }); + + it('should not show toast if rcbShowToast event is prevented', () => { + // Test prevention of toast display by event + mockRcbEventInternal.callRcbEvent.mockReturnValue({ defaultPrevented: true }); + const { result } = renderHook(() => useToastInternal()); + const resultId = result.current.showToast('Prevented toast'); + expect(resultId).toBeNull(); + expect(mockToastsContext.setToasts).not.toHaveBeenCalled(); + }); + + it('should call rcbDismissToast event when dismissing a toast', () => { + // Test triggering of dismiss event upon toast removal + const toast = { id: 'toast-1', content: 'Toast to dismiss' }; + mockToastsContext.toasts = [toast]; + mockRcbEventInternal.callRcbEvent.mockReturnValue({ defaultPrevented: false }); + const { result } = renderHook(() => useToastInternal()); + act(() => { + result.current.dismissToast('toast-1'); + }); + expect(mockRcbEventInternal.callRcbEvent).toHaveBeenCalledWith(RcbEvent.DISMISS_TOAST, { toast }); + }); +}); From bcd356bbdb7827d023954a13143cda527142dc3f Mon Sep 17 00:00:00 2001 From: anju <20214315.anju@gmail.com> Date: Mon, 28 Oct 2024 22:52:15 +0530 Subject: [PATCH 2/5] updated usetoastsInternal --- .../hooks/internal/useToastsInternal.test.tsx | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/__tests__/hooks/internal/useToastsInternal.test.tsx b/__tests__/hooks/internal/useToastsInternal.test.tsx index db9039a5..bcbd2437 100644 --- a/__tests__/hooks/internal/useToastsInternal.test.tsx +++ b/__tests__/hooks/internal/useToastsInternal.test.tsx @@ -1,6 +1,6 @@ // Import required testing utilities and hooks import { renderHook, act } from '@testing-library/react-hooks'; -import { useToastInternal } from '../../../src/hooks/internal/useToastsInternal'; +import { useToastsInternal } from '../../../src/hooks/internal/useToastsInternal'; import { useSettingsContext } from '../../../src/context/SettingsContext'; import { useToastsContext } from '../../../src/context/ToastsContext'; import { useRcbEventInternal } from '../../../src/hooks/internal/useRcbEventInternal'; @@ -15,7 +15,7 @@ jest.mock('../../../src/utils/idGenerator', () => ({ generateSecureUUID: jest.fn(), })); -describe('useToastInternal', () => { +describe('useToastsInternal', () => { let mockSettingsContext: any; let mockToastsContext: any; let mockRcbEventInternal: any; @@ -57,7 +57,7 @@ describe('useToastInternal', () => { mockRcbEventInternal.callRcbEvent.mockReturnValue({ defaultPrevented: false, data: { toast: { id: 'mocked-uuid', content: 'New toast content', timeout: undefined } } }); - const { result } = renderHook(() => useToastInternal()); + const { result } = renderHook(() => useToastsInternal()); act(() => { result.current.showToast('New toast content'); }); @@ -73,7 +73,7 @@ describe('useToastInternal', () => { it('should not add a new toast if maxCount is reached and forbidOnMax is true', () => { // Test forbidding new toast if maxCount is reached mockToastsContext.toasts = [{ id: '1' }, { id: '2' }, { id: '3' }]; - const { result } = renderHook(() => useToastInternal()); + const { result } = renderHook(() => useToastsInternal()); const toastId = result.current.showToast('Toast content'); expect(toastId).toBeNull(); expect(mockToastsContext.setToasts).not.toHaveBeenCalled(); @@ -87,7 +87,7 @@ describe('useToastInternal', () => { defaultPrevented: false, data: { toast: { id: 'mocked-uuid', content: 'New toast content', timeout: undefined } } }); - const { result } = renderHook(() => useToastInternal()); + const { result } = renderHook(() => useToastsInternal()); act(() => { result.current.showToast('New toast content'); }); @@ -108,7 +108,7 @@ describe('useToastInternal', () => { const toast = { id: 'toast-1', content: 'Toast to dismiss' }; mockToastsContext.toasts = [toast]; mockRcbEventInternal.callRcbEvent.mockReturnValue({ defaultPrevented: false }); - const { result } = renderHook(() => useToastInternal()); + const { result } = renderHook(() => useToastsInternal()); act(() => { result.current.dismissToast('toast-1'); }); @@ -123,7 +123,7 @@ describe('useToastInternal', () => { it('should not dismiss a toast if the id is not found', () => { // Test no dismissal if ID not found mockToastsContext.toasts = [{ id: 'toast-2', content: 'Another toast' }]; - const { result } = renderHook(() => useToastInternal()); + const { result } = renderHook(() => useToastsInternal()); const resultId = result.current.dismissToast('invalid-id'); expect(resultId).toBeNull(); expect(mockToastsContext.setToasts).not.toHaveBeenCalled(); @@ -132,7 +132,7 @@ describe('useToastInternal', () => { it('should not show toast if rcbShowToast event is prevented', () => { // Test prevention of toast display by event mockRcbEventInternal.callRcbEvent.mockReturnValue({ defaultPrevented: true }); - const { result } = renderHook(() => useToastInternal()); + const { result } = renderHook(() => useToastsInternal()); const resultId = result.current.showToast('Prevented toast'); expect(resultId).toBeNull(); expect(mockToastsContext.setToasts).not.toHaveBeenCalled(); @@ -143,7 +143,7 @@ describe('useToastInternal', () => { const toast = { id: 'toast-1', content: 'Toast to dismiss' }; mockToastsContext.toasts = [toast]; mockRcbEventInternal.callRcbEvent.mockReturnValue({ defaultPrevented: false }); - const { result } = renderHook(() => useToastInternal()); + const { result } = renderHook(() => useToastsInternal()); act(() => { result.current.dismissToast('toast-1'); }); From 640559d8ad0dc4499151d75268ea9317a0c83872 Mon Sep 17 00:00:00 2001 From: anju <20214315.anju@gmail.com> Date: Mon, 28 Oct 2024 22:59:29 +0530 Subject: [PATCH 3/5] updated --- __tests__/hooks/internal/useToastsInternal.test.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/__tests__/hooks/internal/useToastsInternal.test.tsx b/__tests__/hooks/internal/useToastsInternal.test.tsx index bcbd2437..3287b3c1 100644 --- a/__tests__/hooks/internal/useToastsInternal.test.tsx +++ b/__tests__/hooks/internal/useToastsInternal.test.tsx @@ -1,5 +1,5 @@ // Import required testing utilities and hooks -import { renderHook, act } from '@testing-library/react-hooks'; +import { renderHook, act } from "@testing-library/react"; import { useToastsInternal } from '../../../src/hooks/internal/useToastsInternal'; import { useSettingsContext } from '../../../src/context/SettingsContext'; import { useToastsContext } from '../../../src/context/ToastsContext'; From 2eb9c44d091b43cb6e18c168b5bb94cee8656a25 Mon Sep 17 00:00:00 2001 From: anju <20214315.anju@gmail.com> Date: Tue, 29 Oct 2024 15:25:28 +0530 Subject: [PATCH 4/5] defined the types to avoid hard-code --- .../hooks/internal/useToastsInternal.test.tsx | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/__tests__/hooks/internal/useToastsInternal.test.tsx b/__tests__/hooks/internal/useToastsInternal.test.tsx index 3287b3c1..a90f1457 100644 --- a/__tests__/hooks/internal/useToastsInternal.test.tsx +++ b/__tests__/hooks/internal/useToastsInternal.test.tsx @@ -15,10 +15,21 @@ jest.mock('../../../src/utils/idGenerator', () => ({ generateSecureUUID: jest.fn(), })); +// Define types for mock contexts and events + type MockSettingsContextType = { + settings: { toast: { + maxCount: number; forbidOnMax: boolean; }; + event: { rcbShowToast: boolean; rcbDismissToast: boolean; }; + }; }; + type MockToastsContextType = { toasts: Array<{ id: string; content?: string }>; + setToasts: jest.Mock; }; + type MockRcbEventInternalType = { callRcbEvent: jest.Mock;}; + + describe('useToastsInternal', () => { - let mockSettingsContext: any; - let mockToastsContext: any; - let mockRcbEventInternal: any; + let mockSettingsContext: MockSettingsContextType; + let mockToastsContext: MockToastsContextType; + let mockRcbEventInternal: MockRcbEventInternalType beforeEach(() => { // Set up mock settings and contexts before each test From 0f2d54faf1be807128cc21dbe11634d707c295d0 Mon Sep 17 00:00:00 2001 From: anju <20214315.anju@gmail.com> Date: Tue, 29 Oct 2024 15:31:53 +0530 Subject: [PATCH 5/5] tabs issue resolved --- .../hooks/internal/useToastsInternal.test.tsx | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/__tests__/hooks/internal/useToastsInternal.test.tsx b/__tests__/hooks/internal/useToastsInternal.test.tsx index a90f1457..1a0f547a 100644 --- a/__tests__/hooks/internal/useToastsInternal.test.tsx +++ b/__tests__/hooks/internal/useToastsInternal.test.tsx @@ -16,14 +16,14 @@ jest.mock('../../../src/utils/idGenerator', () => ({ })); // Define types for mock contexts and events - type MockSettingsContextType = { - settings: { toast: { - maxCount: number; forbidOnMax: boolean; }; - event: { rcbShowToast: boolean; rcbDismissToast: boolean; }; - }; }; - type MockToastsContextType = { toasts: Array<{ id: string; content?: string }>; - setToasts: jest.Mock; }; - type MockRcbEventInternalType = { callRcbEvent: jest.Mock;}; +type MockSettingsContextType = { + settings: { toast: { + maxCount: number; forbidOnMax: boolean; }; + event: { rcbShowToast: boolean; rcbDismissToast: boolean; };};}; +type MockToastsContextType = { + toasts: Array<{ id: string; content?: string }>; + setToasts: jest.Mock; }; +type MockRcbEventInternalType = { callRcbEvent: jest.Mock;}; describe('useToastsInternal', () => {