package models import ( "context" "encoding/json" "io" "net/http" "net/http/httptest" "os" "path/filepath" "strings" "testing" ) func newFunASRForTest(baseURL string) *FunASR { return NewFunASRModel( map[string]string{"default": baseURL}, URLSuffix{ ASR: "audio/transcriptions", Models: "models", }, ) } func writeFunASRTestAudio(t *testing.T) string { t.Helper() path := filepath.Join(t.TempDir(), "audio.wav") if err := os.WriteFile(path, []byte("test audio"), 0o600); err != nil { t.Fatalf("write test audio: %v", err) } return path } func TestFunASRTranscribeAudioWithoutAPIKey(t *testing.T) { srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if r.Method != http.MethodPost { t.Errorf("method=%s, want POST", r.Method) } if r.URL.Path != "/audio/transcriptions" { t.Errorf("path=%s, want /audio/transcriptions", r.URL.Path) } if got := r.Header.Get("Authorization"); got != "" { t.Errorf("Authorization=%q, want no header", got) } if err := r.ParseMultipartForm(1 << 20); err != nil { t.Errorf("parse multipart form: %v", err) return } if got := r.FormValue("model"); got != "fun-asr-nano" { t.Errorf("model=%q, want fun-asr-nano", got) } _ = json.NewEncoder(w).Encode(map[string]string{"text": "hello"}) })) defer srv.Close() modelName := " fun-asr-nano " file := writeFunASRTestAudio(t) resp, err := newFunASRForTest(srv.URL).TranscribeAudio( context.Background(), &modelName, &file, &APIConfig{}, nil, nil, ) if err != nil { t.Fatalf("TranscribeAudio: %v", err) } if resp == nil || resp.Text != "hello" { t.Fatalf("response=%v, want text hello", resp) } } func TestFunASRTranscribeAudioRequiresModelName(t *testing.T) { file := writeFunASRTestAudio(t) apiKey := "test-key" blankModelName := " " for _, tc := range []struct { name string modelName *string }{ {name: "nil", modelName: nil}, {name: "whitespace", modelName: &blankModelName}, } { t.Run(tc.name, func(t *testing.T) { _, err := newFunASRForTest("http://unused").TranscribeAudio( context.Background(), tc.modelName, &file, &APIConfig{ApiKey: &apiKey}, nil, nil, ) if err == nil || !strings.Contains(err.Error(), "model name is missing") { t.Fatalf("expected missing-model-name error, got %v", err) } }) } } func TestFunASRListModelsWithoutAPIKey(t *testing.T) { srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if r.Method != http.MethodGet { t.Errorf("method=%s, want GET", r.Method) } if r.URL.Path != "/models" { t.Errorf("path=%s, want /models", r.URL.Path) } if got := r.Header.Get("Authorization"); got != "" { t.Errorf("Authorization=%q, want no header", got) } _, _ = io.WriteString(w, `{"object":"list","data":[{"id":"fun-asr-nano","owned_by":"funasr"}]}`) })) defer srv.Close() models, err := newFunASRForTest(srv.URL).ListModels(context.Background(), &APIConfig{}) if err != nil { t.Fatalf("ListModels: %v", err) } if len(models) != 1 || models[0].Name != "fun-asr-nano@funasr" { t.Fatalf("models=%v, want fun-asr-nano@funasr", models) } } func TestFunASRListModelsSendsAuthWhenProvided(t *testing.T) { srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if got := r.Header.Get("Authorization"); got != "Bearer secret" { t.Errorf("Authorization=%q, want Bearer secret", got) } _, _ = io.WriteString(w, `{"object":"list","data":[{"id":"fun-asr-nano"}]}`) })) defer srv.Close() apiKey := " secret " if _, err := newFunASRForTest(srv.URL).ListModels( context.Background(), &APIConfig{ApiKey: &apiKey}, ); err != nil { t.Fatalf("ListModels: %v", err) } }