import {deleteMe} from 'api/delete-me' import {AuthedUser} from 'api/helpers/endpoint' import {sqlMatch} from 'common/test-utils' import * as firebaseAdmin from 'firebase-admin' import * as firebaseUtils from 'shared/firebase-utils' import * as supabaseInit from 'shared/supabase/init' import * as sharedUtils from 'shared/utils' jest.mock('shared/supabase/init') jest.mock('shared/utils') jest.mock('firebase-admin', () => ({ auth: jest.fn(), })) jest.mock('shared/firebase-utils') describe('deleteMe', () => { let mockPg = {} as any beforeEach(() => { jest.resetAllMocks() mockPg = { none: jest.fn(), } ;(supabaseInit.createSupabaseDirectClient as jest.Mock).mockReturnValue(mockPg) }) afterEach(() => { jest.restoreAllMocks() }) describe('when given valid input', () => { it('should delete the user account from supabase and firebase', async () => { const mockUser = { id: 'mockId', username: 'mockUsername', } const mockAuth = {uid: '321'} as AuthedUser const mockRef = { reasonCategory: 'someReasonCategory', reasonDetails: 'someReasonDetails', } as any const mockDeleteUser = jest.fn().mockResolvedValue(null) ;(sharedUtils.getUser as jest.Mock).mockResolvedValue(mockUser) ;(mockPg.none as jest.Mock).mockResolvedValue(null) ;(firebaseUtils.deleteUserFiles as jest.Mock).mockResolvedValue(null) ;(firebaseAdmin.auth as jest.Mock).mockReturnValue({ deleteUser: mockDeleteUser, }) const debugSpy = jest.spyOn(console, 'debug').mockImplementation(() => {}) await deleteMe(mockRef, mockAuth, mockRef) expect(sharedUtils.getUser).toBeCalledTimes(1) expect(sharedUtils.getUser).toBeCalledWith(mockAuth.uid) expect(mockPg.none).toBeCalledTimes(2) expect(mockPg.none).toHaveBeenNthCalledWith( 1, sqlMatch('INSERT INTO deleted_users (username, reason_category, reason_details)'), [mockUser.username, mockRef.reasonCategory, mockRef.reasonDetails], ) expect(mockPg.none).toHaveBeenNthCalledWith(2, sqlMatch('DELETE FROM users WHERE id = $1'), [ mockUser.id, ]) expect(firebaseUtils.deleteUserFiles).toBeCalledTimes(1) expect(firebaseUtils.deleteUserFiles).toBeCalledWith(mockUser.username) expect(mockDeleteUser).toBeCalledTimes(1) expect(mockDeleteUser).toBeCalledWith(mockUser.id) expect(debugSpy).toBeCalledWith(expect.stringContaining(mockUser.id)) }) }) describe('when an error occurs', () => { it('should throw if the user account was not found', async () => { const _mockUser = { id: 'mockId', username: 'mockUsername', } const mockAuth = {uid: '321'} as AuthedUser const mockRef = {} as any ;(sharedUtils.getUser as jest.Mock).mockResolvedValue(null) expect(deleteMe(mockRef, mockAuth, mockRef)).rejects.toThrow('Your account was not found') }) it('should throw an error if there is no userId', async () => { const mockUser = { username: 'mockUsername', } const mockAuth = {uid: '321'} as AuthedUser const mockRef = {} as any ;(sharedUtils.getUser as jest.Mock).mockResolvedValue(mockUser) expect(deleteMe(mockRef, mockAuth, mockRef)).rejects.toThrow('Invalid user ID') }) it('should throw if unable to remove user from firebase auth', async () => { const mockUser = { id: 'mockId', username: 'mockUsername', } const mockAuth = {uid: '321'} as AuthedUser const mockRef = {} as any const mockDeleteUser = jest.fn().mockRejectedValue(new Error('Error during deletion')) ;(sharedUtils.getUser as jest.Mock).mockResolvedValue(mockUser) ;(mockPg.none as jest.Mock).mockResolvedValue(null) ;(firebaseUtils.deleteUserFiles as jest.Mock).mockResolvedValue(null) ;(firebaseAdmin.auth as jest.Mock).mockReturnValue({ deleteUser: mockDeleteUser, }) const errorSpy = jest.spyOn(console, 'error').mockImplementation(() => {}) await deleteMe(mockRef, mockAuth, mockRef) expect(errorSpy).toBeCalledWith( expect.stringContaining('Error deleting user from Firebase Auth:'), expect.any(Error), ) }) }) })