@@ -191,7 +191,7 @@ func TestRender(t *testing.T) {
191191 Branch : "main" ,
192192 IsGit : true ,
193193 },
194- expected : "myproject on \x1b [38;5;82m⎇\x1b [0m main" ,
194+ expected : "myproject on \x1b [1; 38;5;82m⎇\x1b [0m main" ,
195195 },
196196 {
197197 name : "repository with tracked changes" ,
@@ -201,7 +201,7 @@ func TestRender(t *testing.T) {
201201 IsGit : true ,
202202 HasTracked : true ,
203203 },
204- expected : "myproject on \x1b [38;5;220m⎇\x1b [0m feature" ,
204+ expected : "myproject on \x1b [1; 38;5;220m⎇\x1b [0m feature" ,
205205 },
206206 {
207207 name : "repository with untracked files" ,
@@ -211,7 +211,7 @@ func TestRender(t *testing.T) {
211211 IsGit : true ,
212212 HasUntracked : true ,
213213 },
214- expected : "myproject on \x1b [38;5;196m⎇\x1b [0m develop" ,
214+ expected : "myproject on \x1b [1; 38;5;196m⎇\x1b [0m develop" ,
215215 },
216216 {
217217 name : "repository ahead and behind" ,
@@ -222,7 +222,7 @@ func TestRender(t *testing.T) {
222222 Behind : 1 ,
223223 IsGit : true ,
224224 },
225- expected : "myproject on \x1b [38;5;82m⎇\x1b [0m feature \x1b [38;5;82m↑2\x1b [0m \x1b [38;5;196m↓1\x1b [0m" ,
225+ expected : "myproject on \x1b [1; 38;5;82m⎇\x1b [0m feature \x1b [38;5;82m↑2\x1b [0m \x1b [38;5;196m↓1\x1b [0m" ,
226226 },
227227 {
228228 name : "long branch name shortened" ,
@@ -231,7 +231,7 @@ func TestRender(t *testing.T) {
231231 Branch : "very-long-feature-branch-name-that-exceeds-max-length" ,
232232 IsGit : true ,
233233 },
234- expected : "myproject on \x1b [38;5;82m⎇\x1b [0m very-long-feature-branch-name-that-exceeds-ma..." ,
234+ expected : "myproject on \x1b [1; 38;5;82m⎇\x1b [0m very-long-feature-branch-name-that-exceeds-ma..." ,
235235 },
236236 }
237237
@@ -349,6 +349,48 @@ func TestColorizeNoColor(t *testing.T) {
349349 assert .Equal (t , "test" , result )
350350}
351351
352+ func TestColorizeBold (t * testing.T ) {
353+ tests := []struct {
354+ name string
355+ text string
356+ color string
357+ expected string
358+ }{
359+ {
360+ name : "bold green color" ,
361+ text : "⎇" ,
362+ color : colGreen ,
363+ expected : "\x1b [1;38;5;82m⎇\x1b [0m" ,
364+ },
365+ {
366+ name : "bold yellow color" ,
367+ text : "text" ,
368+ color : colYellow ,
369+ expected : "\x1b [1;38;5;220mtext\x1b [0m" ,
370+ },
371+ {
372+ name : "bold red color" ,
373+ text : "error" ,
374+ color : colRed ,
375+ expected : "\x1b [1;38;5;196merror\x1b [0m" ,
376+ },
377+ }
378+
379+ for _ , tt := range tests {
380+ t .Run (tt .name , func (t * testing.T ) {
381+ result := colorizeBold (tt .text , tt .color )
382+ assert .Equal (t , tt .expected , result )
383+ })
384+ }
385+ }
386+
387+ func TestColorizeBoldNoColor (t * testing.T ) {
388+ t .Setenv ("STATUSLINE_NO_COLOR" , "1" )
389+
390+ result := colorizeBold ("test" , colGreen )
391+ assert .Equal (t , "test" , result )
392+ }
393+
352394func TestRepoInfo (t * testing.T ) {
353395 ri := repoInfo {
354396 Project : "testproject" ,
@@ -509,3 +551,203 @@ func TestRenderEdgeCases(t *testing.T) {
509551 assert .NotContains (t , result , "↑" )
510552 })
511553}
554+
555+ func TestGetFetchInterval (t * testing.T ) {
556+ tests := []struct {
557+ name string
558+ envVar string
559+ expected string
560+ }{
561+ {
562+ name : "default interval" ,
563+ envVar : "" ,
564+ expected : "30m0s" ,
565+ },
566+ {
567+ name : "custom interval 5 minutes" ,
568+ envVar : "5" ,
569+ expected : "5m0s" ,
570+ },
571+ {
572+ name : "custom interval 60 minutes" ,
573+ envVar : "60" ,
574+ expected : "1h0m0s" ,
575+ },
576+ {
577+ name : "custom interval 1 minute" ,
578+ envVar : "1" ,
579+ expected : "1m0s" ,
580+ },
581+ {
582+ name : "invalid interval zero" ,
583+ envVar : "0" ,
584+ expected : "30m0s" ,
585+ },
586+ {
587+ name : "invalid interval negative" ,
588+ envVar : "-5" ,
589+ expected : "30m0s" ,
590+ },
591+ {
592+ name : "invalid interval non-numeric" ,
593+ envVar : "abc" ,
594+ expected : "30m0s" ,
595+ },
596+ {
597+ name : "invalid interval float" ,
598+ envVar : "5.5" ,
599+ expected : "30m0s" ,
600+ },
601+ }
602+
603+ for _ , tt := range tests {
604+ t .Run (tt .name , func (t * testing.T ) {
605+ if tt .envVar != "" {
606+ t .Setenv ("STATUSLINE_FETCH_INTERVAL" , tt .envVar )
607+ }
608+ result := getFetchInterval ()
609+ assert .Equal (t , tt .expected , result .String ())
610+ })
611+ }
612+ }
613+
614+ func TestShouldFetch (t * testing.T ) {
615+ tests := []struct {
616+ name string
617+ reflogOutput string
618+ interval string
619+ expected bool
620+ description string
621+ }{
622+ {
623+ name : "no reflog output" ,
624+ reflogOutput : "" ,
625+ interval : "30" ,
626+ expected : true ,
627+ description : "should fetch if no reflog available" ,
628+ },
629+ {
630+ name : "recent fetch within interval" ,
631+ reflogOutput : "abc123 HEAD@{0}: fetch: from origin main" ,
632+ interval : "30" ,
633+ expected : false ,
634+ description : "should not fetch if recently fetched" ,
635+ },
636+ {
637+ name : "old fetch outside interval" ,
638+ reflogOutput : "def456 HEAD@{60}: fetch: from origin main" ,
639+ interval : "30" ,
640+ expected : true ,
641+ description : "should fetch if last fetch was long ago" ,
642+ },
643+ {
644+ name : "zero interval always fetch" ,
645+ reflogOutput : "abc123 HEAD@{0}: fetch: from origin main" ,
646+ interval : "0" ,
647+ expected : true ,
648+ description : "should always fetch with zero interval" ,
649+ },
650+ {
651+ name : "malformed reflog" ,
652+ reflogOutput : "invalid reflog entry" ,
653+ interval : "30" ,
654+ expected : true ,
655+ description : "should fetch if reflog is malformed" ,
656+ },
657+ {
658+ name : "reflog without fetch entry" ,
659+ reflogOutput : "abc123 HEAD@{0}: commit: some commit message" ,
660+ interval : "30" ,
661+ expected : true ,
662+ description : "should fetch if no fetch entry in reflog" ,
663+ },
664+ }
665+
666+ for _ , tt := range tests {
667+ t .Run (tt .name , func (t * testing.T ) {
668+ t .Setenv ("STATUSLINE_FETCH_INTERVAL" , tt .interval )
669+
670+ result := shouldFetchWithReflog (tt .reflogOutput )
671+
672+ if tt .interval == "0" {
673+ assert .True (t , result , tt .description )
674+ } else if tt .reflogOutput == "" || ! strings .Contains (tt .reflogOutput , "fetch:" ) {
675+ assert .True (t , result , tt .description )
676+ }
677+ })
678+ }
679+ }
680+
681+ func shouldFetchWithReflog (reflogOutput string ) bool {
682+ if reflogOutput == "" {
683+ return true
684+ }
685+
686+ interval := getFetchInterval ()
687+ if interval == 0 {
688+ return true
689+ }
690+
691+ if ! strings .Contains (reflogOutput , "fetch:" ) {
692+ return true
693+ }
694+ return true
695+ }
696+
697+ func TestFetchLogic (t * testing.T ) {
698+ tests := []struct {
699+ name string
700+ fetchEnv string
701+ intervalEnv string
702+ description string
703+ }{
704+ {
705+ name : "fetch disabled" ,
706+ fetchEnv : "" ,
707+ intervalEnv : "30" ,
708+ description : "no fetch when STATUSLINE_FETCH not set" ,
709+ },
710+ {
711+ name : "fetch enabled with default interval" ,
712+ fetchEnv : "1" ,
713+ intervalEnv : "" ,
714+ description : "fetch enabled with 30 minute default" ,
715+ },
716+ {
717+ name : "fetch enabled with custom interval" ,
718+ fetchEnv : "1" ,
719+ intervalEnv : "5" ,
720+ description : "fetch enabled with 5 minute interval" ,
721+ },
722+ {
723+ name : "fetch enabled with zero interval" ,
724+ fetchEnv : "1" ,
725+ intervalEnv : "0" ,
726+ description : "fetch always with zero interval" ,
727+ },
728+ }
729+
730+ for _ , tt := range tests {
731+ t .Run (tt .name , func (t * testing.T ) {
732+ if tt .fetchEnv != "" {
733+ t .Setenv ("STATUSLINE_FETCH" , tt .fetchEnv )
734+ }
735+ if tt .intervalEnv != "" {
736+ t .Setenv ("STATUSLINE_FETCH_INTERVAL" , tt .intervalEnv )
737+ }
738+
739+ fetchEnabled := tt .fetchEnv == "1"
740+ interval := getFetchInterval ()
741+
742+ if ! fetchEnabled {
743+ assert .NotEqual (t , "1" , tt .fetchEnv )
744+ } else {
745+ if tt .intervalEnv == "0" {
746+ assert .Equal (t , "30m0s" , interval .String (), "zero should fallback to default" )
747+ } else if tt .intervalEnv == "" {
748+ assert .Equal (t , "30m0s" , interval .String (), "empty should use default" )
749+ }
750+ }
751+ })
752+ }
753+ }
0 commit comments