package services import ( "strings" "testing" "github.com/breakpilot/school-service/internal/models" ) func TestRandomToken_Hashable(t *testing.T) { raw, hash, err := randomToken() if err != nil { t.Fatalf("randomToken error: %v", err) } if len(raw) < 30 { t.Errorf("raw token suspiciously short: %d", len(raw)) } if len(hash) != 64 { t.Errorf("sha256 hex hash must be 64 chars, got %d", len(hash)) } if hashToken(raw) != hash { t.Errorf("hashToken(raw) must equal the hash randomToken returned") } } func TestRandomToken_NonRepeating(t *testing.T) { // 16 iterations, all raw tokens must differ. seen := map[string]struct{}{} for i := 0; i < 16; i++ { raw, _, err := randomToken() if err != nil { t.Fatalf("iter %d: %v", i, err) } if _, dup := seen[raw]; dup { t.Fatalf("duplicate raw token at iter %d", i) } seen[raw] = struct{}{} } } func TestHashToken_StableHexLowercase(t *testing.T) { h := hashToken("hello world") if strings.ToLower(h) != h { t.Errorf("hash should be lowercase hex") } if len(h) != 64 { t.Errorf("expected 64-char hash, got %d", len(h)) } } func TestInviteParentRequest_Validation(t *testing.T) { tests := []struct { name string req models.InviteParentRequest wantErr bool }{ {"valid", models.InviteParentRequest{ Email: "a@b.de", ChildFirstName: "Max", ChildLastName: "Mueller", TTClassID: "00000000-0000-0000-0000-000000000001", }, false}, {"bad email", models.InviteParentRequest{ Email: "not-an-email", ChildFirstName: "Max", ChildLastName: "Mueller", TTClassID: "00000000-0000-0000-0000-000000000001", }, true}, {"missing child", models.InviteParentRequest{ Email: "a@b.de", TTClassID: "00000000-0000-0000-0000-000000000001", }, true}, {"bad class uuid", models.InviteParentRequest{ Email: "a@b.de", ChildFirstName: "Max", ChildLastName: "Mueller", TTClassID: "not-a-uuid", }, true}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if (validate.Struct(tt.req) != nil) != tt.wantErr { t.Errorf("unexpected validation outcome for %s", tt.name) } }) } }