From 0c2617d0cb9dd03a73005bb6347d16ac7fd3ddc1 Mon Sep 17 00:00:00 2001
From: Imbus <>
Date: Mon, 18 Mar 2024 16:42:35 +0100
Subject: [PATCH] Full fix for getProject route, testing, integration testing
 and frontend-API code

---
 backend/internal/database/db.go               |  5 +++-
 backend/internal/database/db_test.go          | 30 +++++++++++++++++++
 backend/internal/handlers/global_state.go     |  1 +
 .../handlers/handlers_project_related.go      |  5 ++++
 backend/main.go                               |  1 +
 frontend/src/API/API.ts                       | 27 +++++++++++++++++
 testing.py                                    | 15 +++++++++-
 7 files changed, 82 insertions(+), 2 deletions(-)

diff --git a/backend/internal/database/db.go b/backend/internal/database/db.go
index 5cbb13f..a5360e6 100644
--- a/backend/internal/database/db.go
+++ b/backend/internal/database/db.go
@@ -106,7 +106,10 @@ func (d *Db) GetAllProjects() ([]types.Project, error) {
 // GetProject retrieves a specific project by its ID.
 func (d *Db) GetProject(projectId int) (types.Project, error) {
 	var project types.Project
-	err := d.Select(&project, "SELECT * FROM projects WHERE id = ?")
+	err := d.Get(&project, "SELECT * FROM projects WHERE id = ?", projectId)
+	if err != nil {
+		println("Error getting project: ", err)
+	}
 	return project, err
 }
 
diff --git a/backend/internal/database/db_test.go b/backend/internal/database/db_test.go
index 09de45b..a7f3878 100644
--- a/backend/internal/database/db_test.go
+++ b/backend/internal/database/db_test.go
@@ -536,3 +536,33 @@ func TestSignWeeklyReportByAnotherProjectManager(t *testing.T) {
 		t.Error("Expected SignWeeklyReport to fail with a project manager who is not in the project, but it didn't")
 	}
 }
+
+func TestGetProject(t *testing.T) {
+	db, err := setupState()
+	if err != nil {
+		t.Error("setupState failed:", err)
+	}
+
+	// Add a user
+	err = db.AddUser("testuser", "password")
+	if err != nil {
+		t.Error("AddUser failed:", err)
+	}
+
+	// Add a project
+	err = db.AddProject("testproject", "description", "testuser")
+	if err != nil {
+		t.Error("AddProject failed:", err)
+	}
+
+	// Retrieve the added project
+	project, err := db.GetProject(1)
+	if err != nil {
+		t.Error("GetProject failed:", err)
+	}
+
+	// Check if the retrieved project matches the expected values
+	if project.Name != "testproject" {
+		t.Errorf("Expected Name to be testproject, got %s", project.Name)
+	}
+}
diff --git a/backend/internal/handlers/global_state.go b/backend/internal/handlers/global_state.go
index c8beb1c..92bc19d 100644
--- a/backend/internal/handlers/global_state.go
+++ b/backend/internal/handlers/global_state.go
@@ -17,6 +17,7 @@ type GlobalState interface {
 	SubmitWeeklyReport(c *fiber.Ctx) error
 	GetWeeklyReport(c *fiber.Ctx) error
 	SignReport(c *fiber.Ctx) error
+	GetProject(c *fiber.Ctx) error
 	// GetProject(c *fiber.Ctx) error           // To get a specific project
 	// UpdateProject(c *fiber.Ctx) error        // To update a project
 	// DeleteProject(c *fiber.Ctx) error        // To delete a project
diff --git a/backend/internal/handlers/handlers_project_related.go b/backend/internal/handlers/handlers_project_related.go
index 6a430e9..d779663 100644
--- a/backend/internal/handlers/handlers_project_related.go
+++ b/backend/internal/handlers/handlers_project_related.go
@@ -66,6 +66,10 @@ func (gs *GState) ProjectRoleChange(c *fiber.Ctx) error {
 func (gs *GState) GetProject(c *fiber.Ctx) error {
 	// Extract the project ID from the request parameters or body
 	projectID := c.Params("projectID")
+	if projectID == "" {
+		return c.Status(400).SendString("No project ID provided")
+	}
+	println("Getting project with ID: ", projectID)
 
 	// Parse the project ID into an integer
 	projectIDInt, err := strconv.Atoi(projectID)
@@ -80,6 +84,7 @@ func (gs *GState) GetProject(c *fiber.Ctx) error {
 	}
 
 	// Return the project as JSON
+	println("Returning project: ", project.Name)
 	return c.JSON(project)
 }
 
diff --git a/backend/main.go b/backend/main.go
index bc33942..920696b 100644
--- a/backend/main.go
+++ b/backend/main.go
@@ -78,6 +78,7 @@ func main() {
 	server.Post("/api/loginrenew", gs.LoginRenew)
 	server.Delete("/api/userdelete/:username", gs.UserDelete) // Perhaps just use POST to avoid headaches
 	server.Post("/api/project", gs.CreateProject)
+	server.Get("/api/project/:projectId", gs.GetProject)
 	server.Get("/api/getWeeklyReport", gs.GetWeeklyReport)
 
 	// Announce the port we are listening on and start the server
diff --git a/frontend/src/API/API.ts b/frontend/src/API/API.ts
index ac0f531..e8566b6 100644
--- a/frontend/src/API/API.ts
+++ b/frontend/src/API/API.ts
@@ -46,6 +46,7 @@ interface API {
     username: string,
     token: string,
   ): Promise<APIResponse<Project[]>>;
+  getProject(id: number): Promise<APIResponse<Project>>;
 }
 
 // Export an instance of the API
@@ -253,4 +254,30 @@ export const api: API = {
       return Promise.resolve({ success: false, message: "Failed to login" });
     }
   },
+
+  // Gets a projet by id, currently untested since we have no javascript-based tests
+  async getProject(id: number): Promise<APIResponse<Project>> {
+    try {
+      const response = await fetch(`/api/project/${id}`, {
+        method: "GET",
+      });
+
+      if (!response.ok) {
+        return {
+          success: false,
+          message: "Failed to get project: Response code " + response.status,
+        };
+      } else {
+        const data = (await response.json()) as Project;
+        return { success: true, data };
+      }
+      // The code below is garbage but satisfies the linter
+      // This needs fixing, do not copy this pattern
+    } catch (e: unknown) {
+      return {
+        success: false,
+        message: "Failed to get project: " + (e as Error).toString(),
+      };
+    }
+  },
 };
diff --git a/testing.py b/testing.py
index 38d09cc..fd4ec74 100644
--- a/testing.py
+++ b/testing.py
@@ -22,6 +22,7 @@ loginPath = base_url + "/api/login"
 addProjectPath = base_url + "/api/project"
 submitReportPath = base_url + "/api/submitReport"
 getWeeklyReportPath = base_url + "/api/getWeeklyReport"
+getProjectPath = base_url + "/api/project"
 
 
 # Posts the username and password to the register endpoint
@@ -98,10 +99,22 @@ def test_get_weekly_report():
         params={"username": username, "projectName": projectName , "week": 1}
     )
     print(response.text)
+    assert response.status_code == 200, "Get weekly report failed"
+
+# Tests getting a project by id
+def test_get_project():
+    token = login(username, "always_same").json()["token"]
+    response = requests.get(
+        getProjectPath + "/1", # Assumes that the project with id 1 exists
+        headers={"Authorization": "Bearer " + token},
+    )
+    print(response.text)
+    assert response.status_code == 200, "Get project failed"
 
 if __name__ == "__main__":
     test_create_user()
     test_login()
     test_add_project()
     test_submit_report()
-    test_get_weekly_report()
\ No newline at end of file
+    test_get_weekly_report()
+    test_get_project()
\ No newline at end of file