github.com/kyma-incubator/compass/components/director@v0.0.0-20230623144113-d764f56ff805/internal/destinationfetchersvc/handler_test.go (about)

     1  package destinationfetchersvc_test
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"io"
     7  	"net/http"
     8  	"net/http/httptest"
     9  	"testing"
    10  
    11  	"github.com/kyma-incubator/compass/components/director/internal/destinationfetchersvc"
    12  	"github.com/kyma-incubator/compass/components/director/internal/destinationfetchersvc/automock"
    13  	"github.com/kyma-incubator/compass/components/director/internal/domain/tenant"
    14  	"github.com/kyma-incubator/compass/components/director/pkg/apperrors"
    15  	"github.com/kyma-incubator/compass/components/director/pkg/resource"
    16  	"github.com/stretchr/testify/assert"
    17  	"github.com/stretchr/testify/mock"
    18  )
    19  
    20  const expectedTenantID = "f09ba084-0e82-49ab-ab2e-b7ecc988312d"
    21  
    22  func TestHandler_SyncDestinations(t *testing.T) {
    23  	target := "/v1/fetch"
    24  
    25  	validHandlerConfig := destinationfetchersvc.HandlerConfig{
    26  		SyncDestinationsEndpoint:      "/v1/fetch",
    27  		DestinationsSensitiveEndpoint: "/v1/info",
    28  	}
    29  
    30  	reqWithUserContext := httptest.NewRequest(http.MethodPut, target, nil)
    31  	reqWithUserContext = reqWithUserContext.WithContext(
    32  		tenant.SaveToContext(reqWithUserContext.Context(), expectedTenantID, ""))
    33  
    34  	testCases := []struct {
    35  		Name                string
    36  		Request             *http.Request
    37  		DestinationManager  func() *automock.DestinationManager
    38  		ExpectedErrorOutput string
    39  		ExpectedStatusCode  int
    40  	}{
    41  		{
    42  			Name:    "Successful fetch on-demand",
    43  			Request: reqWithUserContext,
    44  			DestinationManager: func() *automock.DestinationManager {
    45  				svc := &automock.DestinationManager{}
    46  				svc.On("SyncTenantDestinations", mock.Anything, expectedTenantID).Return(nil)
    47  				return svc
    48  			},
    49  			ExpectedStatusCode: http.StatusOK,
    50  		},
    51  		{
    52  			Name:    "Missing tenant header",
    53  			Request: httptest.NewRequest(http.MethodPut, target, nil),
    54  			DestinationManager: func() *automock.DestinationManager {
    55  				return &automock.DestinationManager{}
    56  			},
    57  			ExpectedStatusCode: http.StatusBadRequest,
    58  		},
    59  		{
    60  			Name:    "Tenant not found",
    61  			Request: reqWithUserContext,
    62  			DestinationManager: func() *automock.DestinationManager {
    63  				svc := &automock.DestinationManager{}
    64  				err := apperrors.NewNotFoundErrorWithMessage(resource.Label,
    65  					expectedTenantID, fmt.Sprintf("tenant %s not found", expectedTenantID))
    66  				svc.On("SyncTenantDestinations", mock.Anything, expectedTenantID).Return(err)
    67  				return svc
    68  			},
    69  			ExpectedErrorOutput: fmt.Sprintf("tenant %s not found", expectedTenantID),
    70  			ExpectedStatusCode:  http.StatusBadRequest,
    71  		},
    72  		{
    73  			Name:    "Internal Server Error",
    74  			Request: reqWithUserContext,
    75  			DestinationManager: func() *automock.DestinationManager {
    76  				svc := &automock.DestinationManager{}
    77  				err := fmt.Errorf("random error")
    78  				svc.On("SyncTenantDestinations", mock.Anything, expectedTenantID).Return(err)
    79  				return svc
    80  			},
    81  			ExpectedErrorOutput: fmt.Sprintf("Failed to sync destinations for tenant %s", expectedTenantID),
    82  			ExpectedStatusCode:  http.StatusInternalServerError,
    83  		},
    84  	}
    85  	for _, testCase := range testCases {
    86  		t.Run(testCase.Name, func(t *testing.T) {
    87  			tf := testCase.DestinationManager()
    88  			defer mock.AssertExpectationsForObjects(t, tf)
    89  
    90  			handler := destinationfetchersvc.NewDestinationsHTTPHandler(tf, validHandlerConfig)
    91  			req := testCase.Request
    92  			w := httptest.NewRecorder()
    93  
    94  			// WHEN
    95  			handler.SyncTenantDestinations(w, req)
    96  
    97  			// THEN
    98  			resp := w.Result()
    99  			body, err := io.ReadAll(resp.Body)
   100  			assert.NoError(t, err)
   101  
   102  			if len(testCase.ExpectedErrorOutput) > 0 {
   103  				assert.Contains(t, string(body), testCase.ExpectedErrorOutput)
   104  			} else {
   105  				assert.NoError(t, err)
   106  			}
   107  
   108  			assert.Equal(t, testCase.ExpectedStatusCode, resp.StatusCode)
   109  		})
   110  	}
   111  }
   112  
   113  func TestHandler_FetchDestinationsSensitiveData(t *testing.T) {
   114  	const destQueryParameter = "name"
   115  
   116  	json := []byte("{}")
   117  
   118  	target := "/v1/info"
   119  
   120  	validHandlerConfig := destinationfetchersvc.HandlerConfig{
   121  		SyncDestinationsEndpoint:      "/v1/fetch",
   122  		DestinationsSensitiveEndpoint: "/v1/info",
   123  		DestinationsQueryParameter:    destQueryParameter,
   124  	}
   125  
   126  	namesQueryRaw := "name=Rand&name=Mat"
   127  	names := []string{"Rand", "Mat"}
   128  	reqWithUserContext := httptest.NewRequest(http.MethodPut, target, nil)
   129  	reqWithUserContext = reqWithUserContext.WithContext(
   130  		tenant.SaveToContext(reqWithUserContext.Context(), expectedTenantID, ""))
   131  
   132  	testCases := []struct {
   133  		Name                  string
   134  		Request               *http.Request
   135  		DestQuery             string
   136  		DestinationFetcherSvc func() *automock.DestinationManager
   137  		ExpectedErrorOutput   string
   138  		ExpectedStatusCode    int
   139  	}{
   140  		{
   141  			Name:      "Successful fetch data fetch",
   142  			Request:   reqWithUserContext,
   143  			DestQuery: namesQueryRaw,
   144  			DestinationFetcherSvc: func() *automock.DestinationManager {
   145  				svc := &automock.DestinationManager{}
   146  				svc.On("FetchDestinationsSensitiveData", mock.Anything, expectedTenantID, names).
   147  					Return(
   148  						func(ctx context.Context, tenantID string, destNames []string) []byte {
   149  							return json
   150  						},
   151  						func(ctx context.Context, tenantID string, destNames []string) error {
   152  							return nil
   153  						},
   154  					)
   155  				return svc
   156  			},
   157  			ExpectedStatusCode: http.StatusOK,
   158  		},
   159  		{
   160  			Name:    "Missing tenant header",
   161  			Request: httptest.NewRequest(http.MethodPut, target, nil),
   162  			DestinationFetcherSvc: func() *automock.DestinationManager {
   163  				return &automock.DestinationManager{}
   164  			},
   165  			ExpectedStatusCode: http.StatusBadRequest,
   166  		},
   167  		{
   168  			Name:    "Missing destination query parameter.",
   169  			Request: reqWithUserContext,
   170  			DestinationFetcherSvc: func() *automock.DestinationManager {
   171  				return &automock.DestinationManager{}
   172  			},
   173  			ExpectedStatusCode: http.StatusBadRequest,
   174  		},
   175  	}
   176  	for _, testCase := range testCases {
   177  		t.Run(testCase.Name, func(t *testing.T) {
   178  			tf := testCase.DestinationFetcherSvc()
   179  			defer mock.AssertExpectationsForObjects(t, tf)
   180  
   181  			handler := destinationfetchersvc.NewDestinationsHTTPHandler(tf, validHandlerConfig)
   182  			req := testCase.Request
   183  			//req is a pointer and the changes on the previous test are kept
   184  			req.URL.RawQuery = ""
   185  			if len(testCase.DestQuery) > 0 {
   186  				req.URL.RawQuery = testCase.DestQuery
   187  			}
   188  
   189  			w := httptest.NewRecorder()
   190  
   191  			// WHEN
   192  			handler.FetchDestinationsSensitiveData(w, req)
   193  
   194  			// THEN
   195  			resp := w.Result()
   196  			body, err := io.ReadAll(resp.Body)
   197  			assert.NoError(t, err)
   198  
   199  			if len(testCase.ExpectedErrorOutput) > 0 {
   200  				assert.Contains(t, string(body), testCase.ExpectedErrorOutput)
   201  			} else {
   202  				assert.NoError(t, err)
   203  			}
   204  
   205  			assert.Equal(t, testCase.ExpectedStatusCode, resp.StatusCode)
   206  		})
   207  	}
   208  }