@@ -4,7 +4,7 @@ import type { DatabaseType, DatabaseConfig, ModuleOptions } from '../src/types'
44import { cleanupTestSetup , createTestSetup } from './test-setup'
55import { createUsersTable } from '../src/runtime/server/utils/create-users-table'
66import { createPersonalAccessTokensTable } from '../src/runtime/server/utils/create-personal-access-tokens-table'
7- import { createUser , findUserByEmail , updateUser , updateUserPassword , getLastLoginTime , getCurrentUserFromToken } from '../src/runtime/server/utils/user'
7+ import { createUser , findUserByEmail , findUserById , deleteUser , updateUser , updateUserPassword , getLastLoginTime , getCurrentUserFromToken } from '../src/runtime/server/utils/user'
88import { addActiveToUsers } from '../src/runtime/server/utils/add-active-to-users'
99
1010describe ( 'User Utilities (src/utils/user.ts)' , ( ) => {
@@ -181,6 +181,74 @@ describe('User Utilities (src/utils/user.ts)', () => {
181181 } )
182182 } )
183183
184+ describe ( 'deleteUser' , ( ) => {
185+ it ( 'should soft delete user by default (set active to false)' , async ( ) => {
186+ const userData = { email : 'softdelete@example.com' , name : 'Soft Delete User' , password : 'password123' }
187+ const user = await createUser ( userData , testOptions )
188+
189+ // Verify user is active initially (SQLite may return 1 instead of true)
190+ expect ( user . active ) . toBeTruthy ( )
191+
192+ // Delete user (should be soft delete by default)
193+ await deleteUser ( user . id , testOptions )
194+
195+ // Verify user still exists but is inactive
196+ const deletedUser = await findUserById ( user . id , testOptions )
197+ expect ( deletedUser ) . not . toBeNull ( )
198+ expect ( deletedUser ?. active ) . toBeFalsy ( )
199+
200+ // Verify user still exists in database
201+ const result = await db . sql `SELECT * FROM {${ testOptions . tables . users } } WHERE id = ${ user . id } `
202+ expect ( result . rows ?. length ) . toBe ( 1 )
203+ } )
204+
205+ it ( 'should hard delete user when hardDelete option is true' , async ( ) => {
206+ const userData = { email : 'harddelete@example.com' , name : 'Hard Delete User' , password : 'password123' }
207+ const user = await createUser ( userData , testOptions )
208+
209+ // Set hardDelete option
210+ const hardDeleteOptions = { ...testOptions , hardDelete : true }
211+
212+ // Delete user with hard delete
213+ await deleteUser ( user . id , hardDeleteOptions )
214+
215+ // Verify user no longer exists
216+ const deletedUser = await findUserById ( user . id , testOptions )
217+ expect ( deletedUser ) . toBeNull ( )
218+
219+ // Verify user is removed from database
220+ const result = await db . sql `SELECT * FROM {${ testOptions . tables . users } } WHERE id = ${ user . id } `
221+ expect ( result . rows ?. length ) . toBe ( 0 )
222+ } )
223+
224+ it ( 'should throw error when trying to delete non-existent user' , async ( ) => {
225+ await expect ( deleteUser ( 999 , testOptions ) ) . rejects . toThrow ( 'User not found.' )
226+ } )
227+
228+ it ( 'should revoke user tokens on both soft and hard delete' , async ( ) => {
229+ const userData = { email : 'tokenrevoke@example.com' , name : 'Token Revoke User' , password : 'password123' }
230+ const user = await createUser ( userData , testOptions )
231+
232+ // Create a token for the user
233+ await db . sql `
234+ INSERT INTO {${ testOptions . tables . personalAccessTokens } }
235+ (tokenable_type, tokenable_id, name, token, created_at, updated_at)
236+ VALUES ('user', ${ user . id } , 'test-token', 'abc123', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)
237+ `
238+
239+ // Verify token exists
240+ let tokenResult = await db . sql `SELECT * FROM {${ testOptions . tables . personalAccessTokens } } WHERE tokenable_id = ${ user . id } `
241+ expect ( tokenResult . rows ?. length ) . toBe ( 1 )
242+
243+ // Soft delete user
244+ await deleteUser ( user . id , testOptions )
245+
246+ // Verify tokens are revoked
247+ tokenResult = await db . sql `SELECT * FROM {${ testOptions . tables . personalAccessTokens } } WHERE tokenable_id = ${ user . id } `
248+ expect ( tokenResult . rows ?. length ) . toBe ( 0 )
249+ } )
250+ } )
251+
184252 describe ( 'Integration tests' , ( ) => {
185253 it ( 'should work together: create user, find user, update password' , async ( ) => {
186254 const userData = { email : 'integration@webmania.cc' , name : 'Integration User' , password : 'initialpassword' }
0 commit comments