|  | 
|  | 1 | +// ===== IMPORTS ===== | 
|  | 2 | +import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'; | 
|  | 3 | +import { QueueService } from '../../../../src/services/orchestrator/queues'; | 
|  | 4 | +import { ApiClient } from '../../../../src/core/http/api-client'; | 
|  | 5 | +import { PaginationHelpers } from '../../../../src/utils/pagination/helpers'; | 
|  | 6 | +import { | 
|  | 7 | +  createMockRawQueue, | 
|  | 8 | +  createMockTransformedQueueCollection | 
|  | 9 | +} from '../../../utils/mocks/queues'; | 
|  | 10 | +import { createServiceTestDependencies, createMockApiClient } from '../../../utils/setup'; | 
|  | 11 | +import { createMockError } from '../../../utils/mocks/core'; | 
|  | 12 | +import { | 
|  | 13 | +  QueueGetAllOptions, | 
|  | 14 | +  QueueGetByIdOptions | 
|  | 15 | +} from '../../../../src/models/orchestrator/queues.types'; | 
|  | 16 | +import { QUEUE_TEST_CONSTANTS } from '../../../utils/constants/queues'; | 
|  | 17 | +import { TEST_CONSTANTS } from '../../../utils/constants/common'; | 
|  | 18 | +import { QUEUE_ENDPOINTS } from '../../../../src/utils/constants/endpoints'; | 
|  | 19 | +import { FOLDER_ID } from '../../../../src/utils/constants/headers'; | 
|  | 20 | + | 
|  | 21 | +// ===== MOCKING ===== | 
|  | 22 | +// Mock the dependencies | 
|  | 23 | +vi.mock('../../../../src/core/http/api-client'); | 
|  | 24 | + | 
|  | 25 | +// Import mock objects using vi.hoisted() - this ensures they're available before vi.mock() calls | 
|  | 26 | +const mocks = vi.hoisted(() => { | 
|  | 27 | +  // Import/re-export the mock utilities from core | 
|  | 28 | +  return import('../../../utils/mocks/core'); | 
|  | 29 | +}); | 
|  | 30 | + | 
|  | 31 | +// Setup mocks at module level | 
|  | 32 | +// NOTE: We do NOT mock transformData | 
|  | 33 | +vi.mock('../../../../src/utils/pagination/helpers', async () => (await mocks).mockPaginationHelpers); | 
|  | 34 | + | 
|  | 35 | +// ===== TEST SUITE ===== | 
|  | 36 | +describe('QueueService Unit Tests', () => { | 
|  | 37 | +  let queueService: QueueService; | 
|  | 38 | +  let mockApiClient: any; | 
|  | 39 | + | 
|  | 40 | +  beforeEach(() => { | 
|  | 41 | +    // Create mock instances using centralized setup | 
|  | 42 | +    const { config, executionContext, tokenManager } = createServiceTestDependencies(); | 
|  | 43 | +    mockApiClient = createMockApiClient(); | 
|  | 44 | + | 
|  | 45 | +    // Mock the ApiClient constructor | 
|  | 46 | +    vi.mocked(ApiClient).mockImplementation(() => mockApiClient); | 
|  | 47 | + | 
|  | 48 | +    // Reset pagination helpers mock before each test | 
|  | 49 | +    vi.mocked(PaginationHelpers.getAll).mockReset(); | 
|  | 50 | + | 
|  | 51 | +    queueService = new QueueService(config, executionContext, tokenManager); | 
|  | 52 | +  }); | 
|  | 53 | + | 
|  | 54 | +  afterEach(() => { | 
|  | 55 | +    vi.clearAllMocks(); | 
|  | 56 | +  }); | 
|  | 57 | + | 
|  | 58 | +  describe('getById', () => { | 
|  | 59 | +    it('should get queue by ID successfully with all fields mapped correctly', async () => { | 
|  | 60 | +      const mockQueue = createMockRawQueue(); | 
|  | 61 | + | 
|  | 62 | +      mockApiClient.get.mockResolvedValue(mockQueue); | 
|  | 63 | + | 
|  | 64 | +      const result = await queueService.getById( | 
|  | 65 | +        QUEUE_TEST_CONSTANTS.QUEUE_ID, | 
|  | 66 | +        TEST_CONSTANTS.FOLDER_ID | 
|  | 67 | +      ); | 
|  | 68 | + | 
|  | 69 | +      // Verify the result | 
|  | 70 | +      expect(result).toBeDefined(); | 
|  | 71 | +      expect(result.id).toBe(QUEUE_TEST_CONSTANTS.QUEUE_ID); | 
|  | 72 | +      expect(result.name).toBe(QUEUE_TEST_CONSTANTS.QUEUE_NAME); | 
|  | 73 | +      expect(result.riskSlaInMinutes).toBe(QUEUE_TEST_CONSTANTS.RISK_SLA_IN_MINUTES); | 
|  | 74 | + | 
|  | 75 | +      // Verify the API call has correct endpoint and headers | 
|  | 76 | +      expect(mockApiClient.get).toHaveBeenCalledWith( | 
|  | 77 | +        QUEUE_ENDPOINTS.GET_BY_ID(QUEUE_TEST_CONSTANTS.QUEUE_ID), | 
|  | 78 | +        expect.objectContaining({ | 
|  | 79 | +          headers: expect.objectContaining({ | 
|  | 80 | +            [FOLDER_ID]: TEST_CONSTANTS.FOLDER_ID.toString() | 
|  | 81 | +          }) | 
|  | 82 | +        }) | 
|  | 83 | +      ); | 
|  | 84 | + | 
|  | 85 | +      // Verify field transformations | 
|  | 86 | +      // CreationTime -> createdTime | 
|  | 87 | +      expect(result.createdTime).toBe(QUEUE_TEST_CONSTANTS.CREATED_TIME); | 
|  | 88 | +      expect((result as any).CreationTime).toBeUndefined(); // Original field should be removed | 
|  | 89 | + | 
|  | 90 | +      // OrganizationUnitId -> folderId | 
|  | 91 | +      expect(result.folderId).toBe(TEST_CONSTANTS.FOLDER_ID); | 
|  | 92 | +      expect((result as any).OrganizationUnitId).toBeUndefined(); // Original field should be removed | 
|  | 93 | + | 
|  | 94 | +      // OrganizationUnitFullyQualifiedName -> folderName | 
|  | 95 | +      expect(result.folderName).toBe(TEST_CONSTANTS.FOLDER_NAME); | 
|  | 96 | +      expect((result as any).OrganizationUnitFullyQualifiedName).toBeUndefined(); // Original field should be removed | 
|  | 97 | +    }); | 
|  | 98 | + | 
|  | 99 | +    it('should get queue with options successfully', async () => { | 
|  | 100 | +      const mockQueue = createMockRawQueue(); | 
|  | 101 | +      mockApiClient.get.mockResolvedValue(mockQueue); | 
|  | 102 | + | 
|  | 103 | +      const options: QueueGetByIdOptions = { | 
|  | 104 | +        select: QUEUE_TEST_CONSTANTS.ODATA_SELECT_FIELDS | 
|  | 105 | +      }; | 
|  | 106 | + | 
|  | 107 | +      await queueService.getById( | 
|  | 108 | +        QUEUE_TEST_CONSTANTS.QUEUE_ID, | 
|  | 109 | +        TEST_CONSTANTS.FOLDER_ID, | 
|  | 110 | +        options | 
|  | 111 | +      ); | 
|  | 112 | + | 
|  | 113 | +      // Verify API call has options with OData prefix | 
|  | 114 | +      expect(mockApiClient.get).toHaveBeenCalledWith( | 
|  | 115 | +        QUEUE_ENDPOINTS.GET_BY_ID(QUEUE_TEST_CONSTANTS.QUEUE_ID), | 
|  | 116 | +        expect.objectContaining({ | 
|  | 117 | +          params: expect.objectContaining({ | 
|  | 118 | +            '$select': QUEUE_TEST_CONSTANTS.ODATA_SELECT_FIELDS | 
|  | 119 | +          }) | 
|  | 120 | +        }) | 
|  | 121 | +      ); | 
|  | 122 | +    }); | 
|  | 123 | + | 
|  | 124 | +    it('should handle API errors', async () => { | 
|  | 125 | +      const error = createMockError(QUEUE_TEST_CONSTANTS.ERROR_QUEUE_NOT_FOUND); | 
|  | 126 | +      mockApiClient.get.mockRejectedValue(error); | 
|  | 127 | + | 
|  | 128 | +      await expect(queueService.getById( | 
|  | 129 | +        QUEUE_TEST_CONSTANTS.QUEUE_ID, | 
|  | 130 | +        TEST_CONSTANTS.FOLDER_ID | 
|  | 131 | +      )).rejects.toThrow(QUEUE_TEST_CONSTANTS.ERROR_QUEUE_NOT_FOUND); | 
|  | 132 | +    }); | 
|  | 133 | +  }); | 
|  | 134 | + | 
|  | 135 | +  describe('getAll', () => { | 
|  | 136 | +    it('should return all queues with proper field transformations', async () => { | 
|  | 137 | +      const mockResponse = createMockTransformedQueueCollection(); | 
|  | 138 | + | 
|  | 139 | +      vi.mocked(PaginationHelpers.getAll).mockResolvedValue(mockResponse); | 
|  | 140 | + | 
|  | 141 | +      const result = await queueService.getAll(); | 
|  | 142 | + | 
|  | 143 | +      // Verify PaginationHelpers.getAll was called | 
|  | 144 | +      expect(PaginationHelpers.getAll).toHaveBeenCalledWith( | 
|  | 145 | +        expect.objectContaining({ | 
|  | 146 | +          serviceAccess: expect.any(Object), | 
|  | 147 | +          getEndpoint: expect.any(Function), | 
|  | 148 | +          transformFn: expect.any(Function), | 
|  | 149 | +          pagination: expect.any(Object) | 
|  | 150 | +        }), | 
|  | 151 | +        undefined | 
|  | 152 | +      ); | 
|  | 153 | + | 
|  | 154 | +      expect(result).toEqual(mockResponse); | 
|  | 155 | + | 
|  | 156 | +      // Verify the endpoint function returns the correct endpoint | 
|  | 157 | +      const paginationConfig = vi.mocked(PaginationHelpers.getAll).mock.calls[0][0]; | 
|  | 158 | +      const endpoint = paginationConfig.getEndpoint(); | 
|  | 159 | +      expect(endpoint).toBe(QUEUE_ENDPOINTS.GET_ALL); | 
|  | 160 | +    }); | 
|  | 161 | + | 
|  | 162 | +    it('should return queues filtered by folder ID', async () => { | 
|  | 163 | +      const mockResponse = createMockTransformedQueueCollection(); | 
|  | 164 | + | 
|  | 165 | +      vi.mocked(PaginationHelpers.getAll).mockResolvedValue(mockResponse); | 
|  | 166 | + | 
|  | 167 | +      const options: QueueGetAllOptions = { | 
|  | 168 | +        folderId: TEST_CONSTANTS.FOLDER_ID | 
|  | 169 | +      }; | 
|  | 170 | + | 
|  | 171 | +      const result = await queueService.getAll(options); | 
|  | 172 | + | 
|  | 173 | +      // Verify PaginationHelpers.getAll was called with folder options | 
|  | 174 | +      expect(PaginationHelpers.getAll).toHaveBeenCalledWith( | 
|  | 175 | +        expect.any(Object), | 
|  | 176 | +        expect.objectContaining({ | 
|  | 177 | +          folderId: TEST_CONSTANTS.FOLDER_ID | 
|  | 178 | +        }) | 
|  | 179 | +      ); | 
|  | 180 | + | 
|  | 181 | +      expect(result).toEqual(mockResponse); | 
|  | 182 | + | 
|  | 183 | +      // Verify the endpoint function returns the correct endpoint when called with a folderId | 
|  | 184 | +      const paginationConfig = vi.mocked(PaginationHelpers.getAll).mock.calls[0][0]; | 
|  | 185 | +      const endpoint = paginationConfig.getEndpoint(TEST_CONSTANTS.FOLDER_ID); | 
|  | 186 | +      expect(endpoint).toBe(QUEUE_ENDPOINTS.GET_BY_FOLDER); | 
|  | 187 | +    }); | 
|  | 188 | + | 
|  | 189 | +    it('should return paginated queues when pagination options provided', async () => { | 
|  | 190 | +      const mockResponse = createMockTransformedQueueCollection(100, { | 
|  | 191 | +        totalCount: 100, | 
|  | 192 | +        hasNextPage: true, | 
|  | 193 | +        nextCursor: TEST_CONSTANTS.NEXT_CURSOR, | 
|  | 194 | +        previousCursor: null, | 
|  | 195 | +        currentPage: 1, | 
|  | 196 | +        totalPages: 10 | 
|  | 197 | +      }); | 
|  | 198 | + | 
|  | 199 | +      vi.mocked(PaginationHelpers.getAll).mockResolvedValue(mockResponse); | 
|  | 200 | + | 
|  | 201 | +      const options: QueueGetAllOptions = { | 
|  | 202 | +        pageSize: TEST_CONSTANTS.PAGE_SIZE | 
|  | 203 | +      }; | 
|  | 204 | + | 
|  | 205 | +      const result = await queueService.getAll(options) as any; | 
|  | 206 | + | 
|  | 207 | +      // Verify PaginationHelpers.getAll was called with pagination options | 
|  | 208 | +      expect(PaginationHelpers.getAll).toHaveBeenCalledWith( | 
|  | 209 | +        expect.any(Object), | 
|  | 210 | +        expect.objectContaining({ | 
|  | 211 | +          pageSize: TEST_CONSTANTS.PAGE_SIZE | 
|  | 212 | +        }) | 
|  | 213 | +      ); | 
|  | 214 | + | 
|  | 215 | +      expect(result).toEqual(mockResponse); | 
|  | 216 | +      expect(result.hasNextPage).toBe(true); | 
|  | 217 | +      expect(result.nextCursor).toBe(TEST_CONSTANTS.NEXT_CURSOR); | 
|  | 218 | +    }); | 
|  | 219 | + | 
|  | 220 | +    it('should handle API errors', async () => { | 
|  | 221 | +      const error = createMockError(TEST_CONSTANTS.ERROR_MESSAGE); | 
|  | 222 | +      vi.mocked(PaginationHelpers.getAll).mockRejectedValue(error); | 
|  | 223 | + | 
|  | 224 | +      await expect(queueService.getAll()).rejects.toThrow(TEST_CONSTANTS.ERROR_MESSAGE); | 
|  | 225 | +    }); | 
|  | 226 | +  }); | 
|  | 227 | +}); | 
0 commit comments