Monorepo for Tangled
at 507289074b66591c485b5f1047dd3f87672694d4 265 lines 7.2 kB view raw
1package oauth 2 3import ( 4 "testing" 5) 6 7func TestAccountRegistry_AddAccount(t *testing.T) { 8 tests := []struct { 9 name string 10 initial []AccountInfo 11 addDid string 12 addHandle string 13 addSessionId string 14 wantErr error 15 wantLen int 16 wantSessionId string 17 }{ 18 { 19 name: "add first account", 20 initial: []AccountInfo{}, 21 addDid: "did:plc:abc123", 22 addHandle: "alice.bsky.social", 23 addSessionId: "session-1", 24 wantErr: nil, 25 wantLen: 1, 26 wantSessionId: "session-1", 27 }, 28 { 29 name: "add second account", 30 initial: []AccountInfo{ 31 {Did: "did:plc:abc123", Handle: "alice.bsky.social", SessionId: "session-1", AddedAt: 1000}, 32 }, 33 addDid: "did:plc:def456", 34 addHandle: "bob.bsky.social", 35 addSessionId: "session-2", 36 wantErr: nil, 37 wantLen: 2, 38 wantSessionId: "session-2", 39 }, 40 { 41 name: "update existing account session", 42 initial: []AccountInfo{ 43 {Did: "did:plc:abc123", Handle: "alice.bsky.social", SessionId: "old-session", AddedAt: 1000}, 44 }, 45 addDid: "did:plc:abc123", 46 addHandle: "alice.bsky.social", 47 addSessionId: "new-session", 48 wantErr: nil, 49 wantLen: 1, 50 wantSessionId: "new-session", 51 }, 52 } 53 54 for _, tt := range tests { 55 t.Run(tt.name, func(t *testing.T) { 56 registry := &AccountRegistry{Accounts: tt.initial} 57 err := registry.AddAccount(tt.addDid, tt.addHandle, tt.addSessionId) 58 59 if err != tt.wantErr { 60 t.Errorf("AddAccount() error = %v, want %v", err, tt.wantErr) 61 } 62 63 if len(registry.Accounts) != tt.wantLen { 64 t.Errorf("AddAccount() len = %d, want %d", len(registry.Accounts), tt.wantLen) 65 } 66 67 found := registry.FindAccount(tt.addDid) 68 if found == nil { 69 t.Errorf("AddAccount() account not found after add") 70 return 71 } 72 73 if found.SessionId != tt.wantSessionId { 74 t.Errorf("AddAccount() sessionId = %s, want %s", found.SessionId, tt.wantSessionId) 75 } 76 }) 77 } 78} 79 80func TestAccountRegistry_AddAccount_MaxLimit(t *testing.T) { 81 registry := &AccountRegistry{Accounts: make([]AccountInfo, 0, MaxAccounts)} 82 83 for i := range MaxAccounts { 84 err := registry.AddAccount("did:plc:user"+string(rune('a'+i)), "handle", "session") 85 if err != nil { 86 t.Fatalf("AddAccount() unexpected error on account %d: %v", i, err) 87 } 88 } 89 90 if len(registry.Accounts) != MaxAccounts { 91 t.Errorf("expected %d accounts, got %d", MaxAccounts, len(registry.Accounts)) 92 } 93 94 err := registry.AddAccount("did:plc:overflow", "overflow", "session-overflow") 95 if err != ErrMaxAccountsReached { 96 t.Errorf("AddAccount() error = %v, want %v", err, ErrMaxAccountsReached) 97 } 98 99 if len(registry.Accounts) != MaxAccounts { 100 t.Errorf("account added despite max limit, got %d", len(registry.Accounts)) 101 } 102} 103 104func TestAccountRegistry_RemoveAccount(t *testing.T) { 105 tests := []struct { 106 name string 107 initial []AccountInfo 108 removeDid string 109 wantLen int 110 wantDids []string 111 }{ 112 { 113 name: "remove existing account", 114 initial: []AccountInfo{ 115 {Did: "did:plc:abc123", Handle: "alice", SessionId: "s1"}, 116 {Did: "did:plc:def456", Handle: "bob", SessionId: "s2"}, 117 }, 118 removeDid: "did:plc:abc123", 119 wantLen: 1, 120 wantDids: []string{"did:plc:def456"}, 121 }, 122 { 123 name: "remove non-existing account", 124 initial: []AccountInfo{ 125 {Did: "did:plc:abc123", Handle: "alice", SessionId: "s1"}, 126 }, 127 removeDid: "did:plc:notfound", 128 wantLen: 1, 129 wantDids: []string{"did:plc:abc123"}, 130 }, 131 { 132 name: "remove last account", 133 initial: []AccountInfo{ 134 {Did: "did:plc:abc123", Handle: "alice", SessionId: "s1"}, 135 }, 136 removeDid: "did:plc:abc123", 137 wantLen: 0, 138 wantDids: []string{}, 139 }, 140 { 141 name: "remove from empty registry", 142 initial: []AccountInfo{}, 143 removeDid: "did:plc:abc123", 144 wantLen: 0, 145 wantDids: []string{}, 146 }, 147 } 148 149 for _, tt := range tests { 150 t.Run(tt.name, func(t *testing.T) { 151 registry := &AccountRegistry{Accounts: tt.initial} 152 registry.RemoveAccount(tt.removeDid) 153 154 if len(registry.Accounts) != tt.wantLen { 155 t.Errorf("RemoveAccount() len = %d, want %d", len(registry.Accounts), tt.wantLen) 156 } 157 158 for _, wantDid := range tt.wantDids { 159 if registry.FindAccount(wantDid) == nil { 160 t.Errorf("RemoveAccount() expected %s to remain", wantDid) 161 } 162 } 163 164 if registry.FindAccount(tt.removeDid) != nil && tt.wantLen < len(tt.initial) { 165 t.Errorf("RemoveAccount() %s should have been removed", tt.removeDid) 166 } 167 }) 168 } 169} 170 171func TestAccountRegistry_FindAccount(t *testing.T) { 172 registry := &AccountRegistry{ 173 Accounts: []AccountInfo{ 174 {Did: "did:plc:first", Handle: "first", SessionId: "s1", AddedAt: 1000}, 175 {Did: "did:plc:second", Handle: "second", SessionId: "s2", AddedAt: 2000}, 176 {Did: "did:plc:third", Handle: "third", SessionId: "s3", AddedAt: 3000}, 177 }, 178 } 179 180 t.Run("find existing account", func(t *testing.T) { 181 found := registry.FindAccount("did:plc:second") 182 if found == nil { 183 t.Fatal("FindAccount() returned nil for existing account") 184 } 185 if found.Handle != "second" { 186 t.Errorf("FindAccount() handle = %s, want second", found.Handle) 187 } 188 if found.SessionId != "s2" { 189 t.Errorf("FindAccount() sessionId = %s, want s2", found.SessionId) 190 } 191 }) 192 193 t.Run("find non-existing account", func(t *testing.T) { 194 found := registry.FindAccount("did:plc:notfound") 195 if found != nil { 196 t.Errorf("FindAccount() = %v, want nil", found) 197 } 198 }) 199 200 t.Run("returned pointer is mutable", func(t *testing.T) { 201 found := registry.FindAccount("did:plc:first") 202 if found == nil { 203 t.Fatal("FindAccount() returned nil") 204 } 205 found.SessionId = "modified" 206 207 refetch := registry.FindAccount("did:plc:first") 208 if refetch.SessionId != "modified" { 209 t.Errorf("FindAccount() pointer not referencing original, got %s", refetch.SessionId) 210 } 211 }) 212} 213 214func TestAccountRegistry_OtherAccounts(t *testing.T) { 215 registry := &AccountRegistry{ 216 Accounts: []AccountInfo{ 217 {Did: "did:plc:active", Handle: "active", SessionId: "s1"}, 218 {Did: "did:plc:other1", Handle: "other1", SessionId: "s2"}, 219 {Did: "did:plc:other2", Handle: "other2", SessionId: "s3"}, 220 }, 221 } 222 223 others := registry.OtherAccounts("did:plc:active") 224 225 if len(others) != 2 { 226 t.Errorf("OtherAccounts() len = %d, want 2", len(others)) 227 } 228 229 for _, acc := range others { 230 if acc.Did == "did:plc:active" { 231 t.Errorf("OtherAccounts() should not include active account") 232 } 233 } 234 235 hasDid := func(did string) bool { 236 for _, acc := range others { 237 if acc.Did == did { 238 return true 239 } 240 } 241 return false 242 } 243 244 if !hasDid("did:plc:other1") || !hasDid("did:plc:other2") { 245 t.Errorf("OtherAccounts() missing expected accounts") 246 } 247} 248 249func TestMultiAccountUser_Did(t *testing.T) { 250 t.Run("with active user", func(t *testing.T) { 251 user := &MultiAccountUser{ 252 Active: &User{Did: "did:plc:test", Pds: "https://bsky.social"}, 253 } 254 if user.Did() != "did:plc:test" { 255 t.Errorf("Did() = %s, want did:plc:test", user.Did()) 256 } 257 }) 258 259 t.Run("with nil active", func(t *testing.T) { 260 user := &MultiAccountUser{Active: nil} 261 if user.Did() != "" { 262 t.Errorf("Did() = %s, want empty string", user.Did()) 263 } 264 }) 265}