/** * @ai-summary Tests for Community Stations API Client */ import axios from 'axios'; import { communityStationsApi } from '../../api/community-stations.api'; import { SubmitStationData, ReviewDecision } from '../../types/community-stations.types'; jest.mock('axios'); const mockedAxios = axios as jest.Mocked; describe('Community Stations API Client', () => { beforeEach(() => { jest.clearAllMocks(); }); describe('submitStation', () => { it('should submit a station successfully', async () => { const submitData: SubmitStationData = { name: 'Shell Downtown', address: '123 Main St', city: 'Denver', state: 'CO', zipCode: '80202', latitude: 39.7392, longitude: -104.9903, brand: 'Shell', has93Octane: true, has93OctaneEthanolFree: false, price93: 3.599, notes: 'Good quality', }; const mockResponse = { data: { id: '1', ...submitData, status: 'pending', submittedBy: 'user@example.com', createdAt: new Date().toISOString(), updatedAt: new Date().toISOString(), }, }; mockedAxios.post.mockResolvedValueOnce(mockResponse); const result = await communityStationsApi.submitStation(submitData); expect(result).toEqual(mockResponse.data); expect(mockedAxios.post).toHaveBeenCalledWith( '/stations/community/submit', submitData ); }); it('should handle submission errors', async () => { const submitData: SubmitStationData = { name: 'Shell', address: '123 Main St', latitude: 39.7392, longitude: -104.9903, has93Octane: true, has93OctaneEthanolFree: false, }; const mockError = new Error('Network error'); mockedAxios.post.mockRejectedValueOnce(mockError); await expect(communityStationsApi.submitStation(submitData)).rejects.toThrow('Network error'); }); }); describe('getMySubmissions', () => { it('should fetch user submissions', async () => { const mockSubmissions = [ { id: '1', name: 'Shell Downtown', address: '123 Main St', latitude: 39.7392, longitude: -104.9903, has93Octane: true, has93OctaneEthanolFree: false, status: 'pending', submittedBy: 'user@example.com', createdAt: new Date().toISOString(), updatedAt: new Date().toISOString(), }, ]; mockedAxios.get.mockResolvedValueOnce({ data: mockSubmissions }); const result = await communityStationsApi.getMySubmissions(); expect(result).toEqual(mockSubmissions); expect(mockedAxios.get).toHaveBeenCalledWith('/stations/community/mine'); }); }); describe('withdrawSubmission', () => { it('should withdraw a submission', async () => { mockedAxios.delete.mockResolvedValueOnce({ data: null }); await communityStationsApi.withdrawSubmission('1'); expect(mockedAxios.delete).toHaveBeenCalledWith('/stations/community/1'); }); }); describe('getApprovedStations', () => { it('should fetch approved stations with pagination', async () => { const mockResponse = { data: { stations: [ { id: '1', name: 'Shell Downtown', address: '123 Main St', latitude: 39.7392, longitude: -104.9903, has93Octane: true, has93OctaneEthanolFree: false, status: 'approved', submittedBy: 'user@example.com', createdAt: new Date().toISOString(), updatedAt: new Date().toISOString(), }, ], total: 1, page: 0, limit: 50, }, }; mockedAxios.get.mockResolvedValueOnce(mockResponse); const result = await communityStationsApi.getApprovedStations(0, 50); expect(result).toEqual(mockResponse.data); expect(mockedAxios.get).toHaveBeenCalledWith('/stations/community/approved', { params: { page: 0, limit: 50 }, }); }); }); describe('reviewStation (admin)', () => { it('should approve a station', async () => { const decision: ReviewDecision = { status: 'approved' }; const mockResponse = { data: { id: '1', status: 'approved', reviewedAt: new Date().toISOString(), reviewedBy: 'admin@example.com', }, }; mockedAxios.patch.mockResolvedValueOnce(mockResponse); const result = await communityStationsApi.reviewStation('1', decision); expect(result).toEqual(mockResponse.data); expect(mockedAxios.patch).toHaveBeenCalledWith( '/stations/community/admin/1/review', decision ); }); it('should reject a station with reason', async () => { const decision: ReviewDecision = { status: 'rejected', rejectionReason: 'Invalid location', }; const mockResponse = { data: { id: '1', status: 'rejected', rejectionReason: 'Invalid location', reviewedAt: new Date().toISOString(), reviewedBy: 'admin@example.com', }, }; mockedAxios.patch.mockResolvedValueOnce(mockResponse); const result = await communityStationsApi.reviewStation('1', decision); expect(result).toEqual(mockResponse.data); expect(mockedAxios.patch).toHaveBeenCalledWith( '/stations/community/admin/1/review', decision ); }); }); describe('bulkReviewStations (admin)', () => { it('should bulk approve stations', async () => { const ids = ['1', '2', '3']; const decision: ReviewDecision = { status: 'approved' }; const mockResponse = { data: [ { id: '1', status: 'approved' }, { id: '2', status: 'approved' }, { id: '3', status: 'approved' }, ], }; mockedAxios.post.mockResolvedValueOnce(mockResponse); const result = await communityStationsApi.bulkReviewStations(ids, decision); expect(result).toEqual(mockResponse.data); expect(mockedAxios.post).toHaveBeenCalledWith('/stations/community/admin/bulk-review', { ids, ...decision, }); }); }); });