package webauthn import ( "path/filepath" "testing" "time" ) // TestStoreRoundTrip verifies Put + Get + Delete + List + UpdateSignCount. func TestStoreRoundTrip(t *testing.T) { dbPath := filepath.Join(t.TempDir(), "webauthn-creds.db") store, err := NewStore(dbPath) if err != nil { t.Fatalf("NewStore: %v", err) } defer store.Close() cred := &Credential{ UserID: "user-1", CredentialID: []byte("cred-id-123"), PublicKey: []byte("pub-key-bytes"), SignCount: 0, AAGUID: "test-aaguid", CreatedAt: time.Now(), } if err := store.PutCredential(cred); err != nil { t.Fatalf("Put: %v", err) } got, err := store.GetCredential("user-1") if err != nil { t.Fatalf("Get: %v", err) } if got == nil { t.Fatal("Get returned nil") } if got.UserID != "user-1" || string(got.CredentialID) != "cred-id-123" { t.Errorf("got = %+v", got) } if err := store.UpdateSignCount("user-1", 42); err != nil { t.Fatalf("UpdateSignCount: %v", err) } got, _ = store.GetCredential("user-1") if got.SignCount != 42 { t.Errorf("SignCount = %d, want 42", got.SignCount) } list, err := store.ListCredentials() if err != nil { t.Fatalf("List: %v", err) } if len(list) != 1 { t.Errorf("List = %d, want 1", len(list)) } if err := store.DeleteCredential("user-1"); err != nil { t.Fatalf("Delete: %v", err) } got, _ = store.GetCredential("user-1") if got != nil { t.Error("Get after delete should return nil") } } // TestStorePutReplace verifies Put replaces on conflict. func TestStorePutReplace(t *testing.T) { dbPath := filepath.Join(t.TempDir(), "webauthn-creds.db") store, _ := NewStore(dbPath) defer store.Close() c1 := &Credential{UserID: "u", CredentialID: []byte("old"), PublicKey: []byte("pk1"), CreatedAt: time.Now()} store.PutCredential(c1) c2 := &Credential{UserID: "u", CredentialID: []byte("new"), PublicKey: []byte("pk2"), CreatedAt: time.Now()} store.PutCredential(c2) got, _ := store.GetCredential("u") if string(got.CredentialID) != "new" { t.Errorf("CredentialID = %q, want new", got.CredentialID) } } // TestStoreGetMissing verifies Get returns nil, nil for missing. func TestStoreGetMissing(t *testing.T) { dbPath := filepath.Join(t.TempDir(), "webauthn-creds.db") store, _ := NewStore(dbPath) defer store.Close() got, err := store.GetCredential("nonexistent") if err != nil { t.Errorf("Get missing should not error: %v", err) } if got != nil { t.Error("Get missing should return nil") } } // TestEncodeDecodeID verifies base64 round-trip. func TestEncodeDecodeID(t *testing.T) { original := []byte("test-credential-id-12345") encoded := EncodeID(original) decoded, err := DecodeID(encoded) if err != nil { t.Fatalf("Decode: %v", err) } if string(decoded) != string(original) { t.Errorf("decode = %q, want %q", decoded, original) } }