Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Additional Integration tests for question service #81

Merged
merged 1 commit into from
Nov 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion apps/question-service/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,16 @@ require (
google.golang.org/grpc v1.67.1
)

require github.com/joho/godotenv v1.5.1
require (
github.com/joho/godotenv v1.5.1
github.com/stretchr/testify v1.9.0
)

require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)

require (
cloud.google.com/go v0.115.1 // indirect
Expand Down
1 change: 1 addition & 0 deletions apps/question-service/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,7 @@ google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp0
google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA=
google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
Expand Down
65 changes: 65 additions & 0 deletions apps/question-service/tests/common_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package tests

import (
"context"
"log"
"os"
"question-service/handlers"
"question-service/utils"
"testing"

"cloud.google.com/go/firestore"
)

var service *handlers.Service
var ctx = context.Background()

func TestMain(m *testing.M) {
// Set FIRESTORE_EMULATOR_HOST environment variable.
err := os.Setenv("FIRESTORE_EMULATOR_HOST", "127.0.0.1:8080")
if err != nil {
log.Fatalf("could not set env %v", err)
}
// Create client.
client, err := firestore.NewClient(ctx, "my-project-id")
service = &handlers.Service{Client: client}

if err != nil {
log.Fatalf("could not create client %v", err)
}
defer client.Close()

m.Run()
os.Exit(0)
}

// Sets up the firestore emulator with the sample questions
// This repopulates the db
// Returns the docref of one of the questions if a test need it
func setupDb(t *testing.T) string {
// Repopulate document
utils.Populate(service.Client, false)

coll := service.Client.Collection("questions")
if coll == nil {
t.Fatalf("Failed to get CollectionRef")
}
docRef, err := coll.DocumentRefs(ctx).Next()
if err != nil {
t.Fatalf("Failed to get DocRef: %v", err)
}
return docRef.ID
}

func getCount(t *testing.T) int64 {
counterDocRef, err := service.Client.Collection("counters").Doc("questions").Get(context.Background())
if err != nil {
t.Fatal(err)
}
fields := counterDocRef.Data()
if err != nil {
t.Fatal(err)
}
count := fields["count"].(int64)
return count
}
144 changes: 144 additions & 0 deletions apps/question-service/tests/create_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
package tests

import (
"bytes"
"encoding/json"
"net/http"
"net/http/httptest"
"testing"

"question-service/models"

"github.com/stretchr/testify/assert"
)

// tests partially generated using Github Copilot

func createCreateRequestWithData(_ *testing.T, body []byte) *http.Request {
req := httptest.NewRequest(http.MethodPost, "http://localhost:12345/questions", bytes.NewBuffer(body))

return req
}

func TestCreateQuestion(t *testing.T) {
t.Run("Create new question", func(t *testing.T) {
var err error

newQuestion := models.Question{
Title: "New Question",
Description: "New Description",
Complexity: models.Medium,
Categories: []string{"Category1"},

DocRefID: "a-doc-ref-id",
}

setupDb(t)
beforeCount := getCount(t)

w := httptest.NewRecorder()
data, err := json.Marshal(newQuestion)
assert.NoError(t, err)
req := createCreateRequestWithData(t, data)
service.CreateQuestion(w, req)
afterCount := getCount(t)
// Check response
assert.Equal(t, http.StatusOK, w.Code)
var response models.Question
err = json.NewDecoder(w.Body).Decode(&response)
assert.NoError(t, err)
assert.Equal(t, newQuestion.Title, response.Title)
assert.Equal(t, newQuestion.Description, response.Description)
assert.Equal(t, newQuestion.Complexity, response.Complexity)
assert.Equal(t, newQuestion.Categories, response.Categories)
assert.Equal(t, beforeCount+1, afterCount)
})

t.Run("Create question with missing title", func(t *testing.T) {
newQuestion := models.Question{
Description: "New Description",
Complexity: models.Medium,
Categories: []string{"Category1"},
}

setupDb(t)
beforeCount := getCount(t)

w := httptest.NewRecorder()
data, _ := json.Marshal(newQuestion)
req := createCreateRequestWithData(t, data)
service.CreateQuestion(w, req)

// Check response
assert.Equal(t, http.StatusBadRequest, w.Code)
assert.Contains(t, w.Body.String(), "Title is required")
assert.Equal(t, beforeCount, getCount(t))
})

t.Run("Create question with duplicate title", func(t *testing.T) {
newQuestion := models.Question{
Title: "Duplicate Title",
Description: "New Description",
Complexity: models.Medium,
Categories: []string{"Category1"},
}

setupDb(t)

// Create the first question
w := httptest.NewRecorder()
data, _ := json.Marshal(newQuestion)
req := createCreateRequestWithData(t, data)
service.CreateQuestion(w, req)
assert.Equal(t, http.StatusOK, w.Code)

// Try to create the second question with the same title
w = httptest.NewRecorder()
req = createCreateRequestWithData(t, data)
service.CreateQuestion(w, req)

// Check response
assert.Equal(t, http.StatusBadRequest, w.Code)
assert.Contains(t, w.Body.String(), "Question title already exists")
})

t.Run("Create question with empty description", func(t *testing.T) {
newQuestion := models.Question{
Title: "New Question",
Description: "",
Complexity: models.Medium,
Categories: []string{"Category1"},
}

setupDb(t)

w := httptest.NewRecorder()
data, _ := json.Marshal(newQuestion)
req := createCreateRequestWithData(t, data)
service.CreateQuestion(w, req)

// Check response
assert.Equal(t, http.StatusBadRequest, w.Code)
assert.Contains(t, w.Body.String(), "Description is required")
})

t.Run("Create question with nil title", func(t *testing.T) {
newQuestion := models.Question{
// Title: "New Question",
Description: "New Description",
Complexity: models.Medium,
Categories: []string{"Category1"},
}

setupDb(t)

w := httptest.NewRecorder()
data, _ := json.Marshal(newQuestion)
req := createCreateRequestWithData(t, data)
service.CreateQuestion(w, req)

// Check response
assert.Equal(t, http.StatusBadRequest, w.Code)
assert.Contains(t, w.Body.String(), "Title is required")
})
}
47 changes: 47 additions & 0 deletions apps/question-service/tests/delete_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package tests

import (
"context"
"net/http"
"net/http/httptest"
"testing"

"github.com/go-chi/chi/v5"
"github.com/stretchr/testify/assert"
)

// tests partially generated using Github Copilot

func createDeleteRequestWithId(docRefID string) *http.Request {
rctx := chi.NewRouteContext()
rctx.URLParams.Add("docRefID", docRefID)

req := httptest.NewRequest(http.MethodDelete, "/questions/"+docRefID, nil)
req = req.WithContext(context.WithValue(req.Context(), chi.RouteCtxKey, rctx))
return req
}

func TestDeleteQuestion(t *testing.T) {

t.Run("Delete existing question", func(t *testing.T) {
docRefID := setupDb(t)
req := createDeleteRequestWithId(docRefID)
res := httptest.NewRecorder()

service.DeleteQuestion(res, req)

assert.Equal(t, http.StatusOK, res.Code)
assert.Equal(t, res.Body.String(), "Question with ID "+docRefID+" deleted successfully")
})

t.Run("Delete non-existing question", func(t *testing.T) {
nonExistentDocRefID := "non-existent-id"
req := createDeleteRequestWithId(nonExistentDocRefID)
res := httptest.NewRecorder()

service.DeleteQuestion(res, req)

assert.Equal(t, http.StatusNotFound, res.Code)
assert.Equal(t, res.Body.String(), "Question not found\n")
})
}
51 changes: 3 additions & 48 deletions apps/question-service/tests/read_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,60 +2,15 @@ package tests

import (
"context"
"log"
"net/http"
"net/http/httptest"
"os"
"question-service/handlers"
"question-service/utils"
"strings"
"testing"

"cloud.google.com/go/firestore"
"github.com/go-chi/chi/v5"
)

var service *handlers.Service
var ctx = context.Background()

func TestMain(m *testing.M) {
// Set FIRESTORE_EMULATOR_HOST environment variable.
err := os.Setenv("FIRESTORE_EMULATOR_HOST", "127.0.0.1:8080")
if err != nil {
log.Fatalf("could not set env %v", err)
}
// Create client.
client, err := firestore.NewClient(ctx, "my-project-id")
service = &handlers.Service{Client: client}

if err != nil {
log.Fatalf("could not create client %v", err)
}
defer client.Close()

m.Run()
os.Exit(0)
}

// Sets up the firestore emulator with the sample questions
// This repopulates the db
// Returns the docref of one of the questions if a test need it
func setupDb(t *testing.T) string {
// Repopulate document
utils.Populate(service.Client, false)

coll := service.Client.Collection("questions")
if coll == nil {
t.Fatalf("Failed to get CollectionRef")
}
docRef, err := coll.DocumentRefs(ctx).Next()
if err != nil {
t.Fatalf("Failed to get DocRef: %v", err)
}
return docRef.ID
}

func ReadRequestWithId(id string) *http.Request {
func readRequestWithId(id string) *http.Request {
// adds chi context
// https://stackoverflow.com/questions/54580582/testing-chi-routes-w-path-variables
rctx := chi.NewRouteContext()
Expand All @@ -69,7 +24,7 @@ func Test_Read(t *testing.T) {
id := setupDb(t)

res := httptest.NewRecorder()
req := ReadRequestWithId(id)
req := readRequestWithId(id)

service.ReadQuestion(res, req)

Expand All @@ -82,7 +37,7 @@ func Test_ReadNotFound(t *testing.T) {
setupDb(t)

res := httptest.NewRecorder()
req := ReadRequestWithId("invalid-docref")
req := readRequestWithId("invalid-docref")

service.ReadQuestion(res, req)

Expand Down
Loading
Loading