package tests import ( "bytes" "encoding/json" "gitea.pena/SQuiz/common/model" "github.com/stretchr/testify/assert" "net/http" "os" "sync" "testing" "time" ) var baseURL = os.Getenv("API_BASE_URL") var validToken = os.Getenv("VALID_JWT_TOKEN") var expiredToken = os.Getenv("EXPIRED_JWT_TOKEN") var validTokenForDelete = os.Getenv("VALID_JWT_TOKEN_FOR_DELETE") var validAdminToken = os.Getenv("VALID_ADMIN_JWT_TOKEN") var existingUserIDToken = os.Getenv("EXISTING_USER_ID_JWT_TOKEN") var userIDForDelete = os.Getenv("USER_ID_FOR_DELETE") var existingUserID = os.Getenv("EXISTING_USER_ID") var testUserID = os.Getenv("TEST_USER_ID") var sqlInjectionInput = "'; DROP TABLE accounts; --" var xssInput = "" func TestGetAccount_Success(t *testing.T) { req, err := http.NewRequest("GET", baseURL+"/account/get", nil) assert.NoError(t, err) req.Header.Set("Authorization", "Bearer "+validToken) client := &http.Client{Timeout: 5 * time.Second} resp, err := client.Do(req) assert.NoError(t, err) defer resp.Body.Close() assert.Equal(t, http.StatusOK, resp.StatusCode) assert.Equal(t, "application/json", resp.Header.Get("Content-Type")) var acc model.Account err = json.NewDecoder(resp.Body).Decode(&acc) assert.NoError(t, err) assert.NotEmpty(t, acc.ID) assert.NotEmpty(t, acc.UserID) assert.IsType(t, map[string]interface{}{}, acc.Privileges) } func TestGetAccount_Auth(t *testing.T) { t.Run("AccountNoToken", func(t *testing.T) { resp, err := http.Get(baseURL + "/account/get") assert.NoError(t, err) assert.Equal(t, http.StatusUnauthorized, resp.StatusCode) }) t.Run("AccountInvalidToken", func(t *testing.T) { req, err := http.NewRequest("GET", baseURL+"/account/get", nil) assert.NoError(t, err) req.Header.Set("Authorization", "Bearer invalid_token") resp, err := http.DefaultClient.Do(req) assert.NoError(t, err) assert.Equal(t, http.StatusUnauthorized, resp.StatusCode) }) t.Run("AccountExpiredToken", func(t *testing.T) { req, err := http.NewRequest("GET", baseURL+"/account/get", nil) assert.NoError(t, err) req.Header.Set("Authorization", "Bearer "+expiredToken) resp, err := http.DefaultClient.Do(req) assert.NoError(t, err) assert.Equal(t, http.StatusUnauthorized, resp.StatusCode) }) } func TestGetAccount_NotFound(t *testing.T) { t.Run("DeletedAccount", func(t *testing.T) { req, err := http.NewRequest("GET", baseURL+"/account/get", nil) assert.NoError(t, err) req.Header.Set("Authorization", "Bearer "+os.Getenv("DELETED_ACCOUNT_TOKEN")) resp, err := http.DefaultClient.Do(req) assert.NoError(t, err) assert.Equal(t, http.StatusNotFound, resp.StatusCode) }) } func TestGetAccount_Privileges(t *testing.T) { t.Run("NoPrivileges", func(t *testing.T) { req, err := http.NewRequest("GET", baseURL+"/account/get", nil) assert.NoError(t, err) req.Header.Set("Authorization", "Bearer "+os.Getenv("NO_PRIVILEGES_TOKEN")) resp, err := http.DefaultClient.Do(req) assert.NoError(t, err) defer resp.Body.Close() assert.Equal(t, http.StatusOK, resp.StatusCode) var acc model.Account err = json.NewDecoder(resp.Body).Decode(&acc) assert.NoError(t, err) assert.Empty(t, acc.Privileges) }) t.Run("MultiplePrivileges", func(t *testing.T) { req, err := http.NewRequest("GET", baseURL+"/account/get", nil) assert.NoError(t, err) req.Header.Set("Authorization", "Bearer "+os.Getenv("MULTI_PRIVILEGES_TOKEN")) resp, err := http.DefaultClient.Do(req) assert.NoError(t, err) defer resp.Body.Close() assert.Equal(t, http.StatusOK, resp.StatusCode) var acc model.Account err = json.NewDecoder(resp.Body).Decode(&acc) assert.NoError(t, err) assert.Greater(t, len(acc.Privileges), 1) }) } func TestAccount_Performance(t *testing.T) { t.Run("AccountResponseTime", func(t *testing.T) { start := time.Now() req, err := http.NewRequest("GET", baseURL+"/account/get", nil) assert.NoError(t, err) req.Header.Set("Authorization", "Bearer "+validToken) resp, err := http.DefaultClient.Do(req) assert.NoError(t, err) defer resp.Body.Close() duration := time.Since(start) assert.Less(t, duration.Milliseconds(), int64(500)) }) t.Run("AccountLoadTest", func(t *testing.T) { var wg sync.WaitGroup for i := 0; i < 100; i++ { wg.Add(1) go func() { defer wg.Done() req, err := http.NewRequest("GET", baseURL+"/account/get", nil) assert.NoError(t, err) req.Header.Set("Authorization", "Bearer "+validToken) resp, err := http.DefaultClient.Do(req) if err == nil { defer resp.Body.Close() } }() } wg.Wait() }) } // todo 1.3.6 1.3.7 1.3.8. 1.4 пока не знаю как делать надо подумать func TestCreateAccount(t *testing.T) { t.Run("Success", func(t *testing.T) { resp := createAccountRequest(t, validToken, map[string]interface{}{ "user_id": testUserID, }) defer resp.Body.Close() assert.Equal(t, http.StatusOK, resp.StatusCode) assert.Equal(t, "application/json", resp.Header.Get("Content-Type")) }) t.Run("MissingToken", func(t *testing.T) { req, err := http.NewRequest("POST", baseURL+"/account/create", nil) assert.NoError(t, err) resp, err := http.DefaultClient.Do(req) assert.NoError(t, err) assert.Equal(t, http.StatusUnauthorized, resp.StatusCode) }) t.Run("InvalidToken", func(t *testing.T) { resp := createAccountRequest(t, expiredToken, map[string]interface{}{ "user_id": "some-id", }) defer resp.Body.Close() assert.Equal(t, http.StatusUnauthorized, resp.StatusCode) }) t.Run("ExpiredToken", func(t *testing.T) { resp := createAccountRequest(t, expiredToken, map[string]interface{}{ "user_id": "some-id", }) defer resp.Body.Close() assert.Equal(t, http.StatusUnauthorized, resp.StatusCode) }) t.Run("Conflict_ExistingUserID", func(t *testing.T) { resp := createAccountRequest(t, validToken, map[string]interface{}{ "user_id": existingUserID, }) defer resp.Body.Close() assert.Equal(t, http.StatusConflict, resp.StatusCode) }) t.Run("EmptyJSON", func(t *testing.T) { resp := createAccountRequest(t, validToken, map[string]interface{}{}) defer resp.Body.Close() assert.Equal(t, http.StatusBadRequest, resp.StatusCode) }) t.Run("InvalidFormat", func(t *testing.T) { resp := createAccountRequest(t, validToken, map[string]interface{}{ "user_id": 123, }) defer resp.Body.Close() assert.Equal(t, http.StatusBadRequest, resp.StatusCode) }) t.Run("SQLInjection", func(t *testing.T) { resp := createAccountRequest(t, validToken, map[string]interface{}{ "user_id": sqlInjectionInput, }) defer resp.Body.Close() assert.NotEqual(t, http.StatusInternalServerError, resp.StatusCode) }) t.Run("XSSInjection", func(t *testing.T) { resp := createAccountRequest(t, validToken, map[string]interface{}{ "user_id": xssInput, }) defer resp.Body.Close() assert.NotEqual(t, http.StatusInternalServerError, resp.StatusCode) }) // todo 2.3.6 2.3.7 2.3.8 2.4 } func createAccountRequest(t *testing.T, token string, payload map[string]interface{}) *http.Response { body, err := json.Marshal(payload) assert.NoError(t, err) req, err := http.NewRequest("POST", baseURL+"/account/create", bytes.NewBuffer(body)) assert.NoError(t, err) req.Header.Set("Authorization", "Bearer "+token) req.Header.Set("Content-Type", "application/json") resp, err := http.DefaultClient.Do(req) assert.NoError(t, err) return resp } func TestDeleteAccount_Success(t *testing.T) { req, err := http.NewRequest("DELETE", baseURL+"/account/delete", nil) assert.NoError(t, err) req.Header.Set("Authorization", "Bearer "+validTokenForDelete) client := &http.Client{Timeout: 5 * time.Second} resp, err := client.Do(req) assert.NoError(t, err) defer resp.Body.Close() assert.Equal(t, http.StatusOK, resp.StatusCode) assert.Equal(t, "application/json", resp.Header.Get("Content-Type")) var result map[string]string err = json.NewDecoder(resp.Body).Decode(&result) assert.NoError(t, err) assert.NotEmpty(t, result["accountId"]) } func TestDeleteAccount_Auth(t *testing.T) { t.Run("NoToken", func(t *testing.T) { req, err := http.NewRequest("DELETE", baseURL+"/account/delete", nil) assert.NoError(t, err) resp, err := http.DefaultClient.Do(req) assert.NoError(t, err) assert.Equal(t, http.StatusUnauthorized, resp.StatusCode) }) t.Run("InvalidToken", func(t *testing.T) { req, err := http.NewRequest("DELETE", baseURL+"/account/delete", nil) assert.NoError(t, err) req.Header.Set("Authorization", "Bearer invalid_token") resp, err := http.DefaultClient.Do(req) assert.NoError(t, err) assert.Equal(t, http.StatusUnauthorized, resp.StatusCode) }) t.Run("ExpiredToken", func(t *testing.T) { req, err := http.NewRequest("DELETE", baseURL+"/account/delete", nil) assert.NoError(t, err) req.Header.Set("Authorization", "Bearer "+expiredToken) resp, err := http.DefaultClient.Do(req) assert.NoError(t, err) assert.Equal(t, http.StatusUnauthorized, resp.StatusCode) }) } func TestDeleteAccount_AlreadyDeleted(t *testing.T) { req, err := http.NewRequest("DELETE", baseURL+"/account/delete", nil) assert.NoError(t, err) req.Header.Set("Authorization", "Bearer "+validTokenForDelete) resp, err := http.DefaultClient.Do(req) assert.NoError(t, err) assert.Equal(t, http.StatusOK, resp.StatusCode) } func TestDeleteAccount_NonExistent(t *testing.T) { req, err := http.NewRequest("DELETE", baseURL+"/account/delete", nil) assert.NoError(t, err) req.Header.Set("Authorization", "Bearer "+validTokenForDelete) resp, err := http.DefaultClient.Do(req) assert.NoError(t, err) assert.Equal(t, http.StatusOK, resp.StatusCode) } // todo 3.3.4 3.3.5 func TestDeleteAccount_Performance(t *testing.T) { t.Run("ResponseTime", func(t *testing.T) { req, _ := http.NewRequest("DELETE", baseURL+"/account/delete", nil) req.Header.Set("Authorization", "Bearer "+validToken) start := time.Now() resp, err := http.DefaultClient.Do(req) assert.NoError(t, err) defer resp.Body.Close() duration := time.Since(start) assert.Less(t, duration.Milliseconds(), int64(500)) }) } func TestDeleteAccount_Load(t *testing.T) { var wg sync.WaitGroup for i := 0; i < 50; i++ { wg.Add(1) go func() { defer wg.Done() req, err := http.NewRequest("DELETE", baseURL+"/account/delete", nil) assert.NoError(t, err) req.Header.Set("Authorization", "Bearer "+validToken) resp, err := http.DefaultClient.Do(req) assert.NoError(t, err) if resp != nil { defer resp.Body.Close() } }() } wg.Wait() } // todo 3.3.7 3.3.8 3.4 func TestGetAccounts_Success(t *testing.T) { body := map[string]interface{}{ "limit": 10, "page": 1, } b, err := json.Marshal(body) assert.NoError(t, err) req, err := http.NewRequest("GET", baseURL+"/accounts", bytes.NewReader(b)) assert.NoError(t, err) req.Header.Set("Authorization", "Bearer "+validAdminToken) req.Header.Set("Content-Type", "application/json") client := &http.Client{} resp, err := client.Do(req) assert.NoError(t, err) defer resp.Body.Close() assert.Equal(t, http.StatusOK, resp.StatusCode) assert.Equal(t, "application/json", resp.Header.Get("Content-Type")) var result struct { Count uint64 `json:"count"` Items []model.Account `json:"items"` } err = json.NewDecoder(resp.Body).Decode(&result) assert.NoError(t, err) assert.LessOrEqual(t, len(result.Items), 2) for _, acc := range result.Items { assert.NotEmpty(t, acc.ID) assert.NotEmpty(t, acc.UserID) assert.NotEmpty(t, acc.CreatedAt) } } func TestGetAccounts_Auth(t *testing.T) { t.Run("NoToken", func(t *testing.T) { body := map[string]interface{}{ "limit": 10, "page": 1, } b, err := json.Marshal(body) assert.NoError(t, err) req, err := http.NewRequest("GET", baseURL+"/accounts", bytes.NewReader(b)) assert.NoError(t, err) req.Header.Set("Content-Type", "application/json") resp, err := http.DefaultClient.Do(req) assert.NoError(t, err) assert.Equal(t, http.StatusUnauthorized, resp.StatusCode) }) t.Run("InvalidToken", func(t *testing.T) { body := map[string]interface{}{ "limit": 10, "page": 1, } b, err := json.Marshal(body) assert.NoError(t, err) req, err := http.NewRequest("GET", baseURL+"/accounts", bytes.NewReader(b)) assert.NoError(t, err) req.Header.Set("Authorization", "Bearer invalid_token") req.Header.Set("Content-Type", "application/json") resp, err := http.DefaultClient.Do(req) assert.NoError(t, err) assert.Equal(t, http.StatusUnauthorized, resp.StatusCode) }) t.Run("ExpiredToken", func(t *testing.T) { body := map[string]interface{}{ "limit": 10, "page": 1, } b, err := json.Marshal(body) assert.NoError(t, err) req, err := http.NewRequest("GET", baseURL+"/accounts", bytes.NewReader(b)) assert.NoError(t, err) req.Header.Set("Authorization", "Bearer "+expiredToken) req.Header.Set("Content-Type", "application/json") resp, err := http.DefaultClient.Do(req) assert.NoError(t, err) assert.Equal(t, http.StatusUnauthorized, resp.StatusCode) }) } func TestGetAccounts_Pagination(t *testing.T) { t.Run("ValidPagination", func(t *testing.T) { body := map[string]interface{}{"limit": 5, "page": 1} b, err := json.Marshal(body) assert.NoError(t, err) req, err := http.NewRequest("GET", baseURL+"/accounts", bytes.NewReader(b)) assert.NoError(t, err) req.Header.Set("Authorization", "Bearer "+validAdminToken) req.Header.Set("Content-Type", "application/json") resp, err := http.DefaultClient.Do(req) assert.NoError(t, err) defer resp.Body.Close() assert.Equal(t, http.StatusOK, resp.StatusCode) }) // todo //t.Run("ZeroPagination", func(t *testing.T) { // body := map[string]interface{}{"limit": 0, "page": 0} // b, err := json.Marshal(body) // assert.NoError(t, err) // req, err := http.NewRequest("GET", baseURL+"/accounts", bytes.NewReader(b)) // assert.NoError(t, err) // req.Header.Set("Authorization", "Bearer "+validAdminToken) // req.Header.Set("Content-Type", "application/json") // // resp, err := http.DefaultClient.Do(req) // assert.NoError(t, err) // defer resp.Body.Close() // assert.Equal(t, http.StatusBadRequest, resp.StatusCode) //}) // todo //t.Run("TooHighLimit", func(t *testing.T) { // body := map[string]interface{}{"limit": 1000} // b, err := json.Marshal(body) // assert.NoError(t, err) // req, err := http.NewRequest("GET", baseURL+"/accounts", bytes.NewReader(b)) // assert.NoError(t, err) // req.Header.Set("Authorization", "Bearer "+validAdminToken) // req.Header.Set("Content-Type", "application/json") // // resp, err := http.DefaultClient.Do(req) // assert.NoError(t, err) // defer resp.Body.Close() // assert.Equal(t, http.StatusBadRequest, resp.StatusCode) //}) } // todo 4.3.4 4.3.5 func TestGetAccounts_Performance(t *testing.T) { t.Run("ResponseTimeUnder500ms", func(t *testing.T) { body := map[string]interface{}{"limit": 10, "page": 1} b, err := json.Marshal(body) assert.NoError(t, err) req, err := http.NewRequest("GET", baseURL+"/accounts", bytes.NewReader(b)) assert.NoError(t, err) req.Header.Set("Authorization", "Bearer "+validAdminToken) req.Header.Set("Content-Type", "application/json") start := time.Now() resp, err := http.DefaultClient.Do(req) duration := time.Since(start) assert.NoError(t, err) defer resp.Body.Close() assert.Less(t, duration.Milliseconds(), int64(500)) }) t.Run("LoadTest100Requests", func(t *testing.T) { var wg sync.WaitGroup for i := 0; i < 100; i++ { wg.Add(1) go func() { defer wg.Done() body := map[string]interface{}{"limit": 10, "page": 1} b, err := json.Marshal(body) assert.NoError(t, err) req, err := http.NewRequest("GET", baseURL+"/accounts", bytes.NewReader(b)) assert.NoError(t, err) req.Header.Set("Authorization", "Bearer "+validAdminToken) req.Header.Set("Content-Type", "application/json") resp, err := http.DefaultClient.Do(req) if err == nil { resp.Body.Close() } }() } wg.Wait() }) } // todo 4.3.7 4.3.8 4.4 func TestGetPrivilege_Success(t *testing.T) { body := map[string]string{"userId": existingUserID} data, err := json.Marshal(body) assert.NoError(t, err) req, err := http.NewRequest("GET", baseURL+"/privilege/"+existingUserID, bytes.NewBuffer(data)) assert.NoError(t, err) req.Header.Set("Authorization", "Bearer "+existingUserIDToken) req.Header.Set("Content-Type", "application/json") resp, err := http.DefaultClient.Do(req) assert.NoError(t, err) defer resp.Body.Close() assert.Equal(t, http.StatusOK, resp.StatusCode) assert.Equal(t, "application/json", resp.Header.Get("Content-Type")) var privileges []model.ShortPrivilege err = json.NewDecoder(resp.Body).Decode(&privileges) assert.NoError(t, err) for _, p := range privileges { assert.NotEmpty(t, p.ID) assert.NotEmpty(t, p.PrivilegeID) assert.NotEmpty(t, p.PrivilegeName) } } func TestGetPrivilege_Auth(t *testing.T) { t.Run("NoToken", func(t *testing.T) { req, err := http.NewRequest("GET", baseURL+"/privilege/"+existingUserID, nil) assert.NoError(t, err) resp, err := http.DefaultClient.Do(req) assert.NoError(t, err) assert.Equal(t, http.StatusUnauthorized, resp.StatusCode) }) t.Run("InvalidToken", func(t *testing.T) { req, err := http.NewRequest("GET", baseURL+"/privilege/"+existingUserID, nil) assert.NoError(t, err) req.Header.Set("Authorization", "Bearer invalid_token") resp, err := http.DefaultClient.Do(req) assert.NoError(t, err) assert.Equal(t, http.StatusUnauthorized, resp.StatusCode) }) t.Run("ExpiredToken", func(t *testing.T) { req, err := http.NewRequest("GET", baseURL+"/privilege/"+existingUserID, nil) assert.NoError(t, err) req.Header.Set("Authorization", "Bearer "+expiredToken) resp, err := http.DefaultClient.Do(req) assert.NoError(t, err) assert.Equal(t, http.StatusUnauthorized, resp.StatusCode) }) } func TestGetPrivilege_InputValidation(t *testing.T) { t.Run("MissingUserID", func(t *testing.T) { req, err := http.NewRequest("GET", baseURL+"/privilege/", nil) assert.NoError(t, err) req.Header.Set("Authorization", "Bearer "+validToken) resp, err := http.DefaultClient.Do(req) assert.NoError(t, err) assert.Equal(t, http.StatusNotFound, resp.StatusCode) }) t.Run("InvalidUserID", func(t *testing.T) { body := map[string]int{"userId": 111} data, err := json.Marshal(body) assert.NoError(t, err) req, err := http.NewRequest("GET", baseURL+"/privilege/!!!", bytes.NewBuffer(data)) assert.NoError(t, err) req.Header.Set("Authorization", "Bearer "+validToken) req.Header.Set("Content-Type", "application/json") resp, err := http.DefaultClient.Do(req) assert.NoError(t, err) assert.Equal(t, http.StatusBadRequest, resp.StatusCode) }) t.Run("NonExistentUserID", func(t *testing.T) { nonExistentID := "non_existent_user_123" body := map[string]string{"userId": nonExistentID} data, err := json.Marshal(body) assert.NoError(t, err) req, err := http.NewRequest("GET", baseURL+"/privilege/"+nonExistentID, bytes.NewBuffer(data)) assert.NoError(t, err) req.Header.Set("Authorization", "Bearer "+validToken) req.Header.Set("Content-Type", "application/json") resp, err := http.DefaultClient.Do(req) assert.NoError(t, err) defer resp.Body.Close() assert.Equal(t, http.StatusOK, resp.StatusCode) var privileges []model.ShortPrivilege err = json.NewDecoder(resp.Body).Decode(&privileges) assert.NoError(t, err) assert.Empty(t, privileges) }) } // todo 5.3.4 func TestGetPrivilege_Security(t *testing.T) { t.Run("SQLInjection", func(t *testing.T) { injection := "1' OR '1'='1" body := map[string]string{"userId": injection} data, err := json.Marshal(body) assert.NoError(t, err) req, err := http.NewRequest("GET", baseURL+"/privilege/"+injection, bytes.NewBuffer(data)) assert.NoError(t, err) req.Header.Set("Authorization", "Bearer "+validToken) req.Header.Set("Content-Type", "application/json") resp, err := http.DefaultClient.Do(req) assert.NoError(t, err) assert.Equal(t, http.StatusBadRequest, resp.StatusCode) }) t.Run("XSS", func(t *testing.T) { body := map[string]string{"userId": xssInput} data, err := json.Marshal(body) assert.NoError(t, err) req, err := http.NewRequest("GET", baseURL+"/privilege/"+xssInput, bytes.NewBuffer(data)) assert.NoError(t, err) req.Header.Set("Authorization", "Bearer "+validToken) req.Header.Set("Content-Type", "application/json") resp, err := http.DefaultClient.Do(req) assert.NoError(t, err) assert.Equal(t, http.StatusBadRequest, resp.StatusCode) }) } func TestGetPrivilege_Performance(t *testing.T) { t.Run("ResponseTime", func(t *testing.T) { body := map[string]string{"userId": existingUserID} data, err := json.Marshal(body) assert.NoError(t, err) start := time.Now() req, err := http.NewRequest("GET", baseURL+"/privilege/"+existingUserID, bytes.NewBuffer(data)) assert.NoError(t, err) req.Header.Set("Authorization", "Bearer "+existingUserIDToken) req.Header.Set("Content-Type", "application/json") resp, err := http.DefaultClient.Do(req) assert.NoError(t, err) defer resp.Body.Close() assert.Less(t, time.Since(start).Milliseconds(), int64(300)) }) t.Run("LoadTest", func(t *testing.T) { var wg sync.WaitGroup for i := 0; i < 100; i++ { wg.Add(1) go func() { defer wg.Done() body := map[string]string{"userId": existingUserID} data, err := json.Marshal(body) assert.NoError(t, err) req, err := http.NewRequest("GET", baseURL+"/privilege/"+existingUserID, bytes.NewBuffer(data)) assert.NoError(t, err) req.Header.Set("Authorization", "Bearer "+existingUserIDToken) req.Header.Set("Content-Type", "application/json") resp, err := http.DefaultClient.Do(req) assert.NoError(t, err) if resp != nil { defer resp.Body.Close() } }() } wg.Wait() }) } // todo 5.3.7 5.3.8 5.4 func deleteAccountByUserIDRequest(token string, body interface{}) (*http.Response, error) { payload, err := json.Marshal(body) if err != nil { return nil, err } req, err := http.NewRequest("DELETE", baseURL+"/account/"+body.(map[string]string)["userId"], bytes.NewReader(payload)) if err != nil { return nil, err } req.Header.Set("Authorization", "Bearer "+token) req.Header.Set("Content-Type", "application/json") return http.DefaultClient.Do(req) } func TestDeleteAccountByUserID_Success(t *testing.T) { resp, err := deleteAccountByUserIDRequest(validAdminToken, map[string]string{"userId": userIDForDelete}) assert.NoError(t, err) assert.Equal(t, http.StatusOK, resp.StatusCode) assert.Equal(t, "application/json", resp.Header.Get("Content-Type")) var result map[string]string err = json.NewDecoder(resp.Body).Decode(&result) assert.NoError(t, err) assert.Equal(t, testUserID, result["userId"]) } func TestDeleteAccountByUserID_Auth(t *testing.T) { t.Run("NoToken", func(t *testing.T) { req, err := http.NewRequest("DELETE", baseURL+"/account/"+userIDForDelete, nil) assert.NoError(t, err) resp, err := http.DefaultClient.Do(req) assert.NoError(t, err) assert.Equal(t, http.StatusUnauthorized, resp.StatusCode) }) t.Run("InvalidToken", func(t *testing.T) { resp, err := deleteAccountByUserIDRequest("invalid_token", map[string]string{"userId": userIDForDelete}) assert.NoError(t, err) assert.Equal(t, http.StatusUnauthorized, resp.StatusCode) }) t.Run("ExpiredToken", func(t *testing.T) { resp, err := deleteAccountByUserIDRequest(expiredToken, map[string]string{"userId": userIDForDelete}) assert.NoError(t, err) assert.Equal(t, http.StatusUnauthorized, resp.StatusCode) }) } func TestDeleteAccountByUserID_Validation(t *testing.T) { t.Run("EmptyBody", func(t *testing.T) { req, err := http.NewRequest("DELETE", baseURL+"/account/", bytes.NewReader([]byte(`{}`))) assert.NoError(t, err) req.Header.Set("Authorization", "Bearer "+validAdminToken) req.Header.Set("Content-Type", "application/json") resp, err := http.DefaultClient.Do(req) assert.NoError(t, err) assert.Equal(t, http.StatusBadRequest, resp.StatusCode) }) t.Run("InvalidUserID", func(t *testing.T) { resp, err := deleteAccountByUserIDRequest(validAdminToken, map[string]string{"userId": "invalid_id"}) assert.NoError(t, err) assert.Equal(t, http.StatusBadRequest, resp.StatusCode) }) } // todo 6.3.4 6.3.5 func TestDeleteAccountByUserID_SQLInjection_XSS(t *testing.T) { t.Run("SQLInjection", func(t *testing.T) { resp, err := deleteAccountByUserIDRequest(validAdminToken, map[string]string{"userId": sqlInjectionInput}) assert.NoError(t, err) assert.Equal(t, http.StatusBadRequest, resp.StatusCode) }) t.Run("XSS", func(t *testing.T) { resp, err := deleteAccountByUserIDRequest(validAdminToken, map[string]string{"userId": xssInput}) assert.NoError(t, err) assert.Equal(t, http.StatusBadRequest, resp.StatusCode) }) } // todo 6.3.7 6.3.8 6.3.9 6.4 func manualDoneRequest(token string, body map[string]string) (*http.Response, error) { payload, err := json.Marshal(body) if err != nil { return nil, err } req, err := http.NewRequest("POST", baseURL+"/account/manualdone", bytes.NewReader(payload)) if err != nil { return nil, err } req.Header.Set("Authorization", "Bearer "+token) req.Header.Set("Content-Type", "application/json") return http.DefaultClient.Do(req) } func TestManualDone_Success(t *testing.T) { resp, err := manualDoneRequest(validAdminToken, map[string]string{"id": testUserID}) assert.NoError(t, err) assert.Equal(t, http.StatusOK, resp.StatusCode) assert.Equal(t, "application/json", resp.Header.Get("Content-Type")) var result map[string]interface{} err = json.NewDecoder(resp.Body).Decode(&result) assert.NoError(t, err) assert.Equal(t, testUserID, result["id"]) } func TestManualDone_Auth(t *testing.T) { t.Run("NoToken", func(t *testing.T) { payload, err := json.Marshal(map[string]string{"id": testUserID}) assert.NoError(t, err) req, err := http.NewRequest("POST", baseURL+"/account/manualdone", bytes.NewReader(payload)) assert.NoError(t, err) req.Header.Set("Content-Type", "application/json") resp, err := http.DefaultClient.Do(req) assert.NoError(t, err) assert.Equal(t, http.StatusUnauthorized, resp.StatusCode) }) t.Run("InvalidToken", func(t *testing.T) { resp, err := manualDoneRequest("invalid_token", map[string]string{"id": testUserID}) assert.NoError(t, err) assert.Equal(t, http.StatusUnauthorized, resp.StatusCode) }) t.Run("ExpiredToken", func(t *testing.T) { resp, err := manualDoneRequest(expiredToken, map[string]string{"id": testUserID}) assert.NoError(t, err) assert.Equal(t, http.StatusUnauthorized, resp.StatusCode) }) } func TestManualDone_Validation(t *testing.T) { t.Run("EmptyBody", func(t *testing.T) { payload := []byte(`{}`) req, err := http.NewRequest("POST", baseURL+"/account/manualdone", bytes.NewReader(payload)) assert.NoError(t, err) req.Header.Set("Authorization", "Bearer "+validAdminToken) req.Header.Set("Content-Type", "application/json") resp, err := http.DefaultClient.Do(req) assert.NoError(t, err) assert.Equal(t, http.StatusBadRequest, resp.StatusCode) }) t.Run("InvalidID", func(t *testing.T) { resp, err := manualDoneRequest(validAdminToken, map[string]string{"id": "invalid_id"}) assert.NoError(t, err) assert.Equal(t, http.StatusBadRequest, resp.StatusCode) }) t.Run("NonExistentID", func(t *testing.T) { resp, err := manualDoneRequest(validAdminToken, map[string]string{"id": "nonexistent_id"}) assert.NoError(t, err) assert.Equal(t, http.StatusNotFound, resp.StatusCode) }) } // todo 7.3.4 7.3.5 func TestManualDone_Security(t *testing.T) { t.Run("SQLInjection", func(t *testing.T) { resp, err := manualDoneRequest(validAdminToken, map[string]string{"id": "1' OR '1'='1"}) assert.NoError(t, err) assert.Equal(t, http.StatusBadRequest, resp.StatusCode) }) t.Run("XSSAttack", func(t *testing.T) { resp, err := manualDoneRequest(validAdminToken, map[string]string{"id": ""}) assert.NoError(t, err) assert.Equal(t, http.StatusBadRequest, resp.StatusCode) }) } // todo 7.3.7 7.3.8 7.3.9 7.4