okami.mom/albedo
git clone https://git.nkp.pet/okami.mom/albedo
8e3e173
main
1package tui 2 3import ( 4"albedo/cli/internal/daemon" 5"strings" 6"testing" 7 8 tea"charm.land/bubbletea/v2" 9"github.com/charmbracelet/x/ansi" 10) 11 12func dispatchCmd (app * AppModel ,cmd tea.Cmd )* AppModel { 13if cmd == nil { 14return app 15 } 16msg := cmd () 17if batch ,ok := msg .(tea.BatchMsg );ok { 18for _ ,sub := range batch { 19if sub != nil { 20app = dispatchCmd (app ,sub ) 21 } 22 } 23return app 24 } 25if msg != nil { 26updated ,next := app .Update (msg ) 27app = updated .(* AppModel ) 28if next != nil { 29app = dispatchCmd (app ,next ) 30 } 31 } 32return app 33} 34 35func newTestApp (t * testing.T )* AppModel { 36t .Helper () 37conn := daemon .NewConnection (daemon.ConnectionSnapshot {Port :1 },nil ) 38session := & daemon.Session {ID :"test-session" ,Model :"test-model" } 39app := NewAppModel (conn ,Bootstrap {},session ,"" ,false ,nil ) 40t .Cleanup (app .Chat .Close ) 41app .Update (tea.WindowSizeMsg {Width :100 ,Height :30 }) 42return app 43} 44 45func TestQuotaRouteFromChat (t * testing.T ) { 46app := newTestApp (t ) 47if app .State != AppStateChat { 48t .Fatalf ("expected initial state AppStateChat, got %v" ,app .State ) 49 } 50 51app .Chat .TextArea .SetValue ("/quota" ) 52updated ,cmd := app .Update (tea.KeyPressMsg {Code :tea .KeyEnter }) 53app = updated .(* AppModel ) 54app = dispatchCmd (app ,cmd ) 55 56if app .State != AppStateQuota { 57t .Fatalf ("submitting /quota should reach AppStateQuota, got %v" ,app .State ) 58 } 59 60view := ansi .Strip (app .View ().Content ) 61if ! strings .Contains (view ,"/quota" ) { 62t .Fatalf ("view should contain /quota title, got:\n%s" ,view ) 63 } 64} 65 66func TestQuotaRouteEscapeReturnsToChat (t * testing.T ) { 67app := newTestApp (t ) 68app .Chat .TextArea .SetValue ("/quota" ) 69updated ,cmd := app .Update (tea.KeyPressMsg {Code :tea .KeyEnter }) 70app = updated .(* AppModel ) 71app = dispatchCmd (app ,cmd ) 72 73if app .State != AppStateQuota { 74t .Fatalf ("failed to enter AppStateQuota: %v" ,app .State ) 75 } 76 77updated ,cmd = app .Update (tea.KeyPressMsg {Code :tea .KeyEscape }) 78app = updated .(* AppModel ) 79app = dispatchCmd (app ,cmd ) 80 81if app .State != AppStateChat { 82t .Fatalf ("esc from quota screen should return to AppStateChat, got %v" ,app .State ) 83 } 84} 85 86func TestQuotaRouteWindowResize (t * testing.T ) { 87app := newTestApp (t ) 88app .Chat .TextArea .SetValue ("/quota" ) 89updated ,cmd := app .Update (tea.KeyPressMsg {Code :tea .KeyEnter }) 90app = updated .(* AppModel ) 91app = dispatchCmd (app ,cmd ) 92 93if app .State != AppStateQuota { 94t .Fatalf ("failed to enter AppStateQuota: %v" ,app .State ) 95 } 96 97updated ,_ = app .Update (tea.WindowSizeMsg {Width :120 ,Height :45 }) 98app = updated .(* AppModel ) 99 100if app .Quota .Width != 120 || app .Quota .Height != 45 { 101t .Fatalf ("window resize did not resize QuotaModel: got (%d, %d), want (120, 45)" ,app .Quota .Width ,app .Quota .Height ) 102 } 103} 104 105func TestQuotaRouteStaleGenerationIgnored (t * testing.T ) { 106app := newTestApp (t ) 107app .Chat .TextArea .SetValue ("/quota" ) 108updated ,cmd := app .Update (tea.KeyPressMsg {Code :tea .KeyEnter }) 109app = updated .(* AppModel ) 110app = dispatchCmd (app ,cmd ) 111 112if app .State != AppStateQuota { 113t .Fatalf ("failed to enter AppStateQuota: %v" ,app .State ) 114 } 115 116currentGen := app .Quota .Generation 117staleGen := currentGen - 1 118reading := daemon.QuotaObservation { 119Provider :"test-provider" , 120AccountID :"test-account" , 121LimitID :"test-limit" , 122Label :"Test Limit" , 123 } 124 125// Send stale generation reply 126updated ,_ = app .Update (quotaLoadedMsg { 127Gen :staleGen , 128Readings : []daemon.QuotaObservation {reading }, 129 }) 130app = updated .(* AppModel ) 131 132if len (app .Quota .readings )!= 0 { 133t .Fatalf ("stale generation reply modified Quota.readings: got %d readings, want 0" ,len (app .Quota .readings )) 134 } 135 136// Send matching generation reply 137updated ,_ = app .Update (quotaLoadedMsg { 138Gen :currentGen , 139Readings : []daemon.QuotaObservation {reading }, 140 }) 141app = updated .(* AppModel ) 142 143if len (app .Quota .readings )!= 1 { 144t .Fatalf ("valid generation reply did not populate Quota.readings: got %d readings, want 1" ,len (app .Quota .readings )) 145 } 146 147// Send another stale reply with empty readings; it must not overwrite the existing reading 148updated ,_ = app .Update (quotaLoadedMsg { 149Gen :staleGen , 150Readings : []daemon.QuotaObservation {}, 151 }) 152app = updated .(* AppModel ) 153 154if len (app .Quota .readings )!= 1 { 155t .Fatalf ("stale generation reply cleared existing Quota.readings: got %d readings, want 1" ,len (app .Quota .readings )) 156 } 157}