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

[Integration Tests] - /bounties/ticket/review/send #2211

Open
tomsmith8 opened this issue Dec 17, 2024 · 5 comments
Open

[Integration Tests] - /bounties/ticket/review/send #2211

tomsmith8 opened this issue Dec 17, 2024 · 5 comments
Assignees

Comments

@tomsmith8
Copy link

Integration Test Coverage for "/bounties/ticket/review/send"


Stakwork Run


Integration Test Code


File: routes/ticket_routes.go


package handlers

import (
  "bytes"
  "context"
  "encoding/json"
  "errors"
  "fmt"
  "io/ioutil"
  "net/http"
  "net/http/httptest"
  "os"
  "testing"

  "github.com/go-chi/chi"
  "github.com/google/uuid"
  "github.com/stretchr/testify/assert"
  "github.com/stretchr/testify/mock"
)

// Mocking the HTTP client
type MockHttpClient struct {
  mock.Mock
}

func (m *MockHttpClient) Do(req *http.Request) (*http.Response, error) {
  args := m.Called(req)
  return args.Get(0).(*http.Response), args.Error(1)
}

// Mocking the WebSocket pool
type MockWebsocketPool struct {
  mock.Mock
}

func (m *MockWebsocketPool) SendTicketMessage(message TicketMessage) error {
  args := m.Called(message)
  return args.Error(0)
}

// Setup function to initialize environment variables and mocks
func setupTestEnv() (*MockHttpClient, *MockWebsocketPool) {
  os.Setenv("HOST", "http://localhost")
  os.Setenv("SWWFKEY", "test-api-key")

  mockHttpClient := new(MockHttpClient)
  mockWebsocketPool := new(MockWebsocketPool)

  return mockHttpClient, mockWebsocketPool
}

// Test for successful ticket submission
func TestSuccessfulTicketSubmission(t *testing.T) {
  mockHttpClient, _ := setupTestEnv()
  tHandler := NewTicketHandler(mockHttpClient, db.TestDB)

  ticketRequest := UpdateTicketRequest{
  	Ticket: &db.Tickets{
  		UUID:        uuid.New(),
  		FeatureUUID: uuid.New().String(),
  		Name:        "Test Ticket",
  		Description: "Test Description",
  	},
  }

  body, _ := json.Marshal(ticketRequest)
  req, err := setupTestRequest(http.MethodPost, "/bounties/ticket/review/send", body, map[interface{}]interface{}{auth.ContextKey: "valid-pubkey"})
  assert.NoError(t, err)

  rr := httptest.NewRecorder()
  handler := http.HandlerFunc(tHandler.PostTicketDataToStakwork)

  mockHttpClient.On("Do", mock.Anything).Return(&http.Response{
  	StatusCode: http.StatusOK,
  	Body:       ioutil.NopCloser(bytes.NewBufferString(`{"success": true, "data": {"project_id": 12345}}`)),
  }, nil)

  handler.ServeHTTP(rr, req)
  assert.Equal(t, http.StatusOK, rr.Code)

  var response TicketResponse
  assert.NoError(t, json.Unmarshal(rr.Body.Bytes(), &response))
  assert.True(t, response.Success)
  assert.Equal(t, ticketRequest.Ticket.UUID.String(), response.TicketID)
}

// Test for ticket submission with WebSocket notification
func TestTicketSubmissionWithWebSocketNotification(t *testing.T) {
  mockHttpClient, mockWebsocketPool := setupTestEnv()
  tHandler := NewTicketHandler(mockHttpClient, db.TestDB)

  ticketRequest := UpdateTicketRequest{
  	Ticket: &db.Tickets{
  		UUID:        uuid.New(),
  		FeatureUUID: uuid.New().String(),
  		Name:        "Test Ticket",
  		Description: "Test Description",
  	},
  	Metadata: Metadata{
  		Source: "websocket",
  		ID:     "test-session-id",
  	},
  }

  body, _ := json.Marshal(ticketRequest)
  req, err := setupTestRequest(http.MethodPost, "/bounties/ticket/review/send", body, map[interface{}]interface{}{auth.ContextKey: "valid-pubkey"})
  assert.NoError(t, err)

  rr := httptest.NewRecorder()
  handler := http.HandlerFunc(tHandler.PostTicketDataToStakwork)

  mockHttpClient.On("Do", mock.Anything).Return(&http.Response{
  	StatusCode: http.StatusOK,
  	Body:       ioutil.NopCloser(bytes.NewBufferString(`{"success": true, "data": {"project_id": 12345}}`)),
  }, nil)

  mockWebsocketPool.On("SendTicketMessage", mock.Anything).Return(nil)

  handler.ServeHTTP(rr, req)
  assert.Equal(t, http.StatusOK, rr.Code)

  var response TicketResponse
  assert.NoError(t, json.Unmarshal(rr.Body.Bytes(), &response))
  assert.True(t, response.Success)
}

