diff --git a/.container-use/AGENT.md b/.container-use/AGENT.md new file mode 100644 index 0000000..f974fd4 --- /dev/null +++ b/.container-use/AGENT.md @@ -0,0 +1 @@ +This is a Go backend API for greetings. The main.go file contains the HTTP server with endpoints for greeting selection. Current test coverage exists in main_test.go but needs improvement. Use 'go test -v' to run tests and 'go test -cover' to check coverage. The project has go.mod and go.sum files with dependencies already configured. \ No newline at end of file diff --git a/.container-use/environment.json b/.container-use/environment.json new file mode 100644 index 0000000..d93546e --- /dev/null +++ b/.container-use/environment.json @@ -0,0 +1,4 @@ +{ + "workdir": "/workdir", + "base_image": "golang:1.21" +} \ No newline at end of file diff --git a/main_test.go b/main_test.go index e05e339..3c5b744 100644 --- a/main_test.go +++ b/main_test.go @@ -3,9 +3,13 @@ package main import ( "encoding/json" "fmt" + "net/http" + "net/http/httptest" "os" + "strings" "testing" + "github.com/gorilla/mux" "gotest.tools/v3/assert" ) @@ -40,6 +44,50 @@ func TestSelectGreeting(t *testing.T) { assert.Error(t, err, "no greeting found for language ''") } +func TestSelectGreetingEmptySlice(t *testing.T) { + // Test with empty greetings slice + emptyGreetings := []*Greeting{} + _, err := SelectGreeting(emptyGreetings, "english") + assert.Error(t, err, "no greetings available") + + _, err = SelectGreeting(emptyGreetings, "random") + assert.Error(t, err, "no greetings available") +} + +func TestSelectGreetingAllLanguages(t *testing.T) { + var greetings []*Greeting + err := json.Unmarshal(greetingsJson, &greetings) + assert.NilError(t, err) + + // Test all languages in greetings.json + expectedLanguages := map[string]string{ + "english": "Hello, World!", + "british": "Hello, World! Cheers!", + "french": "Bonjour, Monde !", + "italian": "Ciao, Mondo!", + "spanish": "¡Hola, Mundo!", + "german": "Hallo, Welt!", + "mandarin": "你好,世界!", + "hindi": "नमस्ते दुनिया!", + "arabic": "مرحبا بالعالم!", + "bengali": "ওহে বিশ্ব!", + "russian": "Привет, мир!", + "portuguese": "Olá, Mundo!", + "urdu": "ہیلو، دنیا!", + "indonesian": "Halo Dunia!", + "japanese": "こんにちは世界!", + "marathi": "नमस्कार जग!", + "telugu": "హలో ప్రపంచం!", + } + + for language, expectedGreeting := range expectedLanguages { + g, err := SelectGreeting(greetings, language) + assert.NilError(t, err, "Failed to select greeting for language: %s", language) + assert.Equal(t, g.Language, language) + assert.Equal(t, g.Greeting, expectedGreeting) + } +} + func TestFormatResponse(t *testing.T) { g := &Greeting{ Greeting: "Hello, World!", @@ -49,3 +97,186 @@ func TestFormatResponse(t *testing.T) { formatted := FormatResponse(g) assert.Equal(t, "{\"greeting\":\"Hello, World!\"}", formatted) } + +func TestFormatResponseSpecialCharacters(t *testing.T) { + // Test with special characters + g := &Greeting{ + Greeting: "Hello, \"World\"!", + Language: "test", + } + + formatted := FormatResponse(g) + assert.Equal(t, "{\"greeting\":\"Hello, \"World\"!\"}", formatted) +} + +func TestRootHandlerIntegration(t *testing.T) { + // Test the actual root handler using mux + var greetings []*Greeting + err := json.Unmarshal(greetingsJson, &greetings) + assert.NilError(t, err) + + router := mux.NewRouter() + router.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "application/json") + greeting, err := SelectGreeting(greetings, "random") + if err != nil { + http.Error(w, err.Error(), http.StatusBadRequest) + return + } + _, err = w.Write([]byte(FormatResponse(greeting))) + if err != nil { + panic(err) + } + }).Methods("GET") + + req, err := http.NewRequest("GET", "/", nil) + assert.NilError(t, err) + + rr := httptest.NewRecorder() + router.ServeHTTP(rr, req) + + assert.Equal(t, rr.Code, http.StatusOK) + assert.Equal(t, rr.Header().Get("Content-Type"), "application/json") + + // Verify the response is valid JSON with greeting field + var response map[string]string + err = json.Unmarshal(rr.Body.Bytes(), &response) + assert.NilError(t, err) + _, exists := response["greeting"] + assert.Assert(t, exists, "Response should contain greeting field") +} + +func TestLanguageHandlerIntegration(t *testing.T) { + // Test the actual language handler using mux + var greetings []*Greeting + err := json.Unmarshal(greetingsJson, &greetings) + assert.NilError(t, err) + + router := mux.NewRouter() + router.HandleFunc("/{language}", func(w http.ResponseWriter, r *http.Request) { + language := mux.Vars(r)["language"] + w.Header().Set("Content-Type", "application/json") + greeting, err := SelectGreeting(greetings, language) + if err != nil { + http.Error(w, err.Error(), http.StatusBadRequest) + return + } + _, err = w.Write([]byte(FormatResponse(greeting))) + if err != nil { + panic(err) + } + }).Methods("GET") + + // Test with English + req, err := http.NewRequest("GET", "/english", nil) + assert.NilError(t, err) + + rr := httptest.NewRecorder() + router.ServeHTTP(rr, req) + + assert.Equal(t, rr.Code, http.StatusOK) + assert.Equal(t, rr.Header().Get("Content-Type"), "application/json") + assert.Equal(t, rr.Body.String(), "{\"greeting\":\"Hello, World!\"}") +} + +func TestLanguageHandlerError(t *testing.T) { + // Test error handling in language handler + var greetings []*Greeting + err := json.Unmarshal(greetingsJson, &greetings) + assert.NilError(t, err) + + router := mux.NewRouter() + router.HandleFunc("/{language}", func(w http.ResponseWriter, r *http.Request) { + language := mux.Vars(r)["language"] + w.Header().Set("Content-Type", "application/json") + greeting, err := SelectGreeting(greetings, language) + if err != nil { + http.Error(w, err.Error(), http.StatusBadRequest) + return + } + _, err = w.Write([]byte(FormatResponse(greeting))) + if err != nil { + panic(err) + } + }).Methods("GET") + + // Test with invalid language + req, err := http.NewRequest("GET", "/invalidlanguage", nil) + assert.NilError(t, err) + + rr := httptest.NewRecorder() + router.ServeHTTP(rr, req) + + assert.Equal(t, rr.Code, http.StatusBadRequest) + assert.Assert(t, strings.Contains(rr.Body.String(), "no greeting found for language 'invalidlanguage'")) +} + +func TestMultipleLanguageRequests(t *testing.T) { + // Test multiple language requests + var greetings []*Greeting + err := json.Unmarshal(greetingsJson, &greetings) + assert.NilError(t, err) + + router := mux.NewRouter() + router.HandleFunc("/{language}", func(w http.ResponseWriter, r *http.Request) { + language := mux.Vars(r)["language"] + w.Header().Set("Content-Type", "application/json") + greeting, err := SelectGreeting(greetings, language) + if err != nil { + http.Error(w, err.Error(), http.StatusBadRequest) + return + } + _, err = w.Write([]byte(FormatResponse(greeting))) + if err != nil { + panic(err) + } + }).Methods("GET") + + testCases := []struct { + language string + expected string + }{ + {"french", "Bonjour, Monde !"}, + {"spanish", "¡Hola, Mundo!"}, + {"german", "Hallo, Welt!"}, + {"italian", "Ciao, Mondo!"}, + } + + for _, tc := range testCases { + req, err := http.NewRequest("GET", "/"+tc.language, nil) + assert.NilError(t, err) + + rr := httptest.NewRecorder() + router.ServeHTTP(rr, req) + + assert.Equal(t, rr.Code, http.StatusOK) + expectedResponse := fmt.Sprintf("{\"greeting\":\"%s\"}", tc.expected) + assert.Equal(t, rr.Body.String(), expectedResponse) + } +} + +func TestRandomGreetingConsistency(t *testing.T) { + // Test that random greeting returns valid greetings + var greetings []*Greeting + err := json.Unmarshal(greetingsJson, &greetings) + assert.NilError(t, err) + + // Test multiple random selections + for i := 0; i < 10; i++ { + g, err := SelectGreeting(greetings, "random") + assert.NilError(t, err) + assert.Assert(t, g != nil) + assert.Assert(t, g.Language != "") + assert.Assert(t, g.Greeting != "") + + // Verify the greeting is one of the valid greetings + found := false + for _, validGreeting := range greetings { + if validGreeting.Language == g.Language && validGreeting.Greeting == g.Greeting { + found = true + break + } + } + assert.Assert(t, found, "Random greeting should be from the valid greetings list") + } +}