Files
Compass/backend/api/tests/unit/delete-me.unit.test.ts
2026-02-22 18:20:15 +01:00

123 lines
4.2 KiB
TypeScript

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),
)
})
})
})