// Test for missing authorization key
func TestMissingAuthorizationKey(t *testing.T) {
  _, _ = setupTestEnv()
  tHandler := NewTicketHandler(&http.Client{}, db.TestDB)

  ticketRequest := UpdateTicketRequest{
  	Ticket: &db.Tickets{
  		UUID:        uuid.New(),
  		FeatureUUID: uuid.New().String(),
  		Name:        "Test Ticket",
  		Description: "Test Description",
  	},
  }

  body, _ := json.Marshal(ticketRequest)
  req, err := setupTestRequest(http.MethodPost, "/bounties/ticket/review/send", body, nil)
  assert.NoError(t, err)

  rr := httptest.NewRecorder()
  handler := http.HandlerFunc(tHandler.PostTicketDataToStakwork)

  handler.ServeHTTP(rr, req)
  assert.Equal(t, http.StatusUnauthorized, rr.Code)
}

// Test for invalid JSON in request body
func TestInvalidJSONInRequestBody(t *testing.T) {
  _, _ = setupTestEnv()
  tHandler := NewTicketHandler(&http.Client{}, db.TestDB)

  req, err := setupTestRequest(http.MethodPost, "/bounties/ticket/review/send", []byte("invalid-json"), map[interface{}]interface{}{auth.ContextKey: "valid-pubkey"})
  assert.NoError(t, err)

  rr := httptest.NewRecorder()
  handler := http.HandlerFunc(tHandler.PostTicketDataToStakwork)

  handler.ServeHTTP(rr, req)
  assert.Equal(t, http.StatusBadRequest, rr.Code)
}

// Test for missing ticket data
func TestMissingTicketData(t *testing.T) {
  _, _ = setupTestEnv()
  tHandler := NewTicketHandler(&http.Client{}, db.TestDB)

  ticketRequest := UpdateTicketRequest{
  	Ticket: nil,
  }

  body, _ := json.Marshal(ticketRequest)
  req, err := setupTestRequest(http.MethodPost, "/bounties/ticket/review/send", body, map[interface{}]interface{}{auth.ContextKey: "valid-pubkey"})
  assert.NoError(t, err)

  rr := httptest.NewRecorder()
  handler := http.HandlerFunc(tHandler.PostTicketDataToStakwork)

  handler.ServeHTTP(rr, req)
  assert.Equal(t, http.StatusBadRequest, rr.Code)
}

// Test for database error on feature retrieval
func TestDatabaseErrorOnFeatureRetrieval(t *testing.T) {
  _, _ = setupTestEnv()
  tHandler := NewTicketHandler(&http.Client{}, db.TestDB)

  ticketRequest := UpdateTicketRequest{
  	Ticket: &db.Tickets{
  		UUID:        uuid.New(),
  		FeatureUUID: "non-existent-uuid",
  		Name:        "Test Ticket",
  		Description: "Test Description",
  	},
  }

  body, _ := json.Marshal(ticketRequest)
  req, err := setupTestRequest(http.MethodPost, "/bounties/ticket/review/send", body, map[interface{}]interface{}{auth.ContextKey: "valid-pubkey"})
  assert.NoError(t, err)

  rr := httptest.NewRecorder()
  handler := http.HandlerFunc(tHandler.PostTicketDataToStakwork)

  handler.ServeHTTP(rr, req)
  assert.Equal(t, http.StatusInternalServerError, rr.Code)
}

// Test for environment variable not set
func TestEnvironmentVariableNotSet(t *testing.T) {
  os.Unsetenv("HOST")
  _, _ = setupTestEnv()
  tHandler := NewTicketHandler(&http.Client{}, db.TestDB)

  ticketRequest := UpdateTicketRequest{
  	Ticket: &db.Tickets{
  		UUID:        uuid.New(),
  		FeatureUUID: uuid.New().String(),
  		Name:        "Test Ticket",
  		Description: "Test Description",
  	},
  }

  body, _ := json.Marshal(ticketRequest)
  req, err := setupTestRequest(http.MethodPost, "/bounties/ticket/review/send", body, map[interface{}]interface{}{auth.ContextKey: "valid-pubkey"})
  assert.NoError(t, err)

  rr := httptest.NewRecorder()
  handler := http.HandlerFunc(tHandler.PostTicketDataToStakwork)

  handler.ServeHTTP(rr, req)
  assert.Equal(t, http.StatusInternalServerError, rr.Code)
}

// Test for HTTP client error
func TestHttpClientError(t *testing.T) {
  mockHttpClient, _ := setupTestEnv()
  tHandler := NewTicketHandler(mockHttpClient, db.TestDB)

  ticketRequest := UpdateTicketRequest{
  	Ticket: &db.Tickets{
  		UUID:        uuid.New(),
  		FeatureUUID: uuid.New().String(),
  		Name:        "Test Ticket",
  		Description: "Test Description",
  	},
  }

  body, _ := json.Marshal(ticketRequest)
  req, err := setupTestRequest(http.MethodPost, "/bounties/ticket/review/send", body, map[interface{}]interface{}{auth.ContextKey: "valid-pubkey"})
  assert.NoError(t, err)

  rr := httptest.NewRecorder()
  handler := http.HandlerFunc(tHandler.PostTicketDataToStakwork)

  mockHttpClient.On("Do", mock.Anything).Return(nil, errors.New("http client error"))

  handler.ServeHTTP(rr, req)
  assert.Equal(t, http.StatusInternalServerError, rr.Code)
}

// Test for WebSocket client not found
func TestWebSocketClientNotFound(t *testing.T) {
  mockHttpClient, mockWebsocketPool := setupTestEnv()
  tHandler := NewTicketHandler(mockHttpClient, db.TestDB)

  ticketRequest := UpdateTicketRequest{
  	Ticket: &db.Tickets{
  		UUID:        uuid.New(),
  		FeatureUUID: uuid.New().String(),
  		Name:        "Test Ticket",
  		Description: "Test Description",
  	},
  	Metadata: Metadata{
  		Source: "websocket",
  		ID:     "non-existent-session-id",
  	},
  }

  body, _ := json.Marshal(ticketRequest)
  req, err := setupTestRequest(http.MethodPost, "/bounties/ticket/review/send", body, map[interface{}]interface{}{auth.ContextKey: "valid-pubkey"})
  assert.NoError(t, err)

  rr := httptest.NewRecorder()
  handler := http.HandlerFunc(tHandler.PostTicketDataToStakwork)

  mockHttpClient.On("Do", mock.Anything).Return(&http.Response{
  	StatusCode: http.StatusOK,
  	Body:       ioutil.NopCloser(bytes.NewBufferString(`{"success": true, "data": {"project_id": 12345}}`)),
  }, nil)

  mockWebsocketPool.On("SendTicketMessage", mock.Anything).Return(errors.New("client not found"))

  handler.ServeHTTP(rr, req)
  assert.Equal(t, http.StatusOK, rr.Code)

  var response map[string]interface{}
  assert.NoError(t, json.Unmarshal(rr.Body.Bytes(), &response))
  assert.Contains(t, response, "websocket_error")
}

// Test for large payload handling
func TestLargePayloadHandling(t *testing.T) {
  mockHttpClient, _ := setupTestEnv()
  tHandler := NewTicketHandler(mockHttpClient, db.TestDB)

  largeDescription := make([]byte, 10*1024*1024) // 10MB payload
  ticketRequest := UpdateTicketRequest{
  	Ticket: &db.Tickets{
  		UUID:        uuid.New(),
  		FeatureUUID: uuid.New().String(),
  		Name:        "Test Ticket",
  		Description: string(largeDescription),
  	},
  }

  body, _ := json.Marshal(ticketRequest)
  req, err := setupTestRequest(http.MethodPost, "/bounties/ticket/review/send", body, map[interface{}]interface{}{auth.ContextKey: "valid-pubkey"})
  assert.NoError(t, err)

  rr := httptest.NewRecorder()
  handler := http.HandlerFunc(tHandler.PostTicketDataToStakwork)

  mockHttpClient.On("Do", mock.Anything).Return(&http.Response{
  	StatusCode: http.StatusOK,
  	Body:       ioutil.NopCloser(bytes.NewBufferString(`{"success": true, "data": {"project_id": 12345}}`)),
  }, nil)

  handler.ServeHTTP(rr, req)
  assert.Equal(t, http.StatusOK, rr.Code)
}

// Test for concurrent requests
func TestConcurrentRequests(t *testing.T) {
  mockHttpClient, _ := setupTestEnv()
  tHandler := NewTicketHandler(mockHttpClient, db.TestDB)

  ticketRequest := UpdateTicketRequest{
  	Ticket: &db.Tickets{
  		UUID:        uuid.New(),
  		FeatureUUID: uuid.New().String(),
  		Name:        "Test Ticket",
  		Description: "Test Description",
  	},
  }

  body, _ := json.Marshal(ticketRequest)

  mockHttpClient.On("Do", mock.Anything).Return(&http.Response{
  	StatusCode: http.StatusOK,
  	Body:       ioutil.NopCloser(bytes.NewBufferString(`{"success": true, "data": {"project_id": 12345}}`)),
  }, nil)

  for i := 0; i < 10; i++ {
  	t.Run(fmt.Sprintf("concurrent request %d", i), func(t *testing.T) {
  		t.Parallel()
  		req, err := setupTestRequest(http.MethodPost, "/bounties/ticket/review/send", body, map[interface{}]interface{}{auth.ContextKey: "valid-pubkey"})
  		assert.NoError(t, err)

  		rr := httptest.NewRecorder()
  		handler := http.HandlerFunc(tHandler.PostTicketDataToStakwork)

  		handler.ServeHTTP(rr, req)
  		assert.Equal(t, http.StatusOK, rr.Code)
  	})
  }
}

// Test for invalid UUID format
func TestInvalidUUIDFormat(t *testing.T) {
  _, _ = setupTestEnv()
  tHandler := NewTicketHandler(&http.Client{}, db.TestDB)

  ticketRequest := UpdateTicketRequest{
  	Ticket: &db.Tickets{
  		UUID:        uuid.Nil,
  		FeatureUUID: uuid.New().String(),
  		Name:        "Test Ticket",
  		Description: "Test Description",
  	},
  }

  body, _ := json.Marshal(ticketRequest)
  req, err := setupTestRequest(http.MethodPost, "/bounties/ticket/review/send", body, map[interface{}]interface{}{auth.ContextKey: "valid-pubkey"})
  assert.NoError(t, err)

  rr := httptest.NewRecorder()
  handler := http.HandlerFunc(tHandler.PostTicketDataToStakwork)

  handler.ServeHTTP(rr, req)
  assert.Equal(t, http.StatusBadRequest, rr.Code)
}

// Test for feature not found with valid UUID
func TestFeatureNotFoundWithValidUUID(t *testing.T) {
  _, _ = setupTestEnv()
  tHandler := NewTicketHandler(&http.Client{}, db.TestDB)

  ticketRequest := UpdateTicketRequest{
  	Ticket: &db.Tickets{
  		UUID:        uuid.New(),
  		FeatureUUID: "non-existent-uuid",
  		Name:        "Test Ticket",
  		Description: "Test Description",
  	},
  }

  body, _ := json.Marshal(ticketRequest)
  req, err := setupTestRequest(http.MethodPost, "/bounties/ticket/review/send", body, map[interface{}]interface{}{auth.ContextKey: "valid-pubkey"})
  assert.NoError(t, err)

  rr := httptest.NewRecorder()
  handler := http.HandlerFunc(tHandler.PostTicketDataToStakwork)

  handler.ServeHTTP(rr, req)
  assert.Equal(t, http.StatusInternalServerError, rr.Code)
}

// Test for invalid HTTP method
func TestInvalidHTTPMethod(t *testing.T) {
  _, _ = setupTestEnv()
  tHandler := NewTicketHandler(&http.Client{}, db.TestDB)

  req, err := setupTestRequest(http.MethodGet, "/bounties/ticket/review/send", nil, map[interface{}]interface{}{auth.ContextKey: "valid-pubkey"})
  assert.NoError(t, err)

  rr := httptest.NewRecorder()
  handler := http.HandlerFunc(tHandler.PostTicketDataToStakwork)

  handler.ServeHTTP(rr, req)
  assert.Equal(t, http.StatusMethodNotAllowed, rr.Code)
}

// Test for Stakwork API failure
func TestStakworkAPIFailure(t *testing.T) {
  mockHttpClient, _ := setupTestEnv()
  tHandler := NewTicketHandler(mockHttpClient, db.TestDB)

  ticketRequest := UpdateTicketRequest{
  	Ticket: &db.Tickets{
  		UUID:        uuid.New(),
  		FeatureUUID: uuid.New().String(),
  		Name:        "Test Ticket",
  		Description: "Test Description",
  	},
  }

  body, _ := json.Marshal(ticketRequest)
  req, err := setupTestRequest(http.MethodPost, "/bounties/ticket/review/send", body, map[interface{}]interface{}{auth.ContextKey: "valid-pubkey"})
  assert.NoError(t, err)

  rr := httptest.NewRecorder()
  handler := http.HandlerFunc(tHandler.PostTicketDataToStakwork)

  mockHttpClient.On("Do", mock.Anything).Return(&http.Response{
  	StatusCode: http.StatusInternalServerError,
  	Body:       ioutil.NopCloser(bytes.NewBufferString(`{"success": false}`)),
  }, nil)

  handler.ServeHTTP(rr, req)
  assert.Equal(t, http.StatusInternalServerError, rr.Code)
}
@MahtabBukhari
Copy link
Contributor

@tomsmith8 assign

@saithsab877
Copy link
Contributor

@tomsmith8 Please assign me

@tomsmith8
Copy link
Author

@elraphty Could you review this integration test and provide me feedback please

@tomsmith8
Copy link
Author

@humansinstitute Heads up this is first draft at generating Integration Test

@humansinstitute
Copy link
Contributor

Yeah just saw - nice :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants