@@ -115,7 +115,7 @@ vi.mock('@/hooks/queries/admin-users', () => ({
115115} ) )
116116
117117import { AddUserModal } from '@/app/workspace/[workspaceId]/settings/components/admin/add-user-modal'
118- import type { AddUserInput , AdminUser } from '@/hooks/queries/admin-users'
118+ import type { AddUserInput , AddUserResult , AdminUser } from '@/hooks/queries/admin-users'
119119
120120const CREATED_USER : AdminUser = {
121121 id : 'user-1' ,
@@ -128,7 +128,7 @@ const CREATED_USER: AdminUser = {
128128
129129let container : HTMLDivElement
130130let root : Root
131- let onCreated : ReturnType < typeof vi . fn < ( user : AdminUser ) => void > >
131+ let onCreated : ReturnType < typeof vi . fn < ( user : AdminUser , resetEmailError ?: string ) => void > >
132132let onOpenChange : ReturnType < typeof vi . fn < ( open : boolean ) => void > >
133133
134134async function renderModal ( ) {
@@ -203,8 +203,8 @@ describe('AddUserModal', () => {
203203
204204 it ( 'creates a verified credential user and returns it to the admin view' , async ( ) => {
205205 mockMutate . mockImplementation (
206- ( _input : AddUserInput , options : { onSuccess : ( user : AdminUser ) => void } ) => {
207- options . onSuccess ( CREATED_USER )
206+ ( _input : AddUserInput , options : { onSuccess : ( result : AddUserResult ) => void } ) => {
207+ options . onSuccess ( { user : CREATED_USER } )
208208 }
209209 )
210210 await renderModal ( )
@@ -226,7 +226,7 @@ describe('AddUserModal', () => {
226226 { onSuccess : expect . any ( Function ) , onSettled : expect . any ( Function ) }
227227 )
228228 expect ( onOpenChange ) . toHaveBeenCalledWith ( false )
229- expect ( onCreated ) . toHaveBeenCalledWith ( CREATED_USER )
229+ expect ( onCreated ) . toHaveBeenCalledWith ( CREATED_USER , undefined )
230230 } )
231231
232232 it ( 'ignores repeated submissions before the pending state renders' , async ( ) => {
@@ -246,8 +246,8 @@ describe('AddUserModal', () => {
246246
247247 it ( 'supports unverified accounts without exposing a platform-role control' , async ( ) => {
248248 mockMutate . mockImplementation (
249- ( _input : AddUserInput , options : { onSuccess : ( user : AdminUser ) => void } ) => {
250- options . onSuccess ( CREATED_USER )
249+ ( _input : AddUserInput , options : { onSuccess : ( result : AddUserResult ) => void } ) => {
250+ options . onSuccess ( { user : CREATED_USER } )
251251 }
252252 )
253253 await renderModal ( )
@@ -269,8 +269,8 @@ describe('AddUserModal', () => {
269269
270270 it ( 'drops the password field and submits without one when emailing a reset link' , async ( ) => {
271271 mockMutate . mockImplementation (
272- ( _input : AddUserInput , options : { onSuccess : ( user : AdminUser ) => void } ) => {
273- options . onSuccess ( CREATED_USER )
272+ ( _input : AddUserInput , options : { onSuccess : ( result : AddUserResult ) => void } ) => {
273+ options . onSuccess ( { user : CREATED_USER } )
274274 }
275275 )
276276 await renderModal ( )
@@ -295,7 +295,7 @@ describe('AddUserModal', () => {
295295 } ,
296296 { onSuccess : expect . any ( Function ) , onSettled : expect . any ( Function ) }
297297 )
298- expect ( onCreated ) . toHaveBeenCalledWith ( CREATED_USER )
298+ expect ( onCreated ) . toHaveBeenCalledWith ( CREATED_USER , undefined )
299299 } )
300300
301301 it ( 'keeps a typed password across a round trip through the reset-link flow' , async ( ) => {
@@ -308,6 +308,30 @@ describe('AddUserModal', () => {
308308 expect ( buttonLabelled ( 'Add user' ) . disabled ) . toBe ( false )
309309 } )
310310
311+ it ( 'still hands the user back when only its reset email failed' , async ( ) => {
312+ mockMutate . mockImplementation (
313+ ( _input : AddUserInput , options : { onSuccess : ( result : AddUserResult ) => void } ) => {
314+ options . onSuccess ( { user : CREATED_USER , resetEmailError : 'SMTP unavailable' } )
315+ }
316+ )
317+ await renderModal ( )
318+ await changeField ( 'Name' , 'Canary Writer' )
319+ await changeField ( 'Email' , 'writer@synthetics.example.com' )
320+ await changeField ( 'Credentials' , 'email' )
321+
322+ await act ( async ( ) => {
323+ buttonLabelled ( 'Add user' ) . dispatchEvent ( new MouseEvent ( 'click' , { bubbles : true } ) )
324+ await Promise . resolve ( )
325+ await Promise . resolve ( )
326+ } )
327+
328+ // The account exists, so this closes like any other create — the host
329+ // surfaces the user (and the reason) rather than stranding the operator in
330+ // a modal whose form no longer maps to anything.
331+ expect ( onOpenChange ) . toHaveBeenCalledWith ( false )
332+ expect ( onCreated ) . toHaveBeenCalledWith ( CREATED_USER , 'SMTP unavailable' )
333+ } )
334+
311335 it ( 'shows Better Auth failures without closing the modal' , async ( ) => {
312336 addUserMutation . current = {
313337 isPending : false ,
0 commit comments