-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #74 from KonferCA/28-be-create-tests-for-all-api-c…
…alls Add tests
- Loading branch information
Showing
6 changed files
with
679 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
package server | ||
|
||
import ( | ||
"encoding/json" | ||
"net/http" | ||
"net/http/httptest" | ||
"os" | ||
"testing" | ||
|
||
"github.com/labstack/echo/v4" | ||
"github.com/stretchr/testify/assert" | ||
"github.com/stretchr/testify/require" | ||
) | ||
|
||
func TestGetSystemInfo(t *testing.T) { | ||
info := getSystemInfo() | ||
|
||
assert.NotEmpty(t, info.Version) | ||
assert.NotEmpty(t, info.GoVersion) | ||
assert.Greater(t, info.NumGoRoutine, 0) | ||
assert.GreaterOrEqual(t, info.MemoryUsage, 0.0) | ||
} | ||
|
||
func TestHealthCheckHandler(t *testing.T) { | ||
// setup test environment | ||
os.Setenv("DB_HOST", "localhost") | ||
os.Setenv("DB_PORT", "5432") | ||
os.Setenv("DB_USER", "postgres") | ||
os.Setenv("DB_PASSWORD", "postgres") | ||
os.Setenv("DB_NAME", "postgres") | ||
os.Setenv("DB_SSLMODE", "disable") | ||
|
||
// create test server | ||
s, err := New(true) | ||
require.NoError(t, err) | ||
defer s.DBPool.Close() | ||
|
||
tests := []struct { | ||
name string | ||
setupFunc func(*Server) | ||
expectedStatus int | ||
expectedHealth string | ||
}{ | ||
{ | ||
name: "healthy_system", | ||
setupFunc: nil, // no special setup needed | ||
expectedStatus: http.StatusOK, | ||
expectedHealth: "healthy", | ||
}, | ||
{ | ||
name: "unhealthy_system", | ||
setupFunc: func(s *Server) { | ||
s.DBPool.Close() | ||
}, | ||
expectedStatus: http.StatusServiceUnavailable, | ||
expectedHealth: "unhealthy", | ||
}, | ||
} | ||
|
||
for _, tt := range tests { | ||
t.Run(tt.name, func(t *testing.T) { | ||
// setup | ||
e := echo.New() | ||
req := httptest.NewRequest(http.MethodGet, "/health", nil) | ||
rec := httptest.NewRecorder() | ||
c := e.NewContext(req, rec) | ||
|
||
if tt.setupFunc != nil { | ||
tt.setupFunc(s) | ||
} | ||
|
||
// test | ||
err := s.handleHealthCheck(c) | ||
require.NoError(t, err) | ||
|
||
// sssertions | ||
assert.Equal(t, tt.expectedStatus, rec.Code) | ||
|
||
var response HealthReport | ||
err = json.Unmarshal(rec.Body.Bytes(), &response) | ||
require.NoError(t, err) | ||
|
||
assert.Equal(t, tt.expectedHealth, response.Status) | ||
assert.NotEmpty(t, response.Timestamp) | ||
assert.NotNil(t, response.System) | ||
assert.NotNil(t, response.Database) | ||
|
||
if tt.expectedHealth == "unhealthy" { | ||
assert.False(t, response.Database.Connected) | ||
assert.NotEmpty(t, response.Database.Error) | ||
} else { | ||
assert.True(t, response.Database.Connected) | ||
assert.NotEmpty(t, response.Database.PostgresVersion) | ||
assert.GreaterOrEqual(t, response.Database.LatencyMs, 0.0) | ||
} | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,230 @@ | ||
package server | ||
|
||
import ( | ||
"bytes" | ||
"context" | ||
"encoding/json" | ||
"net/http" | ||
"net/http/httptest" | ||
"os" | ||
"testing" | ||
|
||
"github.com/google/uuid" | ||
"github.com/stretchr/testify/assert" | ||
) | ||
|
||
func TestProjectCommentEndpoints(t *testing.T) { | ||
// setup test environment | ||
os.Setenv("DB_HOST", "localhost") | ||
os.Setenv("DB_PORT", "5432") | ||
os.Setenv("DB_USER", "postgres") | ||
os.Setenv("DB_PASSWORD", "postgres") | ||
os.Setenv("DB_NAME", "postgres") | ||
os.Setenv("DB_SSLMODE", "disable") | ||
|
||
// create server | ||
s, err := New(true) | ||
if err != nil { | ||
t.Fatalf("failed to create server: %v", err) | ||
} | ||
defer s.DBPool.Close() | ||
|
||
// clean up database before tests | ||
ctx := context.Background() | ||
_, err = s.DBPool.Exec(ctx, "DELETE FROM project_comments") | ||
if err != nil { | ||
t.Fatalf("failed to clean up project_comments: %v", err) | ||
} | ||
_, err = s.DBPool.Exec(ctx, "DELETE FROM projects") | ||
if err != nil { | ||
t.Fatalf("failed to clean up projects: %v", err) | ||
} | ||
_, err = s.DBPool.Exec(ctx, "DELETE FROM companies WHERE name = $1", "Test Company") | ||
if err != nil { | ||
t.Fatalf("failed to clean up companies: %v", err) | ||
} | ||
_, err = s.DBPool.Exec(ctx, "DELETE FROM users WHERE email = $1", "[email protected]") | ||
if err != nil { | ||
t.Fatalf("failed to clean up test user: %v", err) | ||
} | ||
|
||
// Create a test user directly in the database | ||
userID := uuid.New().String() | ||
_, err = s.DBPool.Exec(ctx, ` | ||
INSERT INTO users (id, email, password_hash, first_name, last_name, role) | ||
VALUES ($1, $2, $3, $4, $5, 'startup_owner') | ||
`, userID, "[email protected]", "hashedpassword", "Test", "User") | ||
if err != nil { | ||
t.Fatalf("failed to create test user: %v", err) | ||
} | ||
|
||
// Create a company | ||
description := "Test Company Description" | ||
companyPayload := CreateCompanyRequest{ | ||
OwnerUserID: userID, | ||
Name: "Test Company", | ||
Description: &description, | ||
} | ||
companyBody, _ := json.Marshal(companyPayload) | ||
|
||
req := httptest.NewRequest(http.MethodPost, "/api/v1/companies", bytes.NewReader(companyBody)) | ||
req.Header.Set("Content-Type", "application/json") | ||
rec := httptest.NewRecorder() | ||
s.echoInstance.ServeHTTP(rec, req) | ||
|
||
t.Logf("Company creation response: %s", rec.Body.String()) | ||
|
||
var companyResponse map[string]interface{} | ||
err = json.NewDecoder(rec.Body).Decode(&companyResponse) | ||
if !assert.NoError(t, err) { | ||
t.Fatalf("Failed to decode company response: %v", err) | ||
} | ||
|
||
companyID, ok := companyResponse["ID"].(string) | ||
if !assert.True(t, ok, "Company ID should be a string") { | ||
t.Fatalf("Failed to get company ID from response: %v", companyResponse) | ||
} | ||
|
||
// Create a project | ||
projectDescription := "Test Description" | ||
projectPayload := CreateProjectRequest{ | ||
CompanyID: companyID, | ||
Title: "Test Project", | ||
Description: &projectDescription, | ||
Status: "draft", | ||
} | ||
projectBody, _ := json.Marshal(projectPayload) | ||
|
||
req = httptest.NewRequest(http.MethodPost, "/api/v1/projects", bytes.NewReader(projectBody)) | ||
req.Header.Set("Content-Type", "application/json") | ||
rec = httptest.NewRecorder() | ||
s.echoInstance.ServeHTTP(rec, req) | ||
|
||
t.Logf("Project creation response: %s", rec.Body.String()) | ||
|
||
var projectResponse map[string]interface{} | ||
err = json.NewDecoder(rec.Body).Decode(&projectResponse) | ||
if !assert.NoError(t, err) { | ||
t.Fatalf("Failed to decode project response: %v", err) | ||
} | ||
|
||
projectID, ok := projectResponse["ID"].(string) | ||
if !assert.True(t, ok, "Project ID should be a string") { | ||
t.Fatalf("Failed to get project ID from response: %v", projectResponse) | ||
} | ||
|
||
// test create comment | ||
t.Run("create comment", func(t *testing.T) { | ||
commentPayload := CreateProjectCommentRequest{ | ||
UserID: userID, | ||
Comment: "This is a test comment", | ||
} | ||
body, _ := json.Marshal(commentPayload) | ||
|
||
req := httptest.NewRequest(http.MethodPost, "/api/v1/projects/"+projectID+"/comments", bytes.NewReader(body)) | ||
req.Header.Set("Content-Type", "application/json") | ||
rec := httptest.NewRecorder() | ||
|
||
s.echoInstance.ServeHTTP(rec, req) | ||
t.Logf("Create comment response: %s", rec.Body.String()) | ||
assert.Equal(t, http.StatusCreated, rec.Code) | ||
|
||
var response map[string]interface{} | ||
err := json.NewDecoder(rec.Body).Decode(&response) | ||
assert.NoError(t, err) | ||
assert.Equal(t, projectID, response["ProjectID"]) | ||
assert.Equal(t, commentPayload.Comment, response["Comment"]) | ||
}) | ||
|
||
// test list comments | ||
t.Run("list comments", func(t *testing.T) { | ||
req := httptest.NewRequest(http.MethodGet, "/api/v1/projects/"+projectID+"/comments", nil) | ||
rec := httptest.NewRecorder() | ||
|
||
s.echoInstance.ServeHTTP(rec, req) | ||
t.Logf("List comments response: %s", rec.Body.String()) | ||
assert.Equal(t, http.StatusOK, rec.Code) | ||
|
||
var response []map[string]interface{} | ||
err := json.NewDecoder(rec.Body).Decode(&response) | ||
assert.NoError(t, err) | ||
assert.Len(t, response, 1) | ||
assert.Equal(t, "This is a test comment", response[0]["Comment"]) | ||
}) | ||
|
||
// test delete comment | ||
t.Run("delete comment", func(t *testing.T) { | ||
// Get the comment ID from the list response | ||
req := httptest.NewRequest(http.MethodGet, "/api/v1/projects/"+projectID+"/comments", nil) | ||
rec := httptest.NewRecorder() | ||
s.echoInstance.ServeHTTP(rec, req) | ||
|
||
var listResponse []map[string]interface{} | ||
err := json.NewDecoder(rec.Body).Decode(&listResponse) | ||
assert.NoError(t, err) | ||
assert.NotEmpty(t, listResponse) | ||
|
||
commentID := listResponse[0]["ID"].(string) | ||
|
||
// Delete the comment | ||
req = httptest.NewRequest(http.MethodDelete, "/api/v1/projects/comments/"+commentID, nil) | ||
rec = httptest.NewRecorder() | ||
|
||
s.echoInstance.ServeHTTP(rec, req) | ||
t.Logf("Delete comment response: %s", rec.Body.String()) | ||
assert.Equal(t, http.StatusNoContent, rec.Code) | ||
|
||
// Verify deletion | ||
req = httptest.NewRequest(http.MethodGet, "/api/v1/projects/"+projectID+"/comments", nil) | ||
rec = httptest.NewRecorder() | ||
|
||
s.echoInstance.ServeHTTP(rec, req) | ||
t.Logf("List comments after delete response: %s", rec.Body.String()) | ||
assert.Equal(t, http.StatusOK, rec.Code) | ||
|
||
var response []map[string]interface{} | ||
err = json.NewDecoder(rec.Body).Decode(&response) | ||
assert.NoError(t, err) | ||
assert.Len(t, response, 0, "Comment list should be empty after deletion") | ||
}) | ||
|
||
// test error cases | ||
t.Run("create comment with invalid project ID", func(t *testing.T) { | ||
commentPayload := CreateProjectCommentRequest{ | ||
UserID: userID, | ||
Comment: "This is a test comment", | ||
} | ||
body, _ := json.Marshal(commentPayload) | ||
|
||
req := httptest.NewRequest(http.MethodPost, "/api/v1/projects/invalid-uuid/comments", bytes.NewReader(body)) | ||
req.Header.Set("Content-Type", "application/json") | ||
rec := httptest.NewRecorder() | ||
|
||
s.echoInstance.ServeHTTP(rec, req) | ||
assert.Equal(t, http.StatusBadRequest, rec.Code) | ||
}) | ||
|
||
t.Run("create comment with invalid user ID", func(t *testing.T) { | ||
commentPayload := CreateProjectCommentRequest{ | ||
UserID: "invalid-uuid", | ||
Comment: "This is a test comment", | ||
} | ||
body, _ := json.Marshal(commentPayload) | ||
|
||
req := httptest.NewRequest(http.MethodPost, "/api/v1/projects/"+projectID+"/comments", bytes.NewReader(body)) | ||
req.Header.Set("Content-Type", "application/json") | ||
rec := httptest.NewRecorder() | ||
|
||
s.echoInstance.ServeHTTP(rec, req) | ||
assert.Equal(t, http.StatusBadRequest, rec.Code) | ||
}) | ||
|
||
t.Run("delete non-existent comment", func(t *testing.T) { | ||
nonExistentID := uuid.New().String() | ||
req := httptest.NewRequest(http.MethodDelete, "/api/v1/projects/comments/"+nonExistentID, nil) | ||
rec := httptest.NewRecorder() | ||
|
||
s.echoInstance.ServeHTTP(rec, req) | ||
assert.Equal(t, http.StatusNotFound, rec.Code) | ||
}) | ||
} |
Oops, something went wrong.