josie / simplegit

package db

import (
	"errors"
	"testing"
)

func TestTokenLifecycle(t *testing.T) {
	database := openTestDB(t)
	userID, err := CreateUser(database, "josie", "hash")
	if err != nil {
		t.Fatalf("CreateUser: %v", err)
	}

	tok, err := CreateToken(database, userID, "laptop", "sg_abcd123", "hash-1")
	if err != nil {
		t.Fatalf("CreateToken: %v", err)
	}
	if tok.ID == 0 || tok.UserID != userID || tok.Name != "laptop" || tok.Hint != "sg_abcd123" {
		t.Errorf("token = %+v, want populated row", tok)
	}
	if tok.LastUsedAt.Valid {
		t.Errorf("LastUsedAt = %+v, want NULL", tok.LastUsedAt)
	}

	byHash, err := GetTokenByHash(database, "hash-1")
	if err != nil {
		t.Fatalf("GetTokenByHash: %v", err)
	}
	if byHash.ID != tok.ID {
		t.Errorf("GetTokenByHash id = %d, want %d", byHash.ID, tok.ID)
	}
	if _, err := GetTokenByHash(database, "nope"); !errors.Is(err, ErrNotFound) {
		t.Errorf("missing hash err = %v, want ErrNotFound", err)
	}

	if err := TouchToken(database, tok.ID); err != nil {
		t.Fatalf("TouchToken: %v", err)
	}
	byHash, err = GetTokenByHash(database, "hash-1")
	if err != nil {
		t.Fatalf("GetTokenByHash after touch: %v", err)
	}
	if !byHash.LastUsedAt.Valid {
		t.Error("LastUsedAt still NULL after TouchToken")
	}

	if _, err := CreateToken(database, userID, "dup", "sg_x", "hash-1"); err == nil {
		t.Error("duplicate token_hash accepted, want UNIQUE error")
	}

	tokens, err := ListTokens(database, userID)
	if err != nil {
		t.Fatalf("ListTokens: %v", err)
	}
	if len(tokens) != 1 || tokens[0].ID != tok.ID {
		t.Errorf("ListTokens = %+v, want the one token", tokens)
	}

	if err := DeleteToken(database, userID+1, tok.ID); !errors.Is(err, ErrNotFound) {
		t.Errorf("DeleteToken by non-owner err = %v, want ErrNotFound", err)
	}
	if err := DeleteToken(database, userID, tok.ID); err != nil {
		t.Fatalf("DeleteToken: %v", err)
	}
	if _, err := GetTokenByHash(database, "hash-1"); !errors.Is(err, ErrNotFound) {
		t.Errorf("token still present after delete: %v", err)
	}
}

func TestTokenCascadeOnUserDelete(t *testing.T) {
	database := openTestDB(t)
	userID, err := CreateUser(database, "josie", "hash")
	if err != nil {
		t.Fatalf("CreateUser: %v", err)
	}
	if _, err := CreateToken(database, userID, "laptop", "sg_abcd123", "hash-1"); err != nil {
		t.Fatalf("CreateToken: %v", err)
	}
	if _, err := database.Exec(`DELETE FROM users WHERE id = ?`, userID); err != nil {
		t.Fatalf("delete user: %v", err)
	}
	if _, err := GetTokenByHash(database, "hash-1"); !errors.Is(err, ErrNotFound) {
		t.Errorf("token survived user delete: %v", err)
	}
}