@@ -3725,6 +3725,139 @@ module.exports['Commands: list handles STATUS NaN values in LSUB response'] = as
37253725 test . done ( ) ;
37263726} ;
37273727
3728+ module . exports [ 'Commands: list STATUS parses UIDVALIDITY UNSEEN HIGHESTMODSEQ' ] = async test => {
3729+ const connection = createMockConnection ( {
3730+ state : 3 ,
3731+ capabilities : new Map ( [
3732+ [ 'LIST-STATUS' , true ] ,
3733+ [ 'CONDSTORE' , true ]
3734+ ] ) ,
3735+ exec : async ( cmd , attrs , opts ) => {
3736+ if ( cmd === 'LIST' ) {
3737+ if ( opts && opts . untagged && opts . untagged . LIST ) {
3738+ await opts . untagged . LIST ( {
3739+ attributes : [ [ { value : '\\HasNoChildren' } ] , { value : '/' } , { value : 'TestFolder' } ]
3740+ } ) ;
3741+ }
3742+ if ( opts && opts . untagged && opts . untagged . STATUS ) {
3743+ await opts . untagged . STATUS ( {
3744+ attributes : [
3745+ { value : 'TestFolder' } ,
3746+ [
3747+ { value : 'UIDVALIDITY' } ,
3748+ { value : '123456789' } ,
3749+ { value : 'UNSEEN' } ,
3750+ { value : '42' } ,
3751+ { value : 'HIGHESTMODSEQ' } ,
3752+ { value : '999999999' }
3753+ ]
3754+ ]
3755+ } ) ;
3756+ }
3757+ }
3758+ return { next : ( ) => { } } ;
3759+ }
3760+ } ) ;
3761+
3762+ const result = await listCommand ( connection , '' , '*' , {
3763+ statusQuery : { uidValidity : true , unseen : true , highestModseq : true }
3764+ } ) ;
3765+ const folder = result . find ( e => e . path === 'TestFolder' ) ;
3766+ test . ok ( folder ) ;
3767+ test . ok ( folder . status ) ;
3768+ test . equal ( folder . status . uidValidity , BigInt ( 123456789 ) ) ;
3769+ test . equal ( folder . status . unseen , 42 ) ;
3770+ test . equal ( folder . status . highestModseq , BigInt ( 999999999 ) ) ;
3771+ test . done ( ) ;
3772+ } ;
3773+
3774+ module . exports [ 'Commands: list LSUB folder not in LIST entries' ] = async test => {
3775+ const connection = createMockConnection ( {
3776+ state : 3 ,
3777+ capabilities : new Map ( [ [ 'SPECIAL-USE' , true ] ] ) ,
3778+ exec : async ( cmd , attrs , opts ) => {
3779+ if ( cmd === 'LIST' && opts && opts . untagged && opts . untagged . LIST ) {
3780+ // Only return INBOX in LIST
3781+ await opts . untagged . LIST ( {
3782+ attributes : [ [ { value : '\\HasNoChildren' } ] , { value : '/' } , { value : 'INBOX' } ]
3783+ } ) ;
3784+ }
3785+ if ( cmd === 'LSUB' && opts && opts . untagged && opts . untagged . LSUB ) {
3786+ // Return a folder in LSUB that wasn't in LIST (hits else branch)
3787+ await opts . untagged . LSUB ( {
3788+ attributes : [ [ { value : '\\HasNoChildren' } ] , { value : '/' } , { value : 'SubscribedOnly' } ]
3789+ } ) ;
3790+ }
3791+ return { next : ( ) => { } } ;
3792+ }
3793+ } ) ;
3794+
3795+ const result = await listCommand ( connection , '' , '*' ) ;
3796+ // The subscribed-only folder should not be in results (else branch ignores it)
3797+ const subscribedOnly = result . find ( e => e . path === 'SubscribedOnly' ) ;
3798+ test . equal ( subscribedOnly , undefined ) ;
3799+ // INBOX should still be there
3800+ const inbox = result . find ( e => e . path === 'INBOX' ) ;
3801+ test . ok ( inbox ) ;
3802+ test . done ( ) ;
3803+ } ;
3804+
3805+ module . exports [ 'Commands: list sort b has specialUse a does not' ] = async test => {
3806+ const connection = createMockConnection ( {
3807+ state : 3 ,
3808+ capabilities : new Map ( [ [ 'SPECIAL-USE' , true ] ] ) ,
3809+ exec : async ( cmd , attrs , opts ) => {
3810+ if ( cmd === 'LIST' && opts && opts . untagged && opts . untagged . LIST ) {
3811+ // First add a folder without special use
3812+ await opts . untagged . LIST ( {
3813+ attributes : [ [ { value : '\\HasNoChildren' } ] , { value : '/' } , { value : 'AAA_Regular' } ]
3814+ } ) ;
3815+ // Then add INBOX which gets special use
3816+ await opts . untagged . LIST ( {
3817+ attributes : [ [ { value : '\\HasNoChildren' } ] , { value : '/' } , { value : 'INBOX' } ]
3818+ } ) ;
3819+ }
3820+ return { next : ( ) => { } } ;
3821+ }
3822+ } ) ;
3823+
3824+ const result = await listCommand ( connection , '' , '*' ) ;
3825+ // When sorting, INBOX has specialUse, AAA_Regular does not
3826+ // So the comparison should hit: !a.specialUse && b.specialUse returns 1
3827+ // This means INBOX should come first even though AAA_Regular is alphabetically first
3828+ test . ok ( result . length >= 2 ) ;
3829+ test . equal ( result [ 0 ] . path , 'INBOX' ) ;
3830+ test . equal ( result [ 0 ] . specialUse , '\\Inbox' ) ;
3831+ test . done ( ) ;
3832+ } ;
3833+
3834+ module . exports [ 'Commands: list sort fallback path comparison' ] = async test => {
3835+ const connection = createMockConnection ( {
3836+ state : 3 ,
3837+ capabilities : new Map ( [ [ 'SPECIAL-USE' , true ] ] ) ,
3838+ exec : async ( cmd , attrs , opts ) => {
3839+ if ( cmd === 'LIST' && opts && opts . untagged && opts . untagged . LIST ) {
3840+ // Create folders where parent parts match but paths differ at the end
3841+ // A/B/C and A/B will have matching parts up to a point
3842+ await opts . untagged . LIST ( {
3843+ attributes : [ [ { value : '\\HasNoChildren' } ] , { value : '/' } , { value : 'Parent/Child/Deep' } ]
3844+ } ) ;
3845+ await opts . untagged . LIST ( {
3846+ attributes : [ [ { value : '\\HasNoChildren' } ] , { value : '/' } , { value : 'Parent/Child' } ]
3847+ } ) ;
3848+ }
3849+ return { next : ( ) => { } } ;
3850+ }
3851+ } ) ;
3852+
3853+ const result = await listCommand ( connection , '' , '*' ) ;
3854+ // Parent/Child should come before Parent/Child/Deep
3855+ const childIndex = result . findIndex ( e => e . path === 'Parent/Child' ) ;
3856+ const deepIndex = result . findIndex ( e => e . path === 'Parent/Child/Deep' ) ;
3857+ test . ok ( childIndex < deepIndex , 'Shorter path should sort before longer when parent matches' ) ;
3858+ test . done ( ) ;
3859+ } ;
3860+
37283861// ============================================
37293862// SELECT Command Tests
37303863// ============================================
0 commit comments