@@ -526,4 +526,34 @@ describe('keycloakService', () => {
526526 expect ( keycloak . removeUserFromGroup ) . toHaveBeenCalledWith ( 'user-2' , 'system-managed-id' )
527527 } )
528528 } )
529+
530+ describe ( 'migration parity: admin-role event path (legacy hook.adminRole.*)' , ( ) => {
531+ const adminRoles : AdminRoleWithDetails [ ] = [
532+ { id : 'admin-role-1' , name : 'admin' , permissions : 0n , position : 0 , oidcGroup : '/admin-group' , type : 'managed' } ,
533+ ]
534+ const users : UserWithAdminRoles [ ] = [
535+ { id : 'user-1' , adminRoleIds : [ 'admin-role-1' ] } ,
536+ ]
537+
538+ it ( 'syncs admin-role OIDC groups via cron reconcile ONLY (no event path exists)' , async ( ) => {
539+ datastore . getAllProjects . mockResolvedValue ( [ ] )
540+ datastore . getAllAdminRoles . mockResolvedValue ( adminRoles )
541+ datastore . getAllUsersWithAdminRoleIds . mockResolvedValue ( users )
542+
543+ const adminGroup = makeGroupRepresentation ( { id : 'kc-parity-group-id' , name : 'admin' , path : '/console/parity-admin' } )
544+ keycloak . getOrCreateGroupByPath . mockResolvedValue ( adminGroup )
545+ keycloak . getGroupMembers . mockResolvedValue ( [ ] )
546+
547+ await service . handleCron ( )
548+
549+ expect ( keycloak . getOrCreateGroupByPath ) . toHaveBeenCalledWith ( '/admin-group' )
550+ expect ( keycloak . addUserToGroup ) . toHaveBeenCalledWith ( 'user-1' , 'kc-parity-group-id' )
551+ } )
552+
553+ it ( 'exposes NO adminRole emit entrypoint on AppEventsService (cutover guard)' , async ( ) => {
554+ const { AppEventsService } = await import ( '../events/app-events.service' )
555+ expect ( Object . getOwnPropertyNames ( AppEventsService . prototype ) )
556+ . not . toContain ( 'emitAdminRoleEvent' )
557+ } )
558+ } )
529559} )
0 commit comments