@@ -26,6 +26,7 @@ const mockPolicies = ref<Record<string, unknown>>({})
2626type SettingsVm = {
2727 getAdminRoute : ( ) => string
2828 isAdmin : boolean
29+ canManagePreferences : boolean
2930}
3031
3132type SettingsWrapper = VueWrapper < SettingsVm >
@@ -102,7 +103,11 @@ describe('Settings', () => {
102103 const createWrapper = (
103104 isAdmin = false ,
104105 canManagePolicies = false ,
105- effectivePolicies : Record < string , unknown > = { } ,
106+ effectivePolicies : Record < string , unknown > = {
107+ signature_flow : {
108+ canSaveAsUserDefault : true ,
109+ } ,
110+ } ,
106111 ) : SettingsWrapper => {
107112 const user = { isAdmin } as ReturnType < typeof auth . getCurrentUser >
108113 getCurrentUserMock . mockReturnValue ( user )
@@ -335,7 +340,7 @@ describe('Settings', () => {
335340 const items = getItems ( )
336341
337342 // Account + Preferences + Rate = 3
338- expect ( items . length ) . toBe ( 3 )
343+ expect ( items . length ) . toBe ( 2 )
339344 } )
340345 } )
341346
@@ -357,7 +362,7 @@ describe('Settings', () => {
357362 } )
358363 } )
359364
360- describe ( 'RULE: Preferences item is always available inside the app ' , ( ) => {
365+ describe ( 'RULE: Preferences item follows personal preference capability ' , ( ) => {
361366 it ( 'shows Preferences for non-admin users' , ( ) => {
362367 wrapper = createWrapper ( false )
363368 const items = getItems ( )
@@ -379,6 +384,36 @@ describe('Settings', () => {
379384
380385 expect ( getWrapper ( ) . find ( '.preferences-icon' ) . exists ( ) ) . toBe ( true )
381386 } )
387+
388+ it ( 'hides Preferences when the user cannot save a personal preference' , ( ) => {
389+ wrapper = createWrapper ( false , false , {
390+ signature_flow : {
391+ canSaveAsUserDefault : false ,
392+ } ,
393+ } )
394+ const items = getItems ( )
395+
396+ expect ( findItemByName ( items , 'Preferences' ) ) . toBeUndefined ( )
397+ } )
398+
399+ it ( 'updates Preferences visibility after policy state changes' , async ( ) => {
400+ wrapper = createWrapper ( false , false , {
401+ signature_flow : {
402+ canSaveAsUserDefault : false ,
403+ } ,
404+ } )
405+ expect ( findItemByName ( getItems ( ) , 'Preferences' ) ) . toBeUndefined ( )
406+
407+ mockPolicies . value = {
408+ signature_flow : {
409+ canSaveAsUserDefault : true ,
410+ } ,
411+ }
412+ await nextTick ( )
413+
414+ const preferencesItem = expectItem ( findItemByName ( getItems ( ) , 'Preferences' ) )
415+ expect ( preferencesItem . props ( 'to' ) ) . toEqual ( { name : 'Preferences' } )
416+ } )
382417 } )
383418
384419 describe ( 'RULE: Policies item follows policy-management capability in the app menu' , ( ) => {
@@ -646,9 +681,27 @@ describe('Settings', () => {
646681 expect ( hasAdmin ) . toBe ( false )
647682 } )
648683
684+ it ( 'hides preferences entry when the user cannot change anything personally' , ( ) => {
685+ wrapper = createWrapper ( false , false , {
686+ signature_flow : {
687+ canSaveAsUserDefault : false ,
688+ } ,
689+ } )
690+ const items = getItems ( )
691+
692+ expect ( items ) . toHaveLength ( 2 )
693+
694+ const hasPreferences = items . some ( i => i . props ( 'name' ) ?. includes ( 'Preferences' ) )
695+ const hasPolicies = items . some ( i => i . props ( 'name' ) ?. includes ( 'Policies' ) )
696+
697+ expect ( hasPreferences ) . toBe ( false )
698+ expect ( hasPolicies ) . toBe ( false )
699+ } )
700+
649701 it ( 'shows policies entry for group manager with editable policies' , ( ) => {
650702 wrapper = createWrapper ( false , true , {
651703 signature_flow : {
704+ canSaveAsUserDefault : true ,
652705 editableByCurrentActor : true ,
653706 groupCount : 1 ,
654707 userCount : 0 ,
0 commit comments