@@ -264,6 +264,51 @@ public void Search_ProvidesLocalizationKeyForMatchReason()
264264 Assert . AreEqual ( "Matched author" , results [ 0 ] . MatchReason ) ;
265265 }
266266
267+ [ TestMethod ]
268+ public void Search_MatchesPersonalAliasAndNotes ( )
269+ {
270+ var documents = new [ ]
271+ {
272+ new ModSearchDocument ( "Example.Mod" , "Example Mod" )
273+ {
274+ Alias = "Daily run helper" ,
275+ Notes = "Disable before multiplayer"
276+ }
277+ } ;
278+
279+ var aliasResults = ModSearchRules . Search ( documents , "Daily run helper" ) ;
280+ var noteResults = ModSearchRules . Search ( documents , "multiplayer" ) ;
281+
282+ Assert . AreEqual ( BmmText . SearchMatchAlias , aliasResults [ 0 ] . MatchReasonKey ) ;
283+ Assert . AreEqual ( BmmText . SearchMatchNotes , noteResults [ 0 ] . MatchReasonKey ) ;
284+ }
285+
286+ [ TestMethod ]
287+ public void ModAnnotations_NormalizeWhitespaceAndDiscardEmptyEntries ( )
288+ {
289+ var annotations = ModAnnotationRules . NormalizeDictionary ( new Dictionary < string , ModAnnotation >
290+ {
291+ [ " Example.Mod " ] = new ( ) { Alias = " Helper " , Notes = "line one\r \n line two " } ,
292+ [ "Empty.Mod" ] = new ( )
293+ } ) ;
294+
295+ Assert . AreEqual ( 1 , annotations . Count ) ;
296+ Assert . AreEqual ( "Helper" , annotations [ "Example.Mod" ] . Alias ) ;
297+ Assert . AreEqual ( "line one\n line two" , annotations [ "Example.Mod" ] . Notes ) ;
298+ }
299+
300+ [ TestMethod ]
301+ public void ModAnnotations_LoadNormalizationPreservesFutureOrManuallyEditedLengths ( )
302+ {
303+ string longNotes = new ( 'x' , ModAnnotationRules . MaxNotesLength + 1 ) ;
304+ var annotations = ModAnnotationRules . NormalizeDictionary ( new Dictionary < string , ModAnnotation >
305+ {
306+ [ "Example.Mod" ] = new ( ) { Notes = longNotes }
307+ } ) ;
308+
309+ Assert . AreEqual ( longNotes , annotations [ "Example.Mod" ] . Notes ) ;
310+ }
311+
267312 [ TestMethod ]
268313 public void Search_ToleratesTyposAndLookalikesForLongQueries ( )
269314 {
@@ -509,6 +554,14 @@ public void GetTopBarPresentation_UsesIconOnlyActions()
509554 Assert . AreEqual ( ModdingScreenConstants . TopBarButtonCompactWidth , wide . ButtonWidth ) ;
510555 }
511556
557+ [ TestMethod ]
558+ public void ShouldStackTopBar_UsesAvailableLocalizedTitleSpace ( )
559+ {
560+ Assert . IsTrue ( ModdingScreenLayoutRules . ShouldStackTopBar ( 0f , 275f ) ) ;
561+ Assert . IsTrue ( ModdingScreenLayoutRules . ShouldStackTopBar ( 274f , 275f ) ) ;
562+ Assert . IsFalse ( ModdingScreenLayoutRules . ShouldStackTopBar ( 275f , 275f ) ) ;
563+ }
564+
512565 [ TestMethod ]
513566 public void ShouldShowRowMoveButtons_PreservesGroupPickerOnNarrowRows ( )
514567 {
@@ -775,7 +828,11 @@ public void ProfileSaveStorage_RoundTripsCurrentSaveData()
775828 CurrentProfileIndex = 0 ,
776829 CustomGroups = new List < string > { "Bosses" } ,
777830 ModGroups = new Dictionary < string , string > { [ "mod-a" ] = "Bosses" } ,
778- CollapsedGroups = new HashSet < string > { "Bosses" }
831+ CollapsedGroups = new HashSet < string > { "Bosses" } ,
832+ ModAnnotations = new Dictionary < string , ModAnnotation >
833+ {
834+ [ "mod-a" ] = new ( ) { Alias = "My boss mod" , Notes = "Load after BaseLib" }
835+ }
779836 } ;
780837
781838 bool wrote = ProfileSaveStorage . TryWrite ( savePath , saveData , _ => { } , out string ? error ) ;
@@ -787,6 +844,8 @@ public void ProfileSaveStorage_RoundTripsCurrentSaveData()
787844 Assert . AreEqual ( "Bosses" , loaded . CustomGroups [ 0 ] ) ;
788845 Assert . AreEqual ( "Bosses" , loaded . ModGroups [ "mod-a" ] ) ;
789846 Assert . IsTrue ( loaded . CollapsedGroups . Contains ( "Bosses" ) ) ;
847+ Assert . AreEqual ( "My boss mod" , loaded . ModAnnotations [ "mod-a" ] . Alias ) ;
848+ Assert . AreEqual ( "Load after BaseLib" , loaded . ModAnnotations [ "mod-a" ] . Notes ) ;
790849 }
791850 finally
792851 {
@@ -1020,8 +1079,8 @@ public void BuildCsv_EscapesExcelFriendlyModExportRows()
10201079 } ) ;
10211080
10221081 string expected = string . Join ( Environment . NewLine ,
1023- "Mod Id,Name,Version,Enabled,Group,Workshop Link" ,
1024- "Example.Mod,\" Example, Mod\" ,1.2.3,TRUE,\" QoL \" \" Core\" \" \" ," ,
1082+ "Mod Id,Name,Version,Enabled,Group,Workshop Link,Alias,Notes " ,
1083+ "Example.Mod,\" Example, Mod\" ,1.2.3,TRUE,\" QoL \" \" Core\" \" \" ,,, " ,
10251084 string . Empty ) ;
10261085
10271086 Assert . AreEqual ( expected , csv ) ;
@@ -1084,7 +1143,11 @@ public void BuildRows_UsesManifestInfoAndAssignedGroups()
10841143 }
10851144 } ,
10861145 new Dictionary < string , string > { [ "Example.Mod" ] = "Core" } ,
1087- "Unassigned" ) ;
1146+ "Unassigned" ,
1147+ new Dictionary < string , ModAnnotation >
1148+ {
1149+ [ "Example.Mod" ] = new ( ) { Alias = "My helper" , Notes = "Keep enabled" }
1150+ } ) ;
10881151
10891152 Assert . AreEqual ( 1 , rows . Count ) ;
10901153 Assert . AreEqual ( "Example.Mod" , rows [ 0 ] . ModId ) ;
@@ -1093,6 +1156,8 @@ public void BuildRows_UsesManifestInfoAndAssignedGroups()
10931156 Assert . IsFalse ( rows [ 0 ] . Enabled ) ;
10941157 Assert . AreEqual ( "Core" , rows [ 0 ] . Group ) ;
10951158 Assert . AreEqual ( "https://steamcommunity.com/sharedfiles/filedetails/?id=3456789012" , rows [ 0 ] . WorkshopUrl ) ;
1159+ Assert . AreEqual ( "My helper" , rows [ 0 ] . Alias ) ;
1160+ Assert . AreEqual ( "Keep enabled" , rows [ 0 ] . Notes ) ;
10961161 }
10971162 finally
10981163 {
0 commit comments