package api import ( "bytes" "encoding/json" "net/http" "net/http/httptest" "testing" "proto-gen/internal/config" "proto-gen/internal/database" "proto-gen/internal/gitclient" "proto-gen/internal/models" ) type mockGitClient struct{} func (m *mockGitClient) ListRepositories(owner string) ([]gitclient.Repository, error) { return nil, nil } func (m *mockGitClient) CreateRepository(owner, name, desc string, private bool) (*gitclient.Repository, error) { return &gitclient.Repository{Name: name}, nil } func (m *mockGitClient) GetRepository(owner, name string) (*gitclient.Repository, error) { return &gitclient.Repository{Name: name}, nil } func (m *mockGitClient) ListBranches(owner, repo string) ([]gitclient.Branch, error) { return []gitclient.Branch{{Name: "main", Commit: "abc123"}}, nil } func (m *mockGitClient) GetBranch(owner, repo, branch string) (*gitclient.Branch, error) { return &gitclient.Branch{Name: branch, Commit: "abc123"}, nil } func newTestServer(t *testing.T) *Server { t.Helper() db, err := database.New(t.TempDir() + "/test.db") if err != nil { t.Fatalf("creating db: %v", err) } t.Cleanup(func() { db.Close() }) cfg := &config.Config{ ToolchainRegistry: "registry.example.com/proto-gen", TargetRepoTemplate: "{proto_repo}-gen-{lang}", Plugins: []config.PluginConfig{ {Language: "go", Image: "proto-gen-go:v1.0"}, {Language: "nodejs", Image: "proto-gen-ts:v1.0"}, }, } return NewServer(db, cfg, &mockGitClient{}) } func TestHandleCreateTask(t *testing.T) { srv := newTestServer(t) body, _ := json.Marshal(CreateTaskRequest{ Language: "go", ProtoRepo: "test-owner/yoresee_doc", ProtoBranch: "main", }) req := httptest.NewRequest("POST", "/api/v1/tasks", bytes.NewReader(body)) w := httptest.NewRecorder() srv.ServeHTTP(w, req) if w.Code != http.StatusCreated { t.Errorf("status = %d, want %d", w.Code, http.StatusCreated) } var task models.Task json.NewDecoder(w.Body).Decode(&task) if task.Language != "go" { t.Errorf("Language = %q, want %q", task.Language, "go") } if task.Status != models.StatusPending { t.Errorf("Status = %q, want %q", task.Status, models.StatusPending) } } func TestHandleCreateTask_UnsupportedLanguage(t *testing.T) { srv := newTestServer(t) body, _ := json.Marshal(CreateTaskRequest{ Language: "python", ProtoRepo: "test-owner/yoresee_doc", ProtoBranch: "main", }) req := httptest.NewRequest("POST", "/api/v1/tasks", bytes.NewReader(body)) w := httptest.NewRecorder() srv.ServeHTTP(w, req) if w.Code != http.StatusBadRequest { t.Errorf("status = %d, want %d", w.Code, http.StatusBadRequest) } } func TestHandleListPlugins(t *testing.T) { srv := newTestServer(t) req := httptest.NewRequest("GET", "/api/v1/plugins", nil) w := httptest.NewRecorder() srv.ServeHTTP(w, req) if w.Code != http.StatusOK { t.Errorf("status = %d, want %d", w.Code, http.StatusOK) } var plugins []config.PluginConfig json.NewDecoder(w.Body).Decode(&plugins) if len(plugins) != 2 { t.Errorf("len(plugins) = %d, want 2", len(plugins)) } } func TestHandleGetTask_NotFound(t *testing.T) { srv := newTestServer(t) req := httptest.NewRequest("GET", "/api/v1/tasks/nonexistent", nil) w := httptest.NewRecorder() srv.ServeHTTP(w, req) if w.Code != http.StatusNotFound { t.Errorf("status = %d, want %d", w.Code, http.StatusNotFound) } }