mirror of
https://github.com/bitechdev/ResolveSpec.git
synced 2026-03-07 05:58:55 +00:00
Initial Spec done. More work to do. Need to bring in Argitek designs
This commit is contained in:
232
tests/integration_test.go
Normal file
232
tests/integration_test.go
Normal file
@@ -0,0 +1,232 @@
|
||||
package test
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
// TestMain sets up the test environment
|
||||
func TestMain(m *testing.M) {
|
||||
TestSetup(m)
|
||||
}
|
||||
|
||||
func TestDepartmentEmployees(t *testing.T) {
|
||||
// Create test department
|
||||
deptPayload := map[string]interface{}{
|
||||
"operation": "create",
|
||||
"data": map[string]interface{}{
|
||||
"id": "dept1",
|
||||
"name": "Engineering",
|
||||
"code": "ENG",
|
||||
"description": "Engineering Department",
|
||||
},
|
||||
}
|
||||
|
||||
resp := makeRequest(t, "/test/departments", deptPayload)
|
||||
assert.Equal(t, http.StatusOK, resp.StatusCode)
|
||||
|
||||
// Create employees in department
|
||||
empPayload := map[string]interface{}{
|
||||
"operation": "create",
|
||||
"data": []map[string]interface{}{
|
||||
{
|
||||
"id": "emp1",
|
||||
"first_name": "John",
|
||||
"last_name": "Doe",
|
||||
"email": "john@example.com",
|
||||
"department_id": "dept1",
|
||||
"title": "Senior Engineer",
|
||||
},
|
||||
{
|
||||
"id": "emp2",
|
||||
"first_name": "Jane",
|
||||
"last_name": "Smith",
|
||||
"email": "jane@example.com",
|
||||
"department_id": "dept1",
|
||||
"title": "Engineer",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
resp = makeRequest(t, "/test/employees", empPayload)
|
||||
assert.Equal(t, http.StatusOK, resp.StatusCode)
|
||||
|
||||
// Read department with employees
|
||||
readPayload := map[string]interface{}{
|
||||
"operation": "read",
|
||||
"options": map[string]interface{}{
|
||||
"preload": []map[string]interface{}{
|
||||
{
|
||||
"relation": "employees",
|
||||
"columns": []string{"id", "first_name", "last_name", "title"},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
resp = makeRequest(t, "/test/departments/dept1", readPayload)
|
||||
assert.Equal(t, http.StatusOK, resp.StatusCode)
|
||||
|
||||
var result map[string]interface{}
|
||||
json.NewDecoder(resp.Body).Decode(&result)
|
||||
data := result["data"].(map[string]interface{})
|
||||
employees := data["employees"].([]interface{})
|
||||
assert.Equal(t, 2, len(employees))
|
||||
}
|
||||
|
||||
func TestEmployeeHierarchy(t *testing.T) {
|
||||
// Create manager
|
||||
mgrPayload := map[string]interface{}{
|
||||
"operation": "create",
|
||||
"data": map[string]interface{}{
|
||||
"id": "mgr1",
|
||||
"first_name": "Alice",
|
||||
"last_name": "Manager",
|
||||
"email": "alice@example.com",
|
||||
"title": "Engineering Manager",
|
||||
"department_id": "dept1",
|
||||
},
|
||||
}
|
||||
|
||||
resp := makeRequest(t, "/test/employees", mgrPayload)
|
||||
assert.Equal(t, http.StatusOK, resp.StatusCode)
|
||||
|
||||
// Update employees to set manager
|
||||
updatePayload := map[string]interface{}{
|
||||
"operation": "update",
|
||||
"data": map[string]interface{}{
|
||||
"manager_id": "mgr1",
|
||||
},
|
||||
}
|
||||
|
||||
resp = makeRequest(t, "/test/employees/emp1", updatePayload)
|
||||
assert.Equal(t, http.StatusOK, resp.StatusCode)
|
||||
resp = makeRequest(t, "/test/employees/emp2", updatePayload)
|
||||
assert.Equal(t, http.StatusOK, resp.StatusCode)
|
||||
|
||||
// Read manager with reports
|
||||
readPayload := map[string]interface{}{
|
||||
"operation": "read",
|
||||
"options": map[string]interface{}{
|
||||
"preload": []map[string]interface{}{
|
||||
{
|
||||
"relation": "reports",
|
||||
"columns": []string{"id", "first_name", "last_name", "title"},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
resp = makeRequest(t, "/test/employees/mgr1", readPayload)
|
||||
assert.Equal(t, http.StatusOK, resp.StatusCode)
|
||||
|
||||
var result map[string]interface{}
|
||||
json.NewDecoder(resp.Body).Decode(&result)
|
||||
data := result["data"].(map[string]interface{})
|
||||
reports := data["reports"].([]interface{})
|
||||
assert.Equal(t, 2, len(reports))
|
||||
}
|
||||
|
||||
func TestProjectStructure(t *testing.T) {
|
||||
// Create project
|
||||
projectPayload := map[string]interface{}{
|
||||
"operation": "create",
|
||||
"data": map[string]interface{}{
|
||||
"id": "proj1",
|
||||
"name": "New Website",
|
||||
"code": "WEB",
|
||||
"description": "Company website redesign",
|
||||
"status": "active",
|
||||
"start_date": time.Now().Format(time.RFC3339),
|
||||
"end_date": time.Now().AddDate(0, 3, 0).Format(time.RFC3339),
|
||||
"budget": 100000,
|
||||
},
|
||||
}
|
||||
|
||||
resp := makeRequest(t, "/test/projects", projectPayload)
|
||||
assert.Equal(t, http.StatusOK, resp.StatusCode)
|
||||
|
||||
// Create project tasks
|
||||
taskPayload := map[string]interface{}{
|
||||
"operation": "create",
|
||||
"data": []map[string]interface{}{
|
||||
{
|
||||
"id": "task1",
|
||||
"project_id": "proj1",
|
||||
"assignee_id": "emp1",
|
||||
"title": "Design Homepage",
|
||||
"description": "Create homepage design",
|
||||
"status": "in_progress",
|
||||
"priority": 1,
|
||||
"due_date": time.Now().AddDate(0, 1, 0).Format(time.RFC3339),
|
||||
},
|
||||
{
|
||||
"id": "task2",
|
||||
"project_id": "proj1",
|
||||
"assignee_id": "emp2",
|
||||
"title": "Implement Backend",
|
||||
"description": "Implement backend APIs",
|
||||
"status": "planned",
|
||||
"priority": 2,
|
||||
"due_date": time.Now().AddDate(0, 2, 0).Format(time.RFC3339),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
resp = makeRequest(t, "/test/project_tasks", taskPayload)
|
||||
assert.Equal(t, http.StatusOK, resp.StatusCode)
|
||||
|
||||
// Create task comments
|
||||
commentPayload := map[string]interface{}{
|
||||
"operation": "create",
|
||||
"data": map[string]interface{}{
|
||||
"id": "comment1",
|
||||
"task_id": "task1",
|
||||
"author_id": "mgr1",
|
||||
"content": "Looking good! Please add more animations.",
|
||||
},
|
||||
}
|
||||
|
||||
resp = makeRequest(t, "/test/comments", commentPayload)
|
||||
assert.Equal(t, http.StatusOK, resp.StatusCode)
|
||||
|
||||
// Read project with all relations
|
||||
readPayload := map[string]interface{}{
|
||||
"operation": "read",
|
||||
"options": map[string]interface{}{
|
||||
"preload": []map[string]interface{}{
|
||||
{
|
||||
"relation": "tasks",
|
||||
"columns": []string{"id", "title", "status", "assignee_id"},
|
||||
"preload": []map[string]interface{}{
|
||||
{
|
||||
"relation": "comments",
|
||||
"columns": []string{"id", "content", "author_id"},
|
||||
"preload": []map[string]interface{}{
|
||||
{
|
||||
"relation": "author",
|
||||
"columns": []string{"id", "first_name", "last_name"},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
"relation": "assignee",
|
||||
"columns": []string{"id", "first_name", "last_name", "title"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
resp = makeRequest(t, "/test/projects/proj1", readPayload)
|
||||
assert.Equal(t, http.StatusOK, resp.StatusCode)
|
||||
|
||||
var result map[string]interface{}
|
||||
json.NewDecoder(resp.Body).Decode(&result)
|
||||
assert.True(t, result["success"].(bool))
|
||||
}
|
||||
152
tests/test_helpers.go
Normal file
152
tests/test_helpers.go
Normal file
@@ -0,0 +1,152 @@
|
||||
package test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/Warky-Devs/ResolveSpec/pkg/logger"
|
||||
"github.com/Warky-Devs/ResolveSpec/pkg/models"
|
||||
"github.com/Warky-Devs/ResolveSpec/pkg/resolvespec"
|
||||
"github.com/Warky-Devs/ResolveSpec/pkg/testmodels"
|
||||
"github.com/glebarez/sqlite"
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
var (
|
||||
testDB *gorm.DB
|
||||
testServer *httptest.Server
|
||||
testServerURL string
|
||||
)
|
||||
|
||||
// makeRequest is a helper function to make HTTP requests in tests
|
||||
func makeRequest(t *testing.T, path string, payload interface{}) *http.Response {
|
||||
jsonData, err := json.Marshal(payload)
|
||||
assert.NoError(t, err, "Failed to marshal request payload")
|
||||
|
||||
logger.Debug("Making request to %s with payload: %s", path, string(jsonData))
|
||||
|
||||
req, err := http.NewRequest("POST", testServerURL+path, bytes.NewBuffer(jsonData))
|
||||
assert.NoError(t, err, "Failed to create request")
|
||||
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
|
||||
client := &http.Client{}
|
||||
resp, err := client.Do(req)
|
||||
assert.NoError(t, err, "Failed to execute request")
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
body, _ := io.ReadAll(resp.Body)
|
||||
logger.Error("Request failed with status %d: %s", resp.StatusCode, string(body))
|
||||
} else {
|
||||
logger.Debug("Request successful with status %d", resp.StatusCode)
|
||||
}
|
||||
|
||||
return resp
|
||||
}
|
||||
|
||||
// verifyResponse is a helper function to verify response status and decode body
|
||||
func verifyResponse(t *testing.T, resp *http.Response) map[string]interface{} {
|
||||
assert.Equal(t, http.StatusOK, resp.StatusCode, "Unexpected response status")
|
||||
|
||||
var result map[string]interface{}
|
||||
err := json.NewDecoder(resp.Body).Decode(&result)
|
||||
assert.NoError(t, err, "Failed to decode response")
|
||||
assert.True(t, result["success"].(bool), "Response indicates failure")
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
// TestSetup initializes the test environment
|
||||
func TestSetup(m *testing.M) int {
|
||||
logger.Init(true)
|
||||
|
||||
logger.Info("Setting up test environment")
|
||||
|
||||
// Create test database
|
||||
db, err := setupTestDB()
|
||||
if err != nil {
|
||||
logger.Error("Failed to setup test database: %v", err)
|
||||
return 1
|
||||
}
|
||||
testDB = db
|
||||
|
||||
// Setup test server
|
||||
router := setupTestRouter(testDB)
|
||||
testServer = httptest.NewServer(router)
|
||||
|
||||
fmt.Printf("ResolveSpec test server starting on %s\n", testServer.URL)
|
||||
testServerURL = testServer.URL
|
||||
|
||||
defer testServer.Close()
|
||||
|
||||
// Run tests
|
||||
code := m.Run()
|
||||
|
||||
// Cleanup
|
||||
logger.Info("Cleaning up test environment")
|
||||
cleanup()
|
||||
return code
|
||||
}
|
||||
|
||||
// setupTestDB creates and initializes the test database
|
||||
func setupTestDB() (*gorm.DB, error) {
|
||||
db, err := gorm.Open(sqlite.Open("file::memory:?cache=shared"), &gorm.Config{})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to open database: %v", err)
|
||||
}
|
||||
|
||||
// Init Models
|
||||
testmodels.RegisterTestModels()
|
||||
|
||||
// Auto migrate all test models
|
||||
err = autoMigrateModels(db)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to migrate models: %v", err)
|
||||
}
|
||||
|
||||
return db, nil
|
||||
}
|
||||
|
||||
// setupTestRouter creates and configures the test router
|
||||
func setupTestRouter(db *gorm.DB) http.Handler {
|
||||
r := mux.NewRouter()
|
||||
handler := resolvespec.NewAPIHandler(db)
|
||||
|
||||
r.HandleFunc("/{schema}/{entity}", func(w http.ResponseWriter, r *http.Request) {
|
||||
vars := mux.Vars(r)
|
||||
handler.Handle(w, r, vars)
|
||||
}).Methods("POST")
|
||||
|
||||
r.HandleFunc("/{schema}/{entity}/{id}", func(w http.ResponseWriter, r *http.Request) {
|
||||
vars := mux.Vars(r)
|
||||
handler.Handle(w, r, vars)
|
||||
}).Methods("POST")
|
||||
|
||||
return r
|
||||
}
|
||||
|
||||
// cleanup performs test cleanup
|
||||
func cleanup() {
|
||||
if testDB != nil {
|
||||
db, err := testDB.DB()
|
||||
if err == nil {
|
||||
db.Close()
|
||||
}
|
||||
}
|
||||
os.Remove("test.db")
|
||||
}
|
||||
|
||||
// autoMigrateModels performs automigration for all test models
|
||||
func autoMigrateModels(db *gorm.DB) error {
|
||||
modelList := models.GetModels()
|
||||
return db.AutoMigrate(modelList...)
|
||||
}
|
||||
Reference in New Issue
Block a user