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

     1  package bundle_test
     2  
     3  import (
     4  	"context"
     5  	"encoding/json"
     6  	"strings"
     7  	"testing"
     8  
     9  	dataloader "github.com/kyma-incubator/compass/components/director/internal/dataloaders"
    10  
    11  	"github.com/kyma-incubator/compass/components/director/pkg/str"
    12  
    13  	"github.com/kyma-incubator/compass/components/director/internal/domain/bundle"
    14  	"github.com/kyma-incubator/compass/components/director/internal/domain/bundle/automock"
    15  	"github.com/kyma-incubator/compass/components/director/internal/model"
    16  	"github.com/kyma-incubator/compass/components/director/pkg/apperrors"
    17  	"github.com/kyma-incubator/compass/components/director/pkg/graphql"
    18  	persistenceautomock "github.com/kyma-incubator/compass/components/director/pkg/persistence/automock"
    19  	"github.com/kyma-incubator/compass/components/director/pkg/persistence/txtest"
    20  	"github.com/kyma-incubator/compass/components/director/pkg/resource"
    21  	"github.com/pkg/errors"
    22  	"github.com/stretchr/testify/assert"
    23  	"github.com/stretchr/testify/require"
    24  )
    25  
    26  func TestResolver_API(t *testing.T) {
    27  	{
    28  		// GIVEN
    29  		id := "bar"
    30  		bndlID := "1"
    31  		var nilBundleID *string
    32  		modelAPI := fixModelAPIDefinition(id, "name", "bar", "test")
    33  		modelSpec := &model.Spec{
    34  			ID:         id,
    35  			ObjectType: model.APISpecReference,
    36  			ObjectID:   id,
    37  		}
    38  		modelBundleRef := &model.BundleReference{
    39  			BundleID:            &bndlID,
    40  			ObjectType:          model.BundleAPIReference,
    41  			ObjectID:            &id,
    42  			APIDefaultTargetURL: str.Ptr(""),
    43  		}
    44  		gqlAPI := fixGQLAPIDefinition(id, bndlID, "name", "bar", "test")
    45  		app := fixGQLBundle("foo", "foo", "foo")
    46  		testErr := errors.New("Test error")
    47  		txGen := txtest.NewTransactionContextGenerator(testErr)
    48  
    49  		testCases := []struct {
    50  			Name                     string
    51  			TransactionerFn          func() (*persistenceautomock.PersistenceTx, *persistenceautomock.Transactioner)
    52  			ServiceFn                func() *automock.APIService
    53  			SpecServiceFn            func() *automock.SpecService
    54  			BundleReferenceServiceFn func() *automock.BundleReferenceService
    55  			ConverterFn              func() *automock.APIConverter
    56  			InputID                  string
    57  			Bundle                   *graphql.Bundle
    58  			ExpectedAPI              *graphql.APIDefinition
    59  			ExpectedErr              error
    60  		}{
    61  			{
    62  				Name:            "Success",
    63  				TransactionerFn: txGen.ThatSucceeds,
    64  				ServiceFn: func() *automock.APIService {
    65  					svc := &automock.APIService{}
    66  					svc.On("GetForBundle", txtest.CtxWithDBMatcher(), "foo", "foo").Return(modelAPI, nil).Once()
    67  
    68  					return svc
    69  				},
    70  				SpecServiceFn: func() *automock.SpecService {
    71  					svc := &automock.SpecService{}
    72  					svc.On("GetByReferenceObjectID", txtest.CtxWithDBMatcher(), resource.Application, model.APISpecReference, modelAPI.ID).Return(modelSpec, nil).Once()
    73  					return svc
    74  				},
    75  				BundleReferenceServiceFn: func() *automock.BundleReferenceService {
    76  					svc := &automock.BundleReferenceService{}
    77  					svc.On("GetForBundle", txtest.CtxWithDBMatcher(), model.BundleAPIReference, &modelAPI.ID, nilBundleID).Return(modelBundleRef, nil).Once()
    78  					return svc
    79  				},
    80  				ConverterFn: func() *automock.APIConverter {
    81  					conv := &automock.APIConverter{}
    82  					conv.On("ToGraphQL", modelAPI, modelSpec, modelBundleRef).Return(gqlAPI, nil).Once()
    83  					return conv
    84  				},
    85  				InputID:     "foo",
    86  				Bundle:      app,
    87  				ExpectedAPI: gqlAPI,
    88  				ExpectedErr: nil,
    89  			},
    90  			{
    91  				Name:            "Returns error when bundle retrieval failed",
    92  				TransactionerFn: txGen.ThatDoesntExpectCommit,
    93  				ServiceFn: func() *automock.APIService {
    94  					svc := &automock.APIService{}
    95  					svc.On("GetForBundle", txtest.CtxWithDBMatcher(), "foo", "foo").Return(nil, testErr).Once()
    96  
    97  					return svc
    98  				},
    99  				SpecServiceFn: func() *automock.SpecService {
   100  					return &automock.SpecService{}
   101  				},
   102  				BundleReferenceServiceFn: func() *automock.BundleReferenceService {
   103  					return &automock.BundleReferenceService{}
   104  				},
   105  				ConverterFn: func() *automock.APIConverter {
   106  					return &automock.APIConverter{}
   107  				},
   108  				InputID:     "foo",
   109  				Bundle:      app,
   110  				ExpectedAPI: nil,
   111  				ExpectedErr: testErr,
   112  			},
   113  			{
   114  				Name:            "Returns null when api for bundle not found",
   115  				TransactionerFn: txGen.ThatSucceeds,
   116  				ServiceFn: func() *automock.APIService {
   117  					svc := &automock.APIService{}
   118  					svc.On("GetForBundle", txtest.CtxWithDBMatcher(), "foo", "foo").Return(nil, apperrors.NewNotFoundError(resource.Bundle, "")).Once()
   119  					return svc
   120  				},
   121  				SpecServiceFn: func() *automock.SpecService {
   122  					return &automock.SpecService{}
   123  				},
   124  				BundleReferenceServiceFn: func() *automock.BundleReferenceService {
   125  					return &automock.BundleReferenceService{}
   126  				},
   127  				ConverterFn: func() *automock.APIConverter {
   128  					return &automock.APIConverter{}
   129  				},
   130  				InputID:     "foo",
   131  				Bundle:      app,
   132  				ExpectedAPI: nil,
   133  				ExpectedErr: nil,
   134  			},
   135  			{
   136  				Name:            "Returns error when Spec retrieval failed",
   137  				TransactionerFn: txGen.ThatDoesntExpectCommit,
   138  				ServiceFn: func() *automock.APIService {
   139  					svc := &automock.APIService{}
   140  					svc.On("GetForBundle", txtest.CtxWithDBMatcher(), "foo", "foo").Return(modelAPI, nil).Once()
   141  
   142  					return svc
   143  				},
   144  				SpecServiceFn: func() *automock.SpecService {
   145  					svc := &automock.SpecService{}
   146  					svc.On("GetByReferenceObjectID", txtest.CtxWithDBMatcher(), resource.Application, model.APISpecReference, modelAPI.ID).Return(nil, testErr).Once()
   147  					return svc
   148  				},
   149  				BundleReferenceServiceFn: func() *automock.BundleReferenceService {
   150  					return &automock.BundleReferenceService{}
   151  				},
   152  				ConverterFn: func() *automock.APIConverter {
   153  					return &automock.APIConverter{}
   154  				},
   155  				InputID:     "foo",
   156  				Bundle:      app,
   157  				ExpectedAPI: nil,
   158  				ExpectedErr: testErr,
   159  			},
   160  			{
   161  				Name:            "Returns error when BundleReference retrieval failed",
   162  				TransactionerFn: txGen.ThatDoesntExpectCommit,
   163  				ServiceFn: func() *automock.APIService {
   164  					svc := &automock.APIService{}
   165  					svc.On("GetForBundle", txtest.CtxWithDBMatcher(), "foo", "foo").Return(modelAPI, nil).Once()
   166  
   167  					return svc
   168  				},
   169  				SpecServiceFn: func() *automock.SpecService {
   170  					svc := &automock.SpecService{}
   171  					svc.On("GetByReferenceObjectID", txtest.CtxWithDBMatcher(), resource.Application, model.APISpecReference, modelAPI.ID).Return(modelSpec, nil).Once()
   172  					return svc
   173  				},
   174  				BundleReferenceServiceFn: func() *automock.BundleReferenceService {
   175  					svc := &automock.BundleReferenceService{}
   176  					svc.On("GetForBundle", txtest.CtxWithDBMatcher(), model.BundleAPIReference, &modelAPI.ID, nilBundleID).Return(nil, testErr).Once()
   177  					return svc
   178  				},
   179  				ConverterFn: func() *automock.APIConverter {
   180  					return &automock.APIConverter{}
   181  				},
   182  				InputID:     "foo",
   183  				Bundle:      app,
   184  				ExpectedAPI: nil,
   185  				ExpectedErr: testErr,
   186  			},
   187  			{
   188  				Name:            "Returns error when converting to GraphQL failed",
   189  				TransactionerFn: txGen.ThatDoesntExpectCommit,
   190  				ServiceFn: func() *automock.APIService {
   191  					svc := &automock.APIService{}
   192  					svc.On("GetForBundle", txtest.CtxWithDBMatcher(), "foo", "foo").Return(modelAPI, nil).Once()
   193  
   194  					return svc
   195  				},
   196  				SpecServiceFn: func() *automock.SpecService {
   197  					svc := &automock.SpecService{}
   198  					svc.On("GetByReferenceObjectID", txtest.CtxWithDBMatcher(), resource.Application, model.APISpecReference, modelAPI.ID).Return(modelSpec, nil).Once()
   199  					return svc
   200  				},
   201  				BundleReferenceServiceFn: func() *automock.BundleReferenceService {
   202  					svc := &automock.BundleReferenceService{}
   203  					svc.On("GetForBundle", txtest.CtxWithDBMatcher(), model.BundleAPIReference, &modelAPI.ID, nilBundleID).Return(modelBundleRef, nil).Once()
   204  					return svc
   205  				},
   206  				ConverterFn: func() *automock.APIConverter {
   207  					conv := &automock.APIConverter{}
   208  					conv.On("ToGraphQL", modelAPI, modelSpec, modelBundleRef).Return(nil, testErr).Once()
   209  					return conv
   210  				},
   211  				InputID:     "foo",
   212  				Bundle:      app,
   213  				ExpectedAPI: nil,
   214  				ExpectedErr: testErr,
   215  			},
   216  			{
   217  				Name:            "Returns error when commit begin error",
   218  				TransactionerFn: txGen.ThatFailsOnBegin,
   219  				ServiceFn: func() *automock.APIService {
   220  					return &automock.APIService{}
   221  				},
   222  				SpecServiceFn: func() *automock.SpecService {
   223  					return &automock.SpecService{}
   224  				},
   225  				BundleReferenceServiceFn: func() *automock.BundleReferenceService {
   226  					return &automock.BundleReferenceService{}
   227  				},
   228  				ConverterFn: func() *automock.APIConverter {
   229  					return &automock.APIConverter{}
   230  				},
   231  				InputID:     "foo",
   232  				Bundle:      app,
   233  				ExpectedAPI: nil,
   234  				ExpectedErr: testErr,
   235  			},
   236  			{
   237  				Name:            "Returns error when commit failed",
   238  				TransactionerFn: txGen.ThatFailsOnCommit,
   239  				ServiceFn: func() *automock.APIService {
   240  					svc := &automock.APIService{}
   241  					svc.On("GetForBundle", txtest.CtxWithDBMatcher(), "foo", "foo").Return(modelAPI, nil).Once()
   242  
   243  					return svc
   244  				},
   245  				SpecServiceFn: func() *automock.SpecService {
   246  					svc := &automock.SpecService{}
   247  					svc.On("GetByReferenceObjectID", txtest.CtxWithDBMatcher(), resource.Application, model.APISpecReference, modelAPI.ID).Return(modelSpec, nil).Once()
   248  					return svc
   249  				},
   250  				BundleReferenceServiceFn: func() *automock.BundleReferenceService {
   251  					svc := &automock.BundleReferenceService{}
   252  					svc.On("GetForBundle", txtest.CtxWithDBMatcher(), model.BundleAPIReference, &modelAPI.ID, nilBundleID).Return(modelBundleRef, nil).Once()
   253  					return svc
   254  				},
   255  				ConverterFn: func() *automock.APIConverter {
   256  					conv := &automock.APIConverter{}
   257  					conv.On("ToGraphQL", modelAPI, modelSpec, modelBundleRef).Return(gqlAPI, nil).Once()
   258  					return conv
   259  				},
   260  				InputID:     "foo",
   261  				Bundle:      app,
   262  				ExpectedAPI: nil,
   263  				ExpectedErr: testErr,
   264  			},
   265  		}
   266  
   267  		for _, testCase := range testCases {
   268  			t.Run(testCase.Name, func(t *testing.T) {
   269  				persist, transact := testCase.TransactionerFn()
   270  				svc := testCase.ServiceFn()
   271  				converter := testCase.ConverterFn()
   272  				specSvc := testCase.SpecServiceFn()
   273  				bndlRefSvc := testCase.BundleReferenceServiceFn()
   274  
   275  				resolver := bundle.NewResolver(transact, nil, nil, bndlRefSvc, svc, nil, nil, nil, nil, converter, nil, nil, specSvc, nil)
   276  
   277  				// WHEN
   278  				result, err := resolver.APIDefinition(context.TODO(), testCase.Bundle, testCase.InputID)
   279  
   280  				// then
   281  				assert.Equal(t, testCase.ExpectedAPI, result)
   282  				if testCase.ExpectedErr != nil {
   283  					require.Error(t, err)
   284  					assert.Contains(t, err.Error(), testCase.ExpectedErr.Error())
   285  				} else {
   286  					require.Nil(t, err)
   287  				}
   288  
   289  				svc.AssertExpectations(t)
   290  				persist.AssertExpectations(t)
   291  				transact.AssertExpectations(t)
   292  				converter.AssertExpectations(t)
   293  				specSvc.AssertExpectations(t)
   294  				bndlRefSvc.AssertExpectations(t)
   295  			})
   296  		}
   297  	}
   298  }
   299  
   300  func TestResolver_APIs(t *testing.T) {
   301  	// GIVEN
   302  	testErr := errors.New("test error")
   303  	group := "group"
   304  	desc := "desc"
   305  	name := "test name"
   306  
   307  	firstBundleID := "bundleID"
   308  	secondBundleID := "bundleID2"
   309  	bundleIDs := []string{firstBundleID, secondBundleID}
   310  	firstAPIID := "apiID"
   311  	secondAPIID := "apiID2"
   312  	apiIDs := []string{firstAPIID, secondAPIID}
   313  	firstSpecID := "specID"
   314  	secondSpecID := "specID2"
   315  
   316  	// model APIDefs
   317  	apiDefFirstBundle := fixModelAPIDefinition(firstAPIID, "Foo", "Lorem Ipsum", group)
   318  	apiDefSecondBundle := fixModelAPIDefinition(secondAPIID, "Bar", "Lorem Ipsum", group)
   319  
   320  	apiDefsFirstBundle := []*model.APIDefinition{apiDefFirstBundle}
   321  	apiDefsSecondBundle := []*model.APIDefinition{apiDefSecondBundle}
   322  
   323  	apiDefPageFirstBundle := fixAPIDefinitionPage(apiDefsFirstBundle)
   324  	apiDefPageSecondBundle := fixAPIDefinitionPage(apiDefsSecondBundle)
   325  	apiDefPages := []*model.APIDefinitionPage{apiDefPageFirstBundle, apiDefPageSecondBundle}
   326  
   327  	// GQL APIDefs
   328  	gqlAPIDefFirstBundle := fixGQLAPIDefinition(firstAPIID, firstBundleID, name, desc, group)
   329  	gqlAPIDefSecondBundle := fixGQLAPIDefinition(secondAPIID, secondBundleID, name, desc, group)
   330  
   331  	gqlAPIDefsFirstBundle := []*graphql.APIDefinition{gqlAPIDefFirstBundle}
   332  	gqlAPIDefsSecondBundle := []*graphql.APIDefinition{gqlAPIDefSecondBundle}
   333  
   334  	gqlAPIDefPageFirstBundle := fixGQLAPIDefinitionPage(gqlAPIDefsFirstBundle)
   335  	gqlAPIDefPageSecondBundle := fixGQLAPIDefinitionPage(gqlAPIDefsSecondBundle)
   336  	gqlAPIDefPages := []*graphql.APIDefinitionPage{gqlAPIDefPageFirstBundle, gqlAPIDefPageSecondBundle}
   337  
   338  	// API BundleReferences
   339  	numberOfAPIsInFirstBundle := 1
   340  	numberOfAPIsInSecondBundle := 1
   341  	apiDefFirstBundleReference := fixModelAPIBundleReference(firstBundleID, firstAPIID)
   342  	apiDefSecondBundleReference := fixModelAPIBundleReference(secondBundleID, secondAPIID)
   343  	bundleRefsFirstAPI := []*model.BundleReference{apiDefFirstBundleReference}
   344  	bundleRefsSecondAPI := []*model.BundleReference{apiDefSecondBundleReference}
   345  	bundleRefs := []*model.BundleReference{apiDefFirstBundleReference, apiDefSecondBundleReference}
   346  	totalCounts := map[string]int{firstBundleID: numberOfAPIsInFirstBundle, secondBundleID: numberOfAPIsInSecondBundle}
   347  
   348  	// API Specs
   349  	apiDefFirstSpec := &model.Spec{ID: firstSpecID, ObjectType: model.APISpecReference, ObjectID: firstAPIID}
   350  	apiDefSecondSpec := &model.Spec{ID: secondSpecID, ObjectType: model.APISpecReference, ObjectID: secondAPIID}
   351  	specsFirstAPI := []*model.Spec{apiDefFirstSpec}
   352  	specsSecondAPI := []*model.Spec{apiDefSecondSpec}
   353  	specs := []*model.Spec{apiDefFirstSpec, apiDefSecondSpec}
   354  
   355  	txGen := txtest.NewTransactionContextGenerator(testErr)
   356  
   357  	first := 2
   358  	gqlAfter := graphql.PageCursor("test")
   359  	after := "test"
   360  
   361  	testCases := []struct {
   362  		Name              string
   363  		TransactionerFn   func() (*persistenceautomock.PersistenceTx, *persistenceautomock.Transactioner)
   364  		ServiceFn         func() *automock.APIService
   365  		ConverterFn       func() *automock.APIConverter
   366  		SpecServiceFn     func() *automock.SpecService
   367  		BundleReferenceFn func() *automock.BundleReferenceService
   368  		ExpectedResult    []*graphql.APIDefinitionPage
   369  		ExpectedErr       []error
   370  	}{
   371  		{
   372  			Name:            "Success",
   373  			TransactionerFn: txGen.ThatSucceeds,
   374  			ServiceFn: func() *automock.APIService {
   375  				svc := &automock.APIService{}
   376  				svc.On("ListByBundleIDs", txtest.CtxWithDBMatcher(), bundleIDs, first, after).Return(apiDefPages, nil).Once()
   377  				return svc
   378  			},
   379  			SpecServiceFn: func() *automock.SpecService {
   380  				svc := &automock.SpecService{}
   381  				svc.On("ListByReferenceObjectIDs", txtest.CtxWithDBMatcher(), model.APISpecReference, apiIDs).Return(specs, nil).Once()
   382  				return svc
   383  			},
   384  			BundleReferenceFn: func() *automock.BundleReferenceService {
   385  				svc := &automock.BundleReferenceService{}
   386  				svc.On("ListByBundleIDs", txtest.CtxWithDBMatcher(), model.BundleAPIReference, bundleIDs, first, after).Return(bundleRefs, totalCounts, nil).Once()
   387  				return svc
   388  			},
   389  			ConverterFn: func() *automock.APIConverter {
   390  				conv := &automock.APIConverter{}
   391  				conv.On("MultipleToGraphQL", apiDefsFirstBundle, specsFirstAPI, bundleRefsFirstAPI).Return(gqlAPIDefsFirstBundle, nil).Once()
   392  				conv.On("MultipleToGraphQL", apiDefsSecondBundle, specsSecondAPI, bundleRefsSecondAPI).Return(gqlAPIDefsSecondBundle, nil).Once()
   393  				return conv
   394  			},
   395  			ExpectedResult: gqlAPIDefPages,
   396  			ExpectedErr:    nil,
   397  		},
   398  		{
   399  			Name:            "Returns error when transaction begin failed",
   400  			TransactionerFn: txGen.ThatFailsOnBegin,
   401  			ServiceFn: func() *automock.APIService {
   402  				return &automock.APIService{}
   403  			},
   404  			SpecServiceFn: func() *automock.SpecService {
   405  				return &automock.SpecService{}
   406  			},
   407  			BundleReferenceFn: func() *automock.BundleReferenceService {
   408  				return &automock.BundleReferenceService{}
   409  			},
   410  			ConverterFn: func() *automock.APIConverter {
   411  				return &automock.APIConverter{}
   412  			},
   413  			ExpectedResult: nil,
   414  			ExpectedErr:    []error{testErr},
   415  		},
   416  		{
   417  			Name:            "Returns error when APIs listing failed",
   418  			TransactionerFn: txGen.ThatDoesntExpectCommit,
   419  			ServiceFn: func() *automock.APIService {
   420  				svc := &automock.APIService{}
   421  				svc.On("ListByBundleIDs", txtest.CtxWithDBMatcher(), bundleIDs, first, after).Return(nil, testErr).Once()
   422  				return svc
   423  			},
   424  			SpecServiceFn: func() *automock.SpecService {
   425  				return &automock.SpecService{}
   426  			},
   427  			BundleReferenceFn: func() *automock.BundleReferenceService {
   428  				return &automock.BundleReferenceService{}
   429  			},
   430  			ConverterFn: func() *automock.APIConverter {
   431  				return &automock.APIConverter{}
   432  			},
   433  			ExpectedResult: nil,
   434  			ExpectedErr:    []error{testErr},
   435  		},
   436  		{
   437  			Name:            "Returns error when Specs retrieval failed",
   438  			TransactionerFn: txGen.ThatDoesntExpectCommit,
   439  			ServiceFn: func() *automock.APIService {
   440  				svc := &automock.APIService{}
   441  				svc.On("ListByBundleIDs", txtest.CtxWithDBMatcher(), bundleIDs, first, after).Return(apiDefPages, nil).Once()
   442  				return svc
   443  			},
   444  			SpecServiceFn: func() *automock.SpecService {
   445  				svc := &automock.SpecService{}
   446  				svc.On("ListByReferenceObjectIDs", txtest.CtxWithDBMatcher(), model.APISpecReference, apiIDs).Return(nil, testErr).Once()
   447  				return svc
   448  			},
   449  			BundleReferenceFn: func() *automock.BundleReferenceService {
   450  				return &automock.BundleReferenceService{}
   451  			},
   452  			ConverterFn: func() *automock.APIConverter {
   453  				return &automock.APIConverter{}
   454  			},
   455  			ExpectedResult: nil,
   456  			ExpectedErr:    []error{testErr},
   457  		},
   458  		{
   459  			Name:            "Returns error when BundleReferences retrieval failed",
   460  			TransactionerFn: txGen.ThatDoesntExpectCommit,
   461  			ServiceFn: func() *automock.APIService {
   462  				svc := &automock.APIService{}
   463  				svc.On("ListByBundleIDs", txtest.CtxWithDBMatcher(), bundleIDs, first, after).Return(apiDefPages, nil).Once()
   464  				return svc
   465  			},
   466  			SpecServiceFn: func() *automock.SpecService {
   467  				svc := &automock.SpecService{}
   468  				svc.On("ListByReferenceObjectIDs", txtest.CtxWithDBMatcher(), model.APISpecReference, apiIDs).Return(specs, nil).Once()
   469  				return svc
   470  			},
   471  			BundleReferenceFn: func() *automock.BundleReferenceService {
   472  				svc := &automock.BundleReferenceService{}
   473  				svc.On("ListByBundleIDs", txtest.CtxWithDBMatcher(), model.BundleAPIReference, bundleIDs, first, after).Return(nil, nil, testErr).Once()
   474  				return svc
   475  			},
   476  			ConverterFn: func() *automock.APIConverter {
   477  				return &automock.APIConverter{}
   478  			},
   479  			ExpectedResult: nil,
   480  			ExpectedErr:    []error{testErr},
   481  		},
   482  		{
   483  			Name:            "Returns error when there is no BundleReference for API",
   484  			TransactionerFn: txGen.ThatDoesntExpectCommit,
   485  			ServiceFn: func() *automock.APIService {
   486  				svc := &automock.APIService{}
   487  				svc.On("ListByBundleIDs", txtest.CtxWithDBMatcher(), bundleIDs, first, after).Return(apiDefPages, nil).Once()
   488  				return svc
   489  			},
   490  			SpecServiceFn: func() *automock.SpecService {
   491  				svc := &automock.SpecService{}
   492  				svc.On("ListByReferenceObjectIDs", txtest.CtxWithDBMatcher(), model.APISpecReference, apiIDs).Return(specs, nil).Once()
   493  				return svc
   494  			},
   495  			BundleReferenceFn: func() *automock.BundleReferenceService {
   496  				svc := &automock.BundleReferenceService{}
   497  				invalidBundleRefs := []*model.BundleReference{apiDefSecondBundleReference}
   498  				svc.On("ListByBundleIDs", txtest.CtxWithDBMatcher(), model.BundleAPIReference, bundleIDs, first, after).Return(invalidBundleRefs, totalCounts, nil).Once()
   499  				return svc
   500  			},
   501  			ConverterFn: func() *automock.APIConverter {
   502  				conv := &automock.APIConverter{}
   503  				return conv
   504  			},
   505  			ExpectedResult: nil,
   506  			ExpectedErr:    []error{errors.New("could not find BundleReference for API with id")},
   507  		},
   508  		{
   509  			Name:            "Returns error when converting to GraphQL failed",
   510  			TransactionerFn: txGen.ThatDoesntExpectCommit,
   511  			ServiceFn: func() *automock.APIService {
   512  				svc := &automock.APIService{}
   513  				svc.On("ListByBundleIDs", txtest.CtxWithDBMatcher(), bundleIDs, first, after).Return(apiDefPages, nil).Once()
   514  				return svc
   515  			},
   516  			SpecServiceFn: func() *automock.SpecService {
   517  				svc := &automock.SpecService{}
   518  				svc.On("ListByReferenceObjectIDs", txtest.CtxWithDBMatcher(), model.APISpecReference, apiIDs).Return(specs, nil).Once()
   519  				return svc
   520  			},
   521  			BundleReferenceFn: func() *automock.BundleReferenceService {
   522  				svc := &automock.BundleReferenceService{}
   523  				svc.On("ListByBundleIDs", txtest.CtxWithDBMatcher(), model.BundleAPIReference, bundleIDs, first, after).Return(bundleRefs, totalCounts, nil).Once()
   524  				return svc
   525  			},
   526  			ConverterFn: func() *automock.APIConverter {
   527  				conv := &automock.APIConverter{}
   528  				conv.On("MultipleToGraphQL", apiDefsFirstBundle, specsFirstAPI, bundleRefsFirstAPI).Return(nil, testErr).Once()
   529  				return conv
   530  			},
   531  			ExpectedResult: nil,
   532  			ExpectedErr:    []error{testErr},
   533  		},
   534  		{
   535  			Name:            "Returns error when transaction commit failed",
   536  			TransactionerFn: txGen.ThatFailsOnCommit,
   537  			ServiceFn: func() *automock.APIService {
   538  				svc := &automock.APIService{}
   539  				svc.On("ListByBundleIDs", txtest.CtxWithDBMatcher(), bundleIDs, first, after).Return(apiDefPages, nil).Once()
   540  				return svc
   541  			},
   542  			SpecServiceFn: func() *automock.SpecService {
   543  				svc := &automock.SpecService{}
   544  				svc.On("ListByReferenceObjectIDs", txtest.CtxWithDBMatcher(), model.APISpecReference, apiIDs).Return(specs, nil).Once()
   545  				return svc
   546  			},
   547  			BundleReferenceFn: func() *automock.BundleReferenceService {
   548  				svc := &automock.BundleReferenceService{}
   549  				svc.On("ListByBundleIDs", txtest.CtxWithDBMatcher(), model.BundleAPIReference, bundleIDs, first, after).Return(bundleRefs, totalCounts, nil).Once()
   550  				return svc
   551  			},
   552  			ConverterFn: func() *automock.APIConverter {
   553  				conv := &automock.APIConverter{}
   554  				conv.On("MultipleToGraphQL", apiDefsFirstBundle, specsFirstAPI, bundleRefsFirstAPI).Return(gqlAPIDefsFirstBundle, nil).Once()
   555  				conv.On("MultipleToGraphQL", apiDefsSecondBundle, specsSecondAPI, bundleRefsSecondAPI).Return(gqlAPIDefsSecondBundle, nil).Once()
   556  				return conv
   557  			},
   558  			ExpectedResult: nil,
   559  			ExpectedErr:    []error{testErr},
   560  		},
   561  	}
   562  
   563  	for _, testCase := range testCases {
   564  		t.Run(testCase.Name, func(t *testing.T) {
   565  			// GIVEN
   566  			persist, transact := testCase.TransactionerFn()
   567  			svc := testCase.ServiceFn()
   568  			converter := testCase.ConverterFn()
   569  			specService := testCase.SpecServiceFn()
   570  			bundleRefService := testCase.BundleReferenceFn()
   571  
   572  			firstBundleParams := dataloader.ParamAPIDef{ID: firstBundleID, Ctx: context.TODO(), First: &first, After: &gqlAfter}
   573  			secondBundleParams := dataloader.ParamAPIDef{ID: secondBundleID, Ctx: context.TODO(), First: &first, After: &gqlAfter}
   574  			keys := []dataloader.ParamAPIDef{firstBundleParams, secondBundleParams}
   575  			resolver := bundle.NewResolver(transact, nil, nil, bundleRefService, svc, nil, nil, nil, nil, converter, nil, nil, specService, nil)
   576  			// WHEN
   577  			result, err := resolver.APIDefinitionsDataLoader(keys)
   578  
   579  			// then
   580  			assert.Equal(t, testCase.ExpectedResult, result)
   581  			if testCase.ExpectedErr != nil {
   582  				require.Error(t, err[0])
   583  				assert.Contains(t, err[0].Error(), testCase.ExpectedErr[0].Error())
   584  			} else {
   585  				require.Nil(t, err)
   586  			}
   587  
   588  			persist.AssertExpectations(t)
   589  			transact.AssertExpectations(t)
   590  			svc.AssertExpectations(t)
   591  			converter.AssertExpectations(t)
   592  			specService.AssertExpectations(t)
   593  			bundleRefService.AssertExpectations(t)
   594  		})
   595  	}
   596  
   597  	t.Run("Returns error when there are no Bundles", func(t *testing.T) {
   598  		resolver := bundle.NewResolver(nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil)
   599  		// WHEN
   600  		_, err := resolver.APIDefinitionsDataLoader([]dataloader.ParamAPIDef{})
   601  		// THEN
   602  		require.Error(t, err[0])
   603  		assert.EqualError(t, err[0], apperrors.NewInternalError("No Bundles found").Error())
   604  	})
   605  
   606  	t.Run("Returns error when start cursor is nil", func(t *testing.T) {
   607  		params := dataloader.ParamAPIDef{ID: firstBundleID, Ctx: context.TODO(), First: nil, After: &gqlAfter}
   608  		keys := []dataloader.ParamAPIDef{params}
   609  
   610  		resolver := bundle.NewResolver(nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil)
   611  		// WHEN
   612  		_, err := resolver.APIDefinitionsDataLoader(keys)
   613  		// THEN
   614  		require.Error(t, err[0])
   615  		assert.EqualError(t, err[0], apperrors.NewInvalidDataError("missing required parameter 'first'").Error())
   616  	})
   617  }
   618  
   619  func TestResolver_Event(t *testing.T) {
   620  	{
   621  		// GIVEN
   622  		id := "bar"
   623  		bndlID := "1"
   624  		var nilBundleID *string
   625  		modelEvent := fixModelEventAPIDefinition(id, "name", "bar", "test")
   626  		modelSpec := &model.Spec{
   627  			ID:         id,
   628  			ObjectType: model.EventSpecReference,
   629  			ObjectID:   id,
   630  		}
   631  		modelBundleRef := &model.BundleReference{
   632  			BundleID:   &bndlID,
   633  			ObjectType: model.BundleEventReference,
   634  			ObjectID:   &id,
   635  		}
   636  		gqlEvent := fixGQLEventDefinition(id, bndlID, "name", "bar", "test")
   637  		app := fixGQLBundle("foo", "foo", "foo")
   638  		testErr := errors.New("Test error")
   639  		txGen := txtest.NewTransactionContextGenerator(testErr)
   640  
   641  		testCases := []struct {
   642  			Name               string
   643  			TransactionerFn    func() (*persistenceautomock.PersistenceTx, *persistenceautomock.Transactioner)
   644  			ServiceFn          func() *automock.EventService
   645  			SpecServiceFn      func() *automock.SpecService
   646  			BundleRefServiceFn func() *automock.BundleReferenceService
   647  			ConverterFn        func() *automock.EventConverter
   648  			InputID            string
   649  			Bundle             *graphql.Bundle
   650  			ExpectedEvent      *graphql.EventDefinition
   651  			ExpectedErr        error
   652  		}{
   653  			{
   654  				Name:            "Success",
   655  				TransactionerFn: txGen.ThatSucceeds,
   656  				ServiceFn: func() *automock.EventService {
   657  					svc := &automock.EventService{}
   658  					svc.On("GetForBundle", txtest.CtxWithDBMatcher(), "foo", "foo").Return(modelEvent, nil).Once()
   659  
   660  					return svc
   661  				},
   662  				SpecServiceFn: func() *automock.SpecService {
   663  					svc := &automock.SpecService{}
   664  					svc.On("GetByReferenceObjectID", txtest.CtxWithDBMatcher(), resource.Application, model.EventSpecReference, modelEvent.ID).Return(modelSpec, nil).Once()
   665  					return svc
   666  				},
   667  				BundleRefServiceFn: func() *automock.BundleReferenceService {
   668  					svc := &automock.BundleReferenceService{}
   669  					svc.On("GetForBundle", txtest.CtxWithDBMatcher(), model.BundleEventReference, &modelEvent.ID, nilBundleID).Return(modelBundleRef, nil).Once()
   670  					return svc
   671  				},
   672  				ConverterFn: func() *automock.EventConverter {
   673  					conv := &automock.EventConverter{}
   674  					conv.On("ToGraphQL", modelEvent, modelSpec, modelBundleRef).Return(gqlEvent, nil).Once()
   675  					return conv
   676  				},
   677  				InputID:       "foo",
   678  				Bundle:        app,
   679  				ExpectedEvent: gqlEvent,
   680  				ExpectedErr:   nil,
   681  			},
   682  			{
   683  				Name:            "Returns error when bundle retrieval failed",
   684  				TransactionerFn: txGen.ThatDoesntExpectCommit,
   685  				ServiceFn: func() *automock.EventService {
   686  					svc := &automock.EventService{}
   687  					svc.On("GetForBundle", txtest.CtxWithDBMatcher(), "foo", "foo").Return(nil, testErr).Once()
   688  
   689  					return svc
   690  				},
   691  				SpecServiceFn: func() *automock.SpecService {
   692  					return &automock.SpecService{}
   693  				},
   694  				BundleRefServiceFn: func() *automock.BundleReferenceService {
   695  					return &automock.BundleReferenceService{}
   696  				},
   697  				ConverterFn: func() *automock.EventConverter {
   698  					return &automock.EventConverter{}
   699  				},
   700  				InputID:       "foo",
   701  				Bundle:        app,
   702  				ExpectedEvent: nil,
   703  				ExpectedErr:   testErr,
   704  			},
   705  			{
   706  				Name:            "Returns null when api for bundle not found",
   707  				TransactionerFn: txGen.ThatSucceeds,
   708  				ServiceFn: func() *automock.EventService {
   709  					svc := &automock.EventService{}
   710  					svc.On("GetForBundle", txtest.CtxWithDBMatcher(), "foo", "foo").Return(nil, apperrors.NewNotFoundError(resource.Bundle, "")).Once()
   711  					return svc
   712  				},
   713  				SpecServiceFn: func() *automock.SpecService {
   714  					return &automock.SpecService{}
   715  				},
   716  				BundleRefServiceFn: func() *automock.BundleReferenceService {
   717  					return &automock.BundleReferenceService{}
   718  				},
   719  				ConverterFn: func() *automock.EventConverter {
   720  					return &automock.EventConverter{}
   721  				},
   722  				InputID:       "foo",
   723  				Bundle:        app,
   724  				ExpectedEvent: nil,
   725  				ExpectedErr:   nil,
   726  			},
   727  			{
   728  				Name:            "Returns error when Spec retrieval failed",
   729  				TransactionerFn: txGen.ThatDoesntExpectCommit,
   730  				ServiceFn: func() *automock.EventService {
   731  					svc := &automock.EventService{}
   732  					svc.On("GetForBundle", txtest.CtxWithDBMatcher(), "foo", "foo").Return(modelEvent, nil).Once()
   733  
   734  					return svc
   735  				},
   736  				SpecServiceFn: func() *automock.SpecService {
   737  					svc := &automock.SpecService{}
   738  					svc.On("GetByReferenceObjectID", txtest.CtxWithDBMatcher(), resource.Application, model.EventSpecReference, modelEvent.ID).Return(nil, testErr).Once()
   739  					return svc
   740  				},
   741  				BundleRefServiceFn: func() *automock.BundleReferenceService {
   742  					return &automock.BundleReferenceService{}
   743  				},
   744  				ConverterFn: func() *automock.EventConverter {
   745  					return &automock.EventConverter{}
   746  				},
   747  				InputID:       "foo",
   748  				Bundle:        app,
   749  				ExpectedEvent: nil,
   750  				ExpectedErr:   testErr,
   751  			},
   752  			{
   753  				Name:            "Returns error when BundleReference retrieval failed",
   754  				TransactionerFn: txGen.ThatDoesntExpectCommit,
   755  				ServiceFn: func() *automock.EventService {
   756  					svc := &automock.EventService{}
   757  					svc.On("GetForBundle", txtest.CtxWithDBMatcher(), "foo", "foo").Return(modelEvent, nil).Once()
   758  
   759  					return svc
   760  				},
   761  				SpecServiceFn: func() *automock.SpecService {
   762  					svc := &automock.SpecService{}
   763  					svc.On("GetByReferenceObjectID", txtest.CtxWithDBMatcher(), resource.Application, model.EventSpecReference, modelEvent.ID).Return(modelSpec, nil).Once()
   764  					return svc
   765  				},
   766  				BundleRefServiceFn: func() *automock.BundleReferenceService {
   767  					svc := &automock.BundleReferenceService{}
   768  					svc.On("GetForBundle", txtest.CtxWithDBMatcher(), model.BundleEventReference, &modelEvent.ID, nilBundleID).Return(nil, testErr).Once()
   769  					return svc
   770  				},
   771  				ConverterFn: func() *automock.EventConverter {
   772  					return &automock.EventConverter{}
   773  				},
   774  				InputID:       "foo",
   775  				Bundle:        app,
   776  				ExpectedEvent: nil,
   777  				ExpectedErr:   testErr,
   778  			},
   779  			{
   780  				Name:            "Returns error when converting to GraphQL failed",
   781  				TransactionerFn: txGen.ThatDoesntExpectCommit,
   782  				ServiceFn: func() *automock.EventService {
   783  					svc := &automock.EventService{}
   784  					svc.On("GetForBundle", txtest.CtxWithDBMatcher(), "foo", "foo").Return(modelEvent, nil).Once()
   785  
   786  					return svc
   787  				},
   788  				SpecServiceFn: func() *automock.SpecService {
   789  					svc := &automock.SpecService{}
   790  					svc.On("GetByReferenceObjectID", txtest.CtxWithDBMatcher(), resource.Application, model.EventSpecReference, modelEvent.ID).Return(modelSpec, nil).Once()
   791  					return svc
   792  				},
   793  				BundleRefServiceFn: func() *automock.BundleReferenceService {
   794  					svc := &automock.BundleReferenceService{}
   795  					svc.On("GetForBundle", txtest.CtxWithDBMatcher(), model.BundleEventReference, &modelEvent.ID, nilBundleID).Return(modelBundleRef, nil).Once()
   796  					return svc
   797  				},
   798  				ConverterFn: func() *automock.EventConverter {
   799  					conv := &automock.EventConverter{}
   800  					conv.On("ToGraphQL", modelEvent, modelSpec, modelBundleRef).Return(nil, testErr).Once()
   801  					return conv
   802  				},
   803  				InputID:       "foo",
   804  				Bundle:        app,
   805  				ExpectedEvent: nil,
   806  				ExpectedErr:   testErr,
   807  			},
   808  			{
   809  				Name:            "Returns error when commit begin error",
   810  				TransactionerFn: txGen.ThatFailsOnBegin,
   811  				ServiceFn: func() *automock.EventService {
   812  					return &automock.EventService{}
   813  				},
   814  				SpecServiceFn: func() *automock.SpecService {
   815  					return &automock.SpecService{}
   816  				},
   817  				BundleRefServiceFn: func() *automock.BundleReferenceService {
   818  					return &automock.BundleReferenceService{}
   819  				},
   820  				ConverterFn: func() *automock.EventConverter {
   821  					return &automock.EventConverter{}
   822  				},
   823  				InputID:       "foo",
   824  				Bundle:        app,
   825  				ExpectedEvent: nil,
   826  				ExpectedErr:   testErr,
   827  			},
   828  			{
   829  				Name:            "Returns error when commit failed",
   830  				TransactionerFn: txGen.ThatFailsOnCommit,
   831  				ServiceFn: func() *automock.EventService {
   832  					svc := &automock.EventService{}
   833  					svc.On("GetForBundle", txtest.CtxWithDBMatcher(), "foo", "foo").Return(modelEvent, nil).Once()
   834  
   835  					return svc
   836  				},
   837  				SpecServiceFn: func() *automock.SpecService {
   838  					svc := &automock.SpecService{}
   839  					svc.On("GetByReferenceObjectID", txtest.CtxWithDBMatcher(), resource.Application, model.EventSpecReference, modelEvent.ID).Return(modelSpec, nil).Once()
   840  					return svc
   841  				},
   842  				BundleRefServiceFn: func() *automock.BundleReferenceService {
   843  					svc := &automock.BundleReferenceService{}
   844  					svc.On("GetForBundle", txtest.CtxWithDBMatcher(), model.BundleEventReference, &modelEvent.ID, nilBundleID).Return(modelBundleRef, nil).Once()
   845  					return svc
   846  				},
   847  				ConverterFn: func() *automock.EventConverter {
   848  					conv := &automock.EventConverter{}
   849  					conv.On("ToGraphQL", modelEvent, modelSpec, modelBundleRef).Return(gqlEvent, nil).Once()
   850  					return conv
   851  				},
   852  				InputID:       "foo",
   853  				Bundle:        app,
   854  				ExpectedEvent: nil,
   855  				ExpectedErr:   testErr,
   856  			},
   857  		}
   858  
   859  		for _, testCase := range testCases {
   860  			t.Run(testCase.Name, func(t *testing.T) {
   861  				persist, transact := testCase.TransactionerFn()
   862  				svc := testCase.ServiceFn()
   863  				converter := testCase.ConverterFn()
   864  				specSvc := testCase.SpecServiceFn()
   865  				bndlRefService := testCase.BundleRefServiceFn()
   866  
   867  				resolver := bundle.NewResolver(transact, nil, nil, bndlRefService, nil, svc, nil, nil, nil, nil, converter, nil, specSvc, nil)
   868  
   869  				// WHEN
   870  				result, err := resolver.EventDefinition(context.TODO(), testCase.Bundle, testCase.InputID)
   871  
   872  				// then
   873  				assert.Equal(t, testCase.ExpectedEvent, result)
   874  				if testCase.ExpectedErr != nil {
   875  					require.Error(t, err)
   876  					assert.Contains(t, err.Error(), testCase.ExpectedErr.Error())
   877  				} else {
   878  					require.Nil(t, err)
   879  				}
   880  
   881  				svc.AssertExpectations(t)
   882  				persist.AssertExpectations(t)
   883  				transact.AssertExpectations(t)
   884  				converter.AssertExpectations(t)
   885  				specSvc.AssertExpectations(t)
   886  				bndlRefService.AssertExpectations(t)
   887  			})
   888  		}
   889  	}
   890  }
   891  
   892  func TestResolver_Events(t *testing.T) {
   893  	// GIVEN
   894  	testErr := errors.New("test error")
   895  	group := "group"
   896  	desc := "desc"
   897  	name := "test name"
   898  
   899  	firstBundleID := "bundleID"
   900  	secondBundleID := "bundleID2"
   901  	bundleIDs := []string{firstBundleID, secondBundleID}
   902  	firstEventID := "eventID"
   903  	secondEventID := "eventID2"
   904  	eventIDs := []string{firstEventID, secondEventID}
   905  	firstSpecID := "specID"
   906  	secondSpecID := "specID2"
   907  
   908  	// model Events
   909  	eventFirstBundle := fixModelEventAPIDefinition(firstEventID, "Foo", "Lorem Ipsum", group)
   910  	eventSecondBundle := fixModelEventAPIDefinition(secondEventID, "Bar", "Lorem Ipsum", group)
   911  
   912  	eventsFirstBundle := []*model.EventDefinition{eventFirstBundle}
   913  	eventsSecondBundle := []*model.EventDefinition{eventSecondBundle}
   914  
   915  	eventPageFirstBundle := fixEventAPIDefinitionPage(eventsFirstBundle)
   916  	eventPageSecondBundle := fixEventAPIDefinitionPage(eventsSecondBundle)
   917  	eventPages := []*model.EventDefinitionPage{eventPageFirstBundle, eventPageSecondBundle}
   918  
   919  	// GQL Events
   920  	gqlEventFirstBundle := fixGQLEventDefinition(firstEventID, firstBundleID, name, desc, group)
   921  	gqlEventSecondBundle := fixGQLEventDefinition(secondEventID, secondBundleID, name, desc, group)
   922  
   923  	gqlEventsFirstBundle := []*graphql.EventDefinition{gqlEventFirstBundle}
   924  	gqlEventsSecondBundle := []*graphql.EventDefinition{gqlEventSecondBundle}
   925  
   926  	gqlEventPageFirstBundle := fixGQLEventDefinitionPage(gqlEventsFirstBundle)
   927  	gqlEventPageSecondBundle := fixGQLEventDefinitionPage(gqlEventsSecondBundle)
   928  	gqlEventPages := []*graphql.EventDefinitionPage{gqlEventPageFirstBundle, gqlEventPageSecondBundle}
   929  
   930  	// Event BundleReferences
   931  	numberOfEventsInFirstBundle := 1
   932  	numberOfEventsInSecondBundle := 1
   933  	eventFirstBundleReference := fixModelEventBundleReference(firstBundleID, firstEventID)
   934  	eventSecondBundleReference := fixModelEventBundleReference(secondBundleID, secondEventID)
   935  	bundleRefsFirstEvent := []*model.BundleReference{eventFirstBundleReference}
   936  	bundleRefsSecondEvent := []*model.BundleReference{eventSecondBundleReference}
   937  	bundleRefs := []*model.BundleReference{eventFirstBundleReference, eventSecondBundleReference}
   938  	totalCounts := map[string]int{firstBundleID: numberOfEventsInFirstBundle, secondBundleID: numberOfEventsInSecondBundle}
   939  
   940  	// Event Specs
   941  	eventFirstSpec := &model.Spec{ID: firstSpecID, ObjectType: model.EventSpecReference, ObjectID: firstEventID}
   942  	eventSecondSpec := &model.Spec{ID: secondSpecID, ObjectType: model.EventSpecReference, ObjectID: secondEventID}
   943  	specsFirstEvent := []*model.Spec{eventFirstSpec}
   944  	specsSecondEvent := []*model.Spec{eventSecondSpec}
   945  	specs := []*model.Spec{eventFirstSpec, eventSecondSpec}
   946  
   947  	txGen := txtest.NewTransactionContextGenerator(testErr)
   948  
   949  	first := 2
   950  	gqlAfter := graphql.PageCursor("test")
   951  	after := "test"
   952  
   953  	testCases := []struct {
   954  		Name              string
   955  		TransactionerFn   func() (*persistenceautomock.PersistenceTx, *persistenceautomock.Transactioner)
   956  		ServiceFn         func() *automock.EventService
   957  		ConverterFn       func() *automock.EventConverter
   958  		SpecServiceFn     func() *automock.SpecService
   959  		BundleReferenceFn func() *automock.BundleReferenceService
   960  		ExpectedResult    []*graphql.EventDefinitionPage
   961  		ExpectedErr       []error
   962  	}{
   963  		{
   964  			Name:            "Success",
   965  			TransactionerFn: txGen.ThatSucceeds,
   966  			ServiceFn: func() *automock.EventService {
   967  				svc := &automock.EventService{}
   968  				svc.On("ListByBundleIDs", txtest.CtxWithDBMatcher(), bundleIDs, first, after).Return(eventPages, nil).Once()
   969  				return svc
   970  			},
   971  			SpecServiceFn: func() *automock.SpecService {
   972  				svc := &automock.SpecService{}
   973  				svc.On("ListByReferenceObjectIDs", txtest.CtxWithDBMatcher(), model.EventSpecReference, eventIDs).Return(specs, nil).Once()
   974  				return svc
   975  			},
   976  			BundleReferenceFn: func() *automock.BundleReferenceService {
   977  				svc := &automock.BundleReferenceService{}
   978  				svc.On("ListByBundleIDs", txtest.CtxWithDBMatcher(), model.BundleEventReference, bundleIDs, first, after).Return(bundleRefs, totalCounts, nil).Once()
   979  				return svc
   980  			},
   981  			ConverterFn: func() *automock.EventConverter {
   982  				conv := &automock.EventConverter{}
   983  				conv.On("MultipleToGraphQL", eventsFirstBundle, specsFirstEvent, bundleRefsFirstEvent).Return(gqlEventsFirstBundle, nil).Once()
   984  				conv.On("MultipleToGraphQL", eventsSecondBundle, specsSecondEvent, bundleRefsSecondEvent).Return(gqlEventsSecondBundle, nil).Once()
   985  				return conv
   986  			},
   987  			ExpectedResult: gqlEventPages,
   988  			ExpectedErr:    nil,
   989  		},
   990  		{
   991  			Name:            "Returns error when transaction begin failed",
   992  			TransactionerFn: txGen.ThatFailsOnBegin,
   993  			ServiceFn: func() *automock.EventService {
   994  				return &automock.EventService{}
   995  			},
   996  			SpecServiceFn: func() *automock.SpecService {
   997  				return &automock.SpecService{}
   998  			},
   999  			BundleReferenceFn: func() *automock.BundleReferenceService {
  1000  				return &automock.BundleReferenceService{}
  1001  			},
  1002  			ConverterFn: func() *automock.EventConverter {
  1003  				return &automock.EventConverter{}
  1004  			},
  1005  			ExpectedResult: nil,
  1006  			ExpectedErr:    []error{testErr},
  1007  		},
  1008  		{
  1009  			Name:            "Returns error when Events listing failed",
  1010  			TransactionerFn: txGen.ThatDoesntExpectCommit,
  1011  			ServiceFn: func() *automock.EventService {
  1012  				svc := &automock.EventService{}
  1013  				svc.On("ListByBundleIDs", txtest.CtxWithDBMatcher(), bundleIDs, first, after).Return(nil, testErr).Once()
  1014  				return svc
  1015  			},
  1016  			SpecServiceFn: func() *automock.SpecService {
  1017  				return &automock.SpecService{}
  1018  			},
  1019  			BundleReferenceFn: func() *automock.BundleReferenceService {
  1020  				return &automock.BundleReferenceService{}
  1021  			},
  1022  			ConverterFn: func() *automock.EventConverter {
  1023  				return &automock.EventConverter{}
  1024  			},
  1025  			ExpectedResult: nil,
  1026  			ExpectedErr:    []error{testErr},
  1027  		},
  1028  		{
  1029  			Name:            "Returns error when Specs retrieval failed",
  1030  			TransactionerFn: txGen.ThatDoesntExpectCommit,
  1031  			ServiceFn: func() *automock.EventService {
  1032  				svc := &automock.EventService{}
  1033  				svc.On("ListByBundleIDs", txtest.CtxWithDBMatcher(), bundleIDs, first, after).Return(eventPages, nil).Once()
  1034  				return svc
  1035  			},
  1036  			SpecServiceFn: func() *automock.SpecService {
  1037  				svc := &automock.SpecService{}
  1038  				svc.On("ListByReferenceObjectIDs", txtest.CtxWithDBMatcher(), model.EventSpecReference, eventIDs).Return(nil, testErr).Once()
  1039  				return svc
  1040  			},
  1041  			BundleReferenceFn: func() *automock.BundleReferenceService {
  1042  				return &automock.BundleReferenceService{}
  1043  			},
  1044  			ConverterFn: func() *automock.EventConverter {
  1045  				return &automock.EventConverter{}
  1046  			},
  1047  			ExpectedResult: nil,
  1048  			ExpectedErr:    []error{testErr},
  1049  		},
  1050  		{
  1051  			Name:            "Returns error when BundleReferences retrieval failed",
  1052  			TransactionerFn: txGen.ThatDoesntExpectCommit,
  1053  			ServiceFn: func() *automock.EventService {
  1054  				svc := &automock.EventService{}
  1055  				svc.On("ListByBundleIDs", txtest.CtxWithDBMatcher(), bundleIDs, first, after).Return(eventPages, nil).Once()
  1056  				return svc
  1057  			},
  1058  			SpecServiceFn: func() *automock.SpecService {
  1059  				svc := &automock.SpecService{}
  1060  				svc.On("ListByReferenceObjectIDs", txtest.CtxWithDBMatcher(), model.EventSpecReference, eventIDs).Return(specs, nil).Once()
  1061  				return svc
  1062  			},
  1063  			BundleReferenceFn: func() *automock.BundleReferenceService {
  1064  				svc := &automock.BundleReferenceService{}
  1065  				svc.On("ListByBundleIDs", txtest.CtxWithDBMatcher(), model.BundleEventReference, bundleIDs, first, after).Return(nil, nil, testErr).Once()
  1066  				return svc
  1067  			},
  1068  			ConverterFn: func() *automock.EventConverter {
  1069  				return &automock.EventConverter{}
  1070  			},
  1071  			ExpectedResult: nil,
  1072  			ExpectedErr:    []error{testErr},
  1073  		},
  1074  		{
  1075  			Name:            "Returns error when converting to GraphQL failed",
  1076  			TransactionerFn: txGen.ThatDoesntExpectCommit,
  1077  			ServiceFn: func() *automock.EventService {
  1078  				svc := &automock.EventService{}
  1079  				svc.On("ListByBundleIDs", txtest.CtxWithDBMatcher(), bundleIDs, first, after).Return(eventPages, nil).Once()
  1080  				return svc
  1081  			},
  1082  			SpecServiceFn: func() *automock.SpecService {
  1083  				svc := &automock.SpecService{}
  1084  				svc.On("ListByReferenceObjectIDs", txtest.CtxWithDBMatcher(), model.EventSpecReference, eventIDs).Return(specs, nil).Once()
  1085  				return svc
  1086  			},
  1087  			BundleReferenceFn: func() *automock.BundleReferenceService {
  1088  				svc := &automock.BundleReferenceService{}
  1089  				svc.On("ListByBundleIDs", txtest.CtxWithDBMatcher(), model.BundleEventReference, bundleIDs, first, after).Return(bundleRefs, totalCounts, nil).Once()
  1090  				return svc
  1091  			},
  1092  			ConverterFn: func() *automock.EventConverter {
  1093  				conv := &automock.EventConverter{}
  1094  				conv.On("MultipleToGraphQL", eventsFirstBundle, specsFirstEvent, bundleRefsFirstEvent).Return(nil, testErr).Once()
  1095  				return conv
  1096  			},
  1097  			ExpectedResult: nil,
  1098  			ExpectedErr:    []error{testErr},
  1099  		},
  1100  		{
  1101  			Name:            "Returns error when transaction commit failed",
  1102  			TransactionerFn: txGen.ThatFailsOnCommit,
  1103  			ServiceFn: func() *automock.EventService {
  1104  				svc := &automock.EventService{}
  1105  				svc.On("ListByBundleIDs", txtest.CtxWithDBMatcher(), bundleIDs, first, after).Return(eventPages, nil).Once()
  1106  				return svc
  1107  			},
  1108  			SpecServiceFn: func() *automock.SpecService {
  1109  				svc := &automock.SpecService{}
  1110  				svc.On("ListByReferenceObjectIDs", txtest.CtxWithDBMatcher(), model.EventSpecReference, eventIDs).Return(specs, nil).Once()
  1111  				return svc
  1112  			},
  1113  			BundleReferenceFn: func() *automock.BundleReferenceService {
  1114  				svc := &automock.BundleReferenceService{}
  1115  				svc.On("ListByBundleIDs", txtest.CtxWithDBMatcher(), model.BundleEventReference, bundleIDs, first, after).Return(bundleRefs, totalCounts, nil).Once()
  1116  				return svc
  1117  			},
  1118  			ConverterFn: func() *automock.EventConverter {
  1119  				conv := &automock.EventConverter{}
  1120  				conv.On("MultipleToGraphQL", eventsFirstBundle, specsFirstEvent, bundleRefsFirstEvent).Return(gqlEventsFirstBundle, nil).Once()
  1121  				conv.On("MultipleToGraphQL", eventsSecondBundle, specsSecondEvent, bundleRefsSecondEvent).Return(gqlEventsSecondBundle, nil).Once()
  1122  				return conv
  1123  			},
  1124  			ExpectedResult: nil,
  1125  			ExpectedErr:    []error{testErr},
  1126  		},
  1127  	}
  1128  
  1129  	for _, testCase := range testCases {
  1130  		t.Run(testCase.Name, func(t *testing.T) {
  1131  			// GIVEN
  1132  			persist, transact := testCase.TransactionerFn()
  1133  			svc := testCase.ServiceFn()
  1134  			converter := testCase.ConverterFn()
  1135  			specService := testCase.SpecServiceFn()
  1136  			bundleRefService := testCase.BundleReferenceFn()
  1137  
  1138  			firstBundleParams := dataloader.ParamEventDef{ID: firstBundleID, Ctx: context.TODO(), First: &first, After: &gqlAfter}
  1139  			secondBundleParams := dataloader.ParamEventDef{ID: secondBundleID, Ctx: context.TODO(), First: &first, After: &gqlAfter}
  1140  			keys := []dataloader.ParamEventDef{firstBundleParams, secondBundleParams}
  1141  			resolver := bundle.NewResolver(transact, nil, nil, bundleRefService, nil, svc, nil, nil, nil, nil, converter, nil, specService, nil)
  1142  			// WHEN
  1143  			result, err := resolver.EventDefinitionsDataLoader(keys)
  1144  
  1145  			// then
  1146  			assert.Equal(t, testCase.ExpectedResult, result)
  1147  			if testCase.ExpectedErr != nil {
  1148  				require.Error(t, err[0])
  1149  				assert.Contains(t, err[0].Error(), testCase.ExpectedErr[0].Error())
  1150  			} else {
  1151  				require.Nil(t, err)
  1152  			}
  1153  
  1154  			persist.AssertExpectations(t)
  1155  			transact.AssertExpectations(t)
  1156  			svc.AssertExpectations(t)
  1157  			converter.AssertExpectations(t)
  1158  			specService.AssertExpectations(t)
  1159  			bundleRefService.AssertExpectations(t)
  1160  		})
  1161  	}
  1162  
  1163  	t.Run("Returns error when there are no Bundles", func(t *testing.T) {
  1164  		resolver := bundle.NewResolver(nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil)
  1165  		// WHEN
  1166  		_, err := resolver.EventDefinitionsDataLoader([]dataloader.ParamEventDef{})
  1167  		// THEN
  1168  		require.Error(t, err[0])
  1169  		assert.EqualError(t, err[0], apperrors.NewInternalError("No Bundles found").Error())
  1170  	})
  1171  
  1172  	t.Run("Returns error when start cursor is nil", func(t *testing.T) {
  1173  		params := dataloader.ParamEventDef{ID: firstBundleID, Ctx: context.TODO(), First: nil, After: &gqlAfter}
  1174  		keys := []dataloader.ParamEventDef{params}
  1175  
  1176  		resolver := bundle.NewResolver(nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil)
  1177  		// WHEN
  1178  		_, err := resolver.EventDefinitionsDataLoader(keys)
  1179  		// THEN
  1180  		require.Error(t, err[0])
  1181  		assert.EqualError(t, err[0], apperrors.NewInvalidDataError("missing required parameter 'first'").Error())
  1182  	})
  1183  }
  1184  
  1185  func TestResolver_Document(t *testing.T) {
  1186  	// GIVEN
  1187  	id := "bar"
  1188  
  1189  	modelDoc := fixModelDocument("foo", id)
  1190  	gqlDoc := fixGQLDocument(id)
  1191  	bndl := fixGQLBundle("foo", "foo", "foo")
  1192  	testErr := errors.New("Test error")
  1193  	txGen := txtest.NewTransactionContextGenerator(testErr)
  1194  
  1195  	testCases := []struct {
  1196  		Name            string
  1197  		TransactionerFn func() (*persistenceautomock.PersistenceTx, *persistenceautomock.Transactioner)
  1198  		ServiceFn       func() *automock.DocumentService
  1199  		ConverterFn     func() *automock.DocumentConverter
  1200  		InputID         string
  1201  		Bundle          *graphql.Bundle
  1202  		ExpectedDoc     *graphql.Document
  1203  		ExpectedErr     error
  1204  	}{
  1205  		{
  1206  			Name:            "Success",
  1207  			TransactionerFn: txGen.ThatSucceeds,
  1208  			ServiceFn: func() *automock.DocumentService {
  1209  				svc := &automock.DocumentService{}
  1210  				svc.On("GetForBundle", txtest.CtxWithDBMatcher(), "foo", "foo").Return(modelDoc, nil).Once()
  1211  
  1212  				return svc
  1213  			},
  1214  			ConverterFn: func() *automock.DocumentConverter {
  1215  				conv := &automock.DocumentConverter{}
  1216  				conv.On("ToGraphQL", modelDoc).Return(gqlDoc).Once()
  1217  				return conv
  1218  			},
  1219  			InputID:     "foo",
  1220  			Bundle:      bndl,
  1221  			ExpectedDoc: gqlDoc,
  1222  			ExpectedErr: nil,
  1223  		},
  1224  		{
  1225  			Name:            "Returns error when application retrieval failed",
  1226  			TransactionerFn: txGen.ThatDoesntExpectCommit,
  1227  			ServiceFn: func() *automock.DocumentService {
  1228  				svc := &automock.DocumentService{}
  1229  				svc.On("GetForBundle", txtest.CtxWithDBMatcher(), "foo", "foo").Return(nil, testErr).Once()
  1230  
  1231  				return svc
  1232  			},
  1233  			ConverterFn: func() *automock.DocumentConverter {
  1234  				conv := &automock.DocumentConverter{}
  1235  				return conv
  1236  			},
  1237  			InputID:     "foo",
  1238  			Bundle:      bndl,
  1239  			ExpectedDoc: nil,
  1240  			ExpectedErr: testErr,
  1241  		},
  1242  		{
  1243  			Name:            "Returns null when document for bundle not found",
  1244  			TransactionerFn: txGen.ThatSucceeds,
  1245  			ServiceFn: func() *automock.DocumentService {
  1246  				svc := &automock.DocumentService{}
  1247  				svc.On("GetForBundle", txtest.CtxWithDBMatcher(), "foo", "foo").Return(nil, apperrors.NewNotFoundError(resource.Bundle, "")).Once()
  1248  
  1249  				return svc
  1250  			},
  1251  			ConverterFn: func() *automock.DocumentConverter {
  1252  				conv := &automock.DocumentConverter{}
  1253  				return conv
  1254  			},
  1255  			InputID:     "foo",
  1256  			Bundle:      bndl,
  1257  			ExpectedDoc: nil,
  1258  			ExpectedErr: nil,
  1259  		},
  1260  		{
  1261  			Name:            "Returns error when commit begin error",
  1262  			TransactionerFn: txGen.ThatFailsOnBegin,
  1263  			ServiceFn: func() *automock.DocumentService {
  1264  				svc := &automock.DocumentService{}
  1265  
  1266  				return svc
  1267  			},
  1268  			ConverterFn: func() *automock.DocumentConverter {
  1269  				conv := &automock.DocumentConverter{}
  1270  				return conv
  1271  			},
  1272  			InputID:     "foo",
  1273  			Bundle:      bndl,
  1274  			ExpectedDoc: nil,
  1275  			ExpectedErr: testErr,
  1276  		},
  1277  		{
  1278  			Name:            "Returns error when commit failed",
  1279  			TransactionerFn: txGen.ThatFailsOnCommit,
  1280  			ServiceFn: func() *automock.DocumentService {
  1281  				svc := &automock.DocumentService{}
  1282  				svc.On("GetForBundle", txtest.CtxWithDBMatcher(), "foo", "foo").Return(modelDoc, nil).Once()
  1283  				return svc
  1284  			},
  1285  			ConverterFn: func() *automock.DocumentConverter {
  1286  				conv := &automock.DocumentConverter{}
  1287  				return conv
  1288  			},
  1289  			InputID:     "foo",
  1290  			Bundle:      bndl,
  1291  			ExpectedDoc: nil,
  1292  			ExpectedErr: testErr,
  1293  		},
  1294  	}
  1295  
  1296  	for _, testCase := range testCases {
  1297  		t.Run(testCase.Name, func(t *testing.T) {
  1298  			persist, transact := testCase.TransactionerFn()
  1299  			svc := testCase.ServiceFn()
  1300  			converter := testCase.ConverterFn()
  1301  
  1302  			resolver := bundle.NewResolver(transact, nil, nil, nil, nil, nil, svc, nil, nil, nil, nil, converter, nil, nil)
  1303  
  1304  			// WHEN
  1305  			result, err := resolver.Document(context.TODO(), testCase.Bundle, testCase.InputID)
  1306  
  1307  			// then
  1308  			assert.Equal(t, testCase.ExpectedDoc, result)
  1309  			assert.Equal(t, testCase.ExpectedErr, err)
  1310  
  1311  			svc.AssertExpectations(t)
  1312  			persist.AssertExpectations(t)
  1313  			transact.AssertExpectations(t)
  1314  			converter.AssertExpectations(t)
  1315  		})
  1316  	}
  1317  }
  1318  
  1319  func TestResolver_Documents(t *testing.T) {
  1320  	// GIVEN
  1321  	contextParam := txtest.CtxWithDBMatcher()
  1322  
  1323  	firstBundleID := "bundleID"
  1324  	secondBundleID := "bundleID2"
  1325  	bundleIDs := []string{firstBundleID, secondBundleID}
  1326  	firstDocID := "docID"
  1327  	secondDocID := "docID2"
  1328  
  1329  	// model Docs
  1330  	docFirstBundle := fixModelDocument(firstBundleID, firstDocID)
  1331  	docSecondBundle := fixModelDocument(secondBundleID, secondDocID)
  1332  
  1333  	docsFirstBundle := []*model.Document{docFirstBundle}
  1334  	docsSecondBundle := []*model.Document{docSecondBundle}
  1335  
  1336  	docPageFirstBundle := fixModelDocumentPage(docsFirstBundle)
  1337  	docPageSecondBundle := fixModelDocumentPage(docsSecondBundle)
  1338  	docPages := []*model.DocumentPage{docPageFirstBundle, docPageSecondBundle}
  1339  
  1340  	// GQL Docs
  1341  	gqlDocFirstBundle := fixGQLDocument(firstDocID)
  1342  	gqlDocSecondBundle := fixGQLDocument(secondDocID)
  1343  
  1344  	gqlDocsFirstBundle := []*graphql.Document{gqlDocFirstBundle}
  1345  	gqlDocsSecondBundle := []*graphql.Document{gqlDocSecondBundle}
  1346  
  1347  	gqlDocPageFirstBundle := fixGQLDocumentPage(gqlDocsFirstBundle)
  1348  	gqlDocPageSecondBundle := fixGQLDocumentPage(gqlDocsSecondBundle)
  1349  	gqlDocPages := []*graphql.DocumentPage{gqlDocPageFirstBundle, gqlDocPageSecondBundle}
  1350  
  1351  	first := 2
  1352  	gqlAfter := graphql.PageCursor("test")
  1353  	after := "test"
  1354  	testErr := errors.New("Test error")
  1355  
  1356  	testCases := []struct {
  1357  		Name            string
  1358  		ServiceFn       func() *automock.DocumentService
  1359  		ConverterFn     func() *automock.DocumentConverter
  1360  		PersistenceFn   func() *persistenceautomock.PersistenceTx
  1361  		TransactionerFn func(persistTx *persistenceautomock.PersistenceTx) *persistenceautomock.Transactioner
  1362  		ExpectedResult  []*graphql.DocumentPage
  1363  		ExpectedErr     []error
  1364  	}{
  1365  		{
  1366  			Name:            "Success",
  1367  			PersistenceFn:   txtest.PersistenceContextThatExpectsCommit,
  1368  			TransactionerFn: txtest.TransactionerThatSucceeds,
  1369  			ServiceFn: func() *automock.DocumentService {
  1370  				svc := &automock.DocumentService{}
  1371  				svc.On("ListByBundleIDs", contextParam, bundleIDs, first, after).Return(docPages, nil).Once()
  1372  				return svc
  1373  			},
  1374  			ConverterFn: func() *automock.DocumentConverter {
  1375  				conv := &automock.DocumentConverter{}
  1376  				conv.On("MultipleToGraphQL", docsFirstBundle).Return(gqlDocsFirstBundle).Once()
  1377  				conv.On("MultipleToGraphQL", docsSecondBundle).Return(gqlDocsSecondBundle).Once()
  1378  				return conv
  1379  			},
  1380  			ExpectedResult: gqlDocPages,
  1381  			ExpectedErr:    nil,
  1382  		},
  1383  		{
  1384  			Name:            "Returns error when document listing failed",
  1385  			PersistenceFn:   txtest.PersistenceContextThatDoesntExpectCommit,
  1386  			TransactionerFn: txtest.TransactionerThatSucceeds,
  1387  			ServiceFn: func() *automock.DocumentService {
  1388  				svc := &automock.DocumentService{}
  1389  				svc.On("ListByBundleIDs", contextParam, bundleIDs, first, after).Return(nil, testErr).Once()
  1390  				return svc
  1391  			},
  1392  			ConverterFn: func() *automock.DocumentConverter {
  1393  				conv := &automock.DocumentConverter{}
  1394  				return conv
  1395  			},
  1396  			ExpectedResult: nil,
  1397  			ExpectedErr:    []error{testErr},
  1398  		},
  1399  	}
  1400  
  1401  	for _, testCase := range testCases {
  1402  		t.Run(testCase.Name, func(t *testing.T) {
  1403  			svc := testCase.ServiceFn()
  1404  			converter := testCase.ConverterFn()
  1405  			persistTx := testCase.PersistenceFn()
  1406  			transact := testCase.TransactionerFn(persistTx)
  1407  
  1408  			firstBundleParams := dataloader.ParamDocument{ID: firstBundleID, Ctx: context.TODO(), First: &first, After: &gqlAfter}
  1409  			secondBundleParams := dataloader.ParamDocument{ID: secondBundleID, Ctx: context.TODO(), First: &first, After: &gqlAfter}
  1410  			keys := []dataloader.ParamDocument{firstBundleParams, secondBundleParams}
  1411  			resolver := bundle.NewResolver(transact, nil, nil, nil, nil, nil, svc, nil, nil, nil, nil, converter, nil, nil)
  1412  
  1413  			// WHEN
  1414  			result, err := resolver.DocumentsDataLoader(keys)
  1415  
  1416  			// then
  1417  			assert.Equal(t, testCase.ExpectedResult, result)
  1418  			assert.Equal(t, testCase.ExpectedErr, err)
  1419  
  1420  			svc.AssertExpectations(t)
  1421  			converter.AssertExpectations(t)
  1422  			persistTx.AssertExpectations(t)
  1423  			transact.AssertExpectations(t)
  1424  		})
  1425  	}
  1426  
  1427  	t.Run("Returns error when there are no Bundles", func(t *testing.T) {
  1428  		resolver := bundle.NewResolver(nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil)
  1429  		// WHEN
  1430  		_, err := resolver.DocumentsDataLoader([]dataloader.ParamDocument{})
  1431  		// THEN
  1432  		require.Error(t, err[0])
  1433  		assert.EqualError(t, err[0], apperrors.NewInternalError("No Bundles found").Error())
  1434  	})
  1435  
  1436  	t.Run("Returns error when start cursor is nil", func(t *testing.T) {
  1437  		params := dataloader.ParamDocument{ID: firstBundleID, Ctx: context.TODO(), First: nil, After: &gqlAfter}
  1438  		keys := []dataloader.ParamDocument{params}
  1439  
  1440  		resolver := bundle.NewResolver(nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil)
  1441  		// WHEN
  1442  		_, err := resolver.DocumentsDataLoader(keys)
  1443  		// THEN
  1444  		require.Error(t, err[0])
  1445  		assert.EqualError(t, err[0], apperrors.NewInvalidDataError("missing required parameter 'first'").Error())
  1446  	})
  1447  }
  1448  
  1449  func TestResolver_AddBundle(t *testing.T) {
  1450  	// GIVEN
  1451  	testErr := errors.New("Test error")
  1452  
  1453  	id := "foo"
  1454  	desc := "bar"
  1455  	name := "baz"
  1456  
  1457  	modelBundle := fixBundleModel(name, desc)
  1458  	gqlBundle := fixGQLBundle(id, name, desc)
  1459  	gqlBundleInput := fixGQLBundleCreateInput(name, desc)
  1460  	modelBundleInput := fixModelBundleCreateInput(name, desc)
  1461  
  1462  	txGen := txtest.NewTransactionContextGenerator(testErr)
  1463  
  1464  	testCases := []struct {
  1465  		Name            string
  1466  		TransactionerFn func() (*persistenceautomock.PersistenceTx, *persistenceautomock.Transactioner)
  1467  		BundleSvcFn     func() *automock.BundleService
  1468  		AppSvcFn        func() *automock.ApplicationService
  1469  		ConverterFn     func() *automock.BundleConverter
  1470  		ExpectedBundle  *graphql.Bundle
  1471  		ExpectedErr     error
  1472  	}{
  1473  		{
  1474  			Name:            "Success",
  1475  			TransactionerFn: txGen.ThatSucceeds,
  1476  			BundleSvcFn: func() *automock.BundleService {
  1477  				svc := &automock.BundleService{}
  1478  				svc.On("Create", txtest.CtxWithDBMatcher(), resource.Application, appID, modelBundleInput).Return(id, nil).Once()
  1479  				svc.On("Get", txtest.CtxWithDBMatcher(), id).Return(modelBundle, nil).Once()
  1480  				return svc
  1481  			},
  1482  			AppSvcFn: func() *automock.ApplicationService {
  1483  				svc := &automock.ApplicationService{}
  1484  				svc.On("UpdateBaseURL", txtest.CtxWithDBMatcher(), appID, extractTargetURLFromJSONArray(modelBundleInput.APIDefinitions[0].TargetURLs)).Return(nil).Once()
  1485  				return svc
  1486  			},
  1487  			ConverterFn: func() *automock.BundleConverter {
  1488  				conv := &automock.BundleConverter{}
  1489  				conv.On("CreateInputFromGraphQL", gqlBundleInput).Return(modelBundleInput, nil).Once()
  1490  				conv.On("ToGraphQL", modelBundle).Return(gqlBundle, nil).Once()
  1491  				return conv
  1492  			},
  1493  			ExpectedBundle: gqlBundle,
  1494  			ExpectedErr:    nil,
  1495  		},
  1496  		{
  1497  			Name:            "Returns error when starting transaction",
  1498  			TransactionerFn: txGen.ThatFailsOnBegin,
  1499  			BundleSvcFn: func() *automock.BundleService {
  1500  				svc := &automock.BundleService{}
  1501  				return svc
  1502  			},
  1503  			AppSvcFn: func() *automock.ApplicationService {
  1504  				return &automock.ApplicationService{}
  1505  			},
  1506  			ConverterFn: func() *automock.BundleConverter {
  1507  				conv := &automock.BundleConverter{}
  1508  				return conv
  1509  			},
  1510  			ExpectedBundle: nil,
  1511  			ExpectedErr:    testErr,
  1512  		},
  1513  		{
  1514  			Name:            "Returns error when adding Bundle failed",
  1515  			TransactionerFn: txGen.ThatDoesntExpectCommit,
  1516  			BundleSvcFn: func() *automock.BundleService {
  1517  				svc := &automock.BundleService{}
  1518  				svc.On("Create", txtest.CtxWithDBMatcher(), resource.Application, appID, modelBundleInput).Return("", testErr).Once()
  1519  				return svc
  1520  			},
  1521  			AppSvcFn: func() *automock.ApplicationService {
  1522  				return &automock.ApplicationService{}
  1523  			},
  1524  			ConverterFn: func() *automock.BundleConverter {
  1525  				conv := &automock.BundleConverter{}
  1526  				conv.On("CreateInputFromGraphQL", gqlBundleInput).Return(modelBundleInput, nil).Once()
  1527  				return conv
  1528  			},
  1529  			ExpectedBundle: nil,
  1530  			ExpectedErr:    testErr,
  1531  		},
  1532  		{
  1533  			Name:            "Returns error when Bundle retrieval failed",
  1534  			TransactionerFn: txGen.ThatDoesntExpectCommit,
  1535  			BundleSvcFn: func() *automock.BundleService {
  1536  				svc := &automock.BundleService{}
  1537  				svc.On("Create", txtest.CtxWithDBMatcher(), resource.Application, appID, modelBundleInput).Return(id, nil).Once()
  1538  				svc.On("Get", txtest.CtxWithDBMatcher(), id).Return(nil, testErr).Once()
  1539  				return svc
  1540  			},
  1541  			AppSvcFn: func() *automock.ApplicationService {
  1542  				return &automock.ApplicationService{}
  1543  			},
  1544  			ConverterFn: func() *automock.BundleConverter {
  1545  				conv := &automock.BundleConverter{}
  1546  				conv.On("CreateInputFromGraphQL", gqlBundleInput).Return(modelBundleInput, nil).Once()
  1547  				return conv
  1548  			},
  1549  			ExpectedBundle: nil,
  1550  			ExpectedErr:    testErr,
  1551  		},
  1552  		{
  1553  			Name:            "Returns error when updating base url failed",
  1554  			TransactionerFn: txGen.ThatDoesntExpectCommit,
  1555  			BundleSvcFn: func() *automock.BundleService {
  1556  				svc := &automock.BundleService{}
  1557  				svc.On("Create", txtest.CtxWithDBMatcher(), resource.Application, appID, modelBundleInput).Return(id, nil).Once()
  1558  				svc.On("Get", txtest.CtxWithDBMatcher(), id).Return(modelBundle, nil).Once()
  1559  				return svc
  1560  			},
  1561  			AppSvcFn: func() *automock.ApplicationService {
  1562  				svc := &automock.ApplicationService{}
  1563  				svc.On("UpdateBaseURL", txtest.CtxWithDBMatcher(), appID, extractTargetURLFromJSONArray(modelBundleInput.APIDefinitions[0].TargetURLs)).Return(testErr).Once()
  1564  				return svc
  1565  			},
  1566  			ConverterFn: func() *automock.BundleConverter {
  1567  				conv := &automock.BundleConverter{}
  1568  				conv.On("CreateInputFromGraphQL", gqlBundleInput).Return(modelBundleInput, nil).Once()
  1569  				return conv
  1570  			},
  1571  			ExpectedBundle: nil,
  1572  			ExpectedErr:    testErr,
  1573  		},
  1574  		{
  1575  			Name:            "Returns error when commit transaction failed",
  1576  			TransactionerFn: txGen.ThatFailsOnCommit,
  1577  			BundleSvcFn: func() *automock.BundleService {
  1578  				svc := &automock.BundleService{}
  1579  				svc.On("Create", txtest.CtxWithDBMatcher(), resource.Application, appID, modelBundleInput).Return(id, nil).Once()
  1580  				svc.On("Get", txtest.CtxWithDBMatcher(), id).Return(modelBundle, nil).Once()
  1581  				return svc
  1582  			},
  1583  			AppSvcFn: func() *automock.ApplicationService {
  1584  				svc := &automock.ApplicationService{}
  1585  				svc.On("UpdateBaseURL", txtest.CtxWithDBMatcher(), appID, extractTargetURLFromJSONArray(modelBundleInput.APIDefinitions[0].TargetURLs)).Return(nil).Once()
  1586  				return svc
  1587  			},
  1588  			ConverterFn: func() *automock.BundleConverter {
  1589  				conv := &automock.BundleConverter{}
  1590  				conv.On("CreateInputFromGraphQL", gqlBundleInput).Return(modelBundleInput, nil).Once()
  1591  				conv.On("ToGraphQL", modelBundle).Return(gqlBundle, nil).Once()
  1592  				return conv
  1593  			},
  1594  			ExpectedBundle: nil,
  1595  			ExpectedErr:    testErr,
  1596  		},
  1597  		{
  1598  			Name:            "Returns error when converting to GraphQL failed",
  1599  			TransactionerFn: txGen.ThatDoesntExpectCommit,
  1600  			BundleSvcFn: func() *automock.BundleService {
  1601  				svc := &automock.BundleService{}
  1602  				svc.On("Create", txtest.CtxWithDBMatcher(), resource.Application, appID, modelBundleInput).Return(id, nil).Once()
  1603  				svc.On("Get", txtest.CtxWithDBMatcher(), id).Return(modelBundle, nil).Once()
  1604  				return svc
  1605  			},
  1606  			AppSvcFn: func() *automock.ApplicationService {
  1607  				svc := &automock.ApplicationService{}
  1608  				svc.On("UpdateBaseURL", txtest.CtxWithDBMatcher(), appID, extractTargetURLFromJSONArray(modelBundleInput.APIDefinitions[0].TargetURLs)).Return(nil).Once()
  1609  				return svc
  1610  			},
  1611  			ConverterFn: func() *automock.BundleConverter {
  1612  				conv := &automock.BundleConverter{}
  1613  				conv.On("CreateInputFromGraphQL", gqlBundleInput).Return(modelBundleInput, nil).Once()
  1614  				conv.On("ToGraphQL", modelBundle).Return(nil, testErr).Once()
  1615  				return conv
  1616  			},
  1617  			ExpectedBundle: nil,
  1618  			ExpectedErr:    testErr,
  1619  		},
  1620  	}
  1621  
  1622  	for _, testCase := range testCases {
  1623  		t.Run(testCase.Name, func(t *testing.T) {
  1624  			// GIVEN
  1625  			persist, transact := testCase.TransactionerFn()
  1626  			bundleSvc := testCase.BundleSvcFn()
  1627  			appSvc := testCase.AppSvcFn()
  1628  			converter := testCase.ConverterFn()
  1629  
  1630  			resolver := bundle.NewResolver(transact, bundleSvc, nil, nil, nil, nil, nil, converter, nil, nil, nil, nil, nil, appSvc)
  1631  
  1632  			// WHEN
  1633  			result, err := resolver.AddBundle(context.TODO(), appID, gqlBundleInput)
  1634  
  1635  			// then
  1636  			assert.Equal(t, testCase.ExpectedBundle, result)
  1637  			if testCase.ExpectedErr != nil {
  1638  				require.Error(t, err)
  1639  				assert.Contains(t, err.Error(), testCase.ExpectedErr.Error())
  1640  			} else {
  1641  				require.Nil(t, err)
  1642  			}
  1643  
  1644  			persist.AssertExpectations(t)
  1645  			transact.AssertExpectations(t)
  1646  			bundleSvc.AssertExpectations(t)
  1647  			appSvc.AssertExpectations(t)
  1648  			converter.AssertExpectations(t)
  1649  		})
  1650  	}
  1651  }
  1652  
  1653  func TestResolver_UpdateBundle(t *testing.T) {
  1654  	// GIVEN
  1655  	testErr := errors.New("Test error")
  1656  
  1657  	id := "id"
  1658  	name := "foo"
  1659  	desc := "bar"
  1660  	gqlBundleUpdateInput := fixGQLBundleUpdateInput(name, desc)
  1661  	modelBundleUpdateInput := fixModelBundleUpdateInput(name, desc)
  1662  	gqlBundle := fixGQLBundle(id, name, desc)
  1663  	modelBundle := fixBundleModel(name, desc)
  1664  
  1665  	txGen := txtest.NewTransactionContextGenerator(testErr)
  1666  
  1667  	testCases := []struct {
  1668  		Name            string
  1669  		TransactionerFn func() (*persistenceautomock.PersistenceTx, *persistenceautomock.Transactioner)
  1670  		ServiceFn       func() *automock.BundleService
  1671  		ConverterFn     func() *automock.BundleConverter
  1672  		InputBundle     graphql.BundleUpdateInput
  1673  		ExpectedBundle  *graphql.Bundle
  1674  		ExpectedErr     error
  1675  	}{
  1676  		{
  1677  			Name:            "Success",
  1678  			TransactionerFn: txGen.ThatSucceeds,
  1679  			ServiceFn: func() *automock.BundleService {
  1680  				svc := &automock.BundleService{}
  1681  				svc.On("Update", txtest.CtxWithDBMatcher(), resource.Application, id, modelBundleUpdateInput).Return(nil).Once()
  1682  				svc.On("Get", txtest.CtxWithDBMatcher(), id).Return(modelBundle, nil).Once()
  1683  				return svc
  1684  			},
  1685  			ConverterFn: func() *automock.BundleConverter {
  1686  				conv := &automock.BundleConverter{}
  1687  				conv.On("UpdateInputFromGraphQL", gqlBundleUpdateInput).Return(&modelBundleUpdateInput, nil).Once()
  1688  				conv.On("ToGraphQL", modelBundle).Return(gqlBundle, nil).Once()
  1689  				return conv
  1690  			},
  1691  			InputBundle:    gqlBundleUpdateInput,
  1692  			ExpectedBundle: gqlBundle,
  1693  			ExpectedErr:    nil,
  1694  		},
  1695  		{
  1696  			Name:            "Returns error when starting transaction failed",
  1697  			TransactionerFn: txGen.ThatFailsOnBegin,
  1698  			ServiceFn: func() *automock.BundleService {
  1699  				svc := &automock.BundleService{}
  1700  				return svc
  1701  			},
  1702  			ConverterFn: func() *automock.BundleConverter {
  1703  				conv := &automock.BundleConverter{}
  1704  				return conv
  1705  			},
  1706  			InputBundle:    gqlBundleUpdateInput,
  1707  			ExpectedBundle: nil,
  1708  			ExpectedErr:    testErr,
  1709  		},
  1710  		{
  1711  			Name:            "Returns error when converting from GraphQL failed",
  1712  			TransactionerFn: txGen.ThatDoesntExpectCommit,
  1713  			ServiceFn: func() *automock.BundleService {
  1714  				svc := &automock.BundleService{}
  1715  				return svc
  1716  			},
  1717  			ConverterFn: func() *automock.BundleConverter {
  1718  				conv := &automock.BundleConverter{}
  1719  				conv.On("UpdateInputFromGraphQL", gqlBundleUpdateInput).Return(&model.BundleUpdateInput{}, testErr).Once()
  1720  				return conv
  1721  			},
  1722  			ExpectedBundle: nil,
  1723  			ExpectedErr:    testErr,
  1724  		},
  1725  		{
  1726  			Name:            "Returns error when Bundle update failed",
  1727  			TransactionerFn: txGen.ThatDoesntExpectCommit,
  1728  			ServiceFn: func() *automock.BundleService {
  1729  				svc := &automock.BundleService{}
  1730  				svc.On("Update", txtest.CtxWithDBMatcher(), resource.Application, id, modelBundleUpdateInput).Return(testErr).Once()
  1731  				return svc
  1732  			},
  1733  			ConverterFn: func() *automock.BundleConverter {
  1734  				conv := &automock.BundleConverter{}
  1735  				conv.On("UpdateInputFromGraphQL", gqlBundleUpdateInput).Return(&modelBundleUpdateInput, nil).Once()
  1736  				return conv
  1737  			},
  1738  			InputBundle:    gqlBundleUpdateInput,
  1739  			ExpectedBundle: nil,
  1740  			ExpectedErr:    testErr,
  1741  		},
  1742  		{
  1743  			Name:            "Returns error when Bundle retrieval failed",
  1744  			TransactionerFn: txGen.ThatDoesntExpectCommit,
  1745  			ServiceFn: func() *automock.BundleService {
  1746  				svc := &automock.BundleService{}
  1747  				svc.On("Update", txtest.CtxWithDBMatcher(), resource.Application, id, modelBundleUpdateInput).Return(nil).Once()
  1748  				svc.On("Get", txtest.CtxWithDBMatcher(), id).Return(nil, testErr).Once()
  1749  				return svc
  1750  			},
  1751  			ConverterFn: func() *automock.BundleConverter {
  1752  				conv := &automock.BundleConverter{}
  1753  				conv.On("UpdateInputFromGraphQL", gqlBundleUpdateInput).Return(&modelBundleUpdateInput, nil).Once()
  1754  				return conv
  1755  			},
  1756  			InputBundle:    gqlBundleUpdateInput,
  1757  			ExpectedBundle: nil,
  1758  			ExpectedErr:    testErr,
  1759  		},
  1760  		{
  1761  			Name:            "Returns error when commit transaction failed",
  1762  			TransactionerFn: txGen.ThatFailsOnCommit,
  1763  			ServiceFn: func() *automock.BundleService {
  1764  				svc := &automock.BundleService{}
  1765  				svc.On("Update", txtest.CtxWithDBMatcher(), resource.Application, id, modelBundleUpdateInput).Return(nil).Once()
  1766  				svc.On("Get", txtest.CtxWithDBMatcher(), id).Return(modelBundle, nil).Once()
  1767  				return svc
  1768  			},
  1769  			ConverterFn: func() *automock.BundleConverter {
  1770  				conv := &automock.BundleConverter{}
  1771  				conv.On("UpdateInputFromGraphQL", gqlBundleUpdateInput).Return(&modelBundleUpdateInput, nil).Once()
  1772  				conv.On("ToGraphQL", modelBundle).Return(gqlBundle, nil).Once()
  1773  				return conv
  1774  			},
  1775  			InputBundle:    gqlBundleUpdateInput,
  1776  			ExpectedBundle: nil,
  1777  			ExpectedErr:    testErr,
  1778  		},
  1779  		{
  1780  			Name:            "Returns error when converting to GraphQL failed",
  1781  			TransactionerFn: txGen.ThatDoesntExpectCommit,
  1782  			ServiceFn: func() *automock.BundleService {
  1783  				svc := &automock.BundleService{}
  1784  				svc.On("Update", txtest.CtxWithDBMatcher(), resource.Application, id, modelBundleUpdateInput).Return(nil).Once()
  1785  				svc.On("Get", txtest.CtxWithDBMatcher(), id).Return(modelBundle, nil).Once()
  1786  				return svc
  1787  			},
  1788  			ConverterFn: func() *automock.BundleConverter {
  1789  				conv := &automock.BundleConverter{}
  1790  				conv.On("UpdateInputFromGraphQL", gqlBundleUpdateInput).Return(&modelBundleUpdateInput, nil).Once()
  1791  				conv.On("ToGraphQL", modelBundle).Return(nil, testErr).Once()
  1792  				return conv
  1793  			},
  1794  			ExpectedBundle: nil,
  1795  			ExpectedErr:    testErr,
  1796  		},
  1797  	}
  1798  
  1799  	for _, testCase := range testCases {
  1800  		t.Run(testCase.Name, func(t *testing.T) {
  1801  			// GIVEN
  1802  			persist, transact := testCase.TransactionerFn()
  1803  			svc := testCase.ServiceFn()
  1804  			converter := testCase.ConverterFn()
  1805  
  1806  			resolver := bundle.NewResolver(transact, svc, nil, nil, nil, nil, nil, converter, nil, nil, nil, nil, nil, nil)
  1807  
  1808  			// WHEN
  1809  			result, err := resolver.UpdateBundle(context.TODO(), id, gqlBundleUpdateInput)
  1810  
  1811  			// then
  1812  			assert.Equal(t, testCase.ExpectedBundle, result)
  1813  			if testCase.ExpectedErr != nil {
  1814  				require.Error(t, err)
  1815  				assert.Contains(t, err.Error(), testCase.ExpectedErr.Error())
  1816  			} else {
  1817  				require.Nil(t, err)
  1818  			}
  1819  
  1820  			persist.AssertExpectations(t)
  1821  			transact.AssertExpectations(t)
  1822  			svc.AssertExpectations(t)
  1823  			converter.AssertExpectations(t)
  1824  		})
  1825  	}
  1826  }
  1827  
  1828  func TestResolver_DeleteBundle(t *testing.T) {
  1829  	// GIVEN
  1830  	testErr := errors.New("Test error")
  1831  
  1832  	id := "id"
  1833  	name := "foo"
  1834  	desc := "desc"
  1835  	modelBundle := fixBundleModel(name, desc)
  1836  	gqlBundle := fixGQLBundle(id, name, desc)
  1837  
  1838  	txGen := txtest.NewTransactionContextGenerator(testErr)
  1839  
  1840  	testCases := []struct {
  1841  		Name            string
  1842  		TransactionerFn func() (*persistenceautomock.PersistenceTx, *persistenceautomock.Transactioner)
  1843  		ServiceFn       func() *automock.BundleService
  1844  		APIDefFn        func() *automock.APIService
  1845  		EventDefFn      func() *automock.EventService
  1846  		ConverterFn     func() *automock.BundleConverter
  1847  		ExpectedBundle  *graphql.Bundle
  1848  		ExpectedErr     error
  1849  	}{
  1850  		{
  1851  			Name:            "Success",
  1852  			TransactionerFn: txGen.ThatSucceeds,
  1853  			ServiceFn: func() *automock.BundleService {
  1854  				svc := &automock.BundleService{}
  1855  				svc.On("Get", txtest.CtxWithDBMatcher(), id).Return(modelBundle, nil).Once()
  1856  				svc.On("Delete", txtest.CtxWithDBMatcher(), resource.Application, id).Return(nil).Once()
  1857  				return svc
  1858  			},
  1859  			APIDefFn: func() *automock.APIService {
  1860  				apiSvc := &automock.APIService{}
  1861  				apiSvc.On("DeleteAllByBundleID", txtest.CtxWithDBMatcher(), id).Return(nil).Once()
  1862  				return apiSvc
  1863  			},
  1864  			EventDefFn: func() *automock.EventService {
  1865  				eventSvc := &automock.EventService{}
  1866  				eventSvc.On("DeleteAllByBundleID", txtest.CtxWithDBMatcher(), id).Return(nil).Once()
  1867  				return eventSvc
  1868  			},
  1869  			ConverterFn: func() *automock.BundleConverter {
  1870  				conv := &automock.BundleConverter{}
  1871  				conv.On("ToGraphQL", modelBundle).Return(gqlBundle, nil).Once()
  1872  				return conv
  1873  			},
  1874  			ExpectedBundle: gqlBundle,
  1875  			ExpectedErr:    nil,
  1876  		},
  1877  		{
  1878  			Name:            "Return error when starting transaction fails",
  1879  			TransactionerFn: txGen.ThatFailsOnBegin,
  1880  			ServiceFn: func() *automock.BundleService {
  1881  				svc := &automock.BundleService{}
  1882  				return svc
  1883  			},
  1884  			APIDefFn: func() *automock.APIService {
  1885  				apiSvc := &automock.APIService{}
  1886  				return apiSvc
  1887  			},
  1888  			EventDefFn: func() *automock.EventService {
  1889  				eventSvc := &automock.EventService{}
  1890  				return eventSvc
  1891  			},
  1892  			ConverterFn: func() *automock.BundleConverter {
  1893  				conv := &automock.BundleConverter{}
  1894  				return conv
  1895  			},
  1896  			ExpectedBundle: nil,
  1897  			ExpectedErr:    testErr,
  1898  		},
  1899  		{
  1900  			Name:            "Returns error when Bundle retrieval failed",
  1901  			TransactionerFn: txGen.ThatDoesntExpectCommit,
  1902  			ServiceFn: func() *automock.BundleService {
  1903  				svc := &automock.BundleService{}
  1904  				svc.On("Get", txtest.CtxWithDBMatcher(), id).Return(nil, testErr).Once()
  1905  				return svc
  1906  			},
  1907  			APIDefFn: func() *automock.APIService {
  1908  				apiSvc := &automock.APIService{}
  1909  				return apiSvc
  1910  			},
  1911  			EventDefFn: func() *automock.EventService {
  1912  				eventSvc := &automock.EventService{}
  1913  				return eventSvc
  1914  			},
  1915  			ConverterFn: func() *automock.BundleConverter {
  1916  				conv := &automock.BundleConverter{}
  1917  				return conv
  1918  			},
  1919  			ExpectedBundle: nil,
  1920  			ExpectedErr:    testErr,
  1921  		},
  1922  		{
  1923  			Name:            "Returns error when APIs deletion failed",
  1924  			TransactionerFn: txGen.ThatDoesntExpectCommit,
  1925  			ServiceFn: func() *automock.BundleService {
  1926  				svc := &automock.BundleService{}
  1927  				svc.On("Get", txtest.CtxWithDBMatcher(), id).Return(modelBundle, nil).Once()
  1928  				return svc
  1929  			},
  1930  			APIDefFn: func() *automock.APIService {
  1931  				apiSvc := &automock.APIService{}
  1932  				apiSvc.On("DeleteAllByBundleID", txtest.CtxWithDBMatcher(), id).Return(testErr).Once()
  1933  				return apiSvc
  1934  			},
  1935  			EventDefFn: func() *automock.EventService {
  1936  				eventSvc := &automock.EventService{}
  1937  				return eventSvc
  1938  			},
  1939  			ConverterFn: func() *automock.BundleConverter {
  1940  				conv := &automock.BundleConverter{}
  1941  				return conv
  1942  			},
  1943  			ExpectedBundle: nil,
  1944  			ExpectedErr:    testErr,
  1945  		},
  1946  		{
  1947  			Name:            "Returns error when Events deletion failed",
  1948  			TransactionerFn: txGen.ThatDoesntExpectCommit,
  1949  			ServiceFn: func() *automock.BundleService {
  1950  				svc := &automock.BundleService{}
  1951  				svc.On("Get", txtest.CtxWithDBMatcher(), id).Return(modelBundle, nil).Once()
  1952  				return svc
  1953  			},
  1954  			APIDefFn: func() *automock.APIService {
  1955  				apiSvc := &automock.APIService{}
  1956  				apiSvc.On("DeleteAllByBundleID", txtest.CtxWithDBMatcher(), id).Return(nil).Once()
  1957  				return apiSvc
  1958  			},
  1959  			EventDefFn: func() *automock.EventService {
  1960  				eventSvc := &automock.EventService{}
  1961  				eventSvc.On("DeleteAllByBundleID", txtest.CtxWithDBMatcher(), id).Return(testErr).Once()
  1962  				return eventSvc
  1963  			},
  1964  			ConverterFn: func() *automock.BundleConverter {
  1965  				conv := &automock.BundleConverter{}
  1966  				return conv
  1967  			},
  1968  			ExpectedBundle: nil,
  1969  			ExpectedErr:    testErr,
  1970  		},
  1971  		{
  1972  			Name:            "Returns error when Bundle deletion failed",
  1973  			TransactionerFn: txGen.ThatDoesntExpectCommit,
  1974  			ServiceFn: func() *automock.BundleService {
  1975  				svc := &automock.BundleService{}
  1976  				svc.On("Get", txtest.CtxWithDBMatcher(), id).Return(modelBundle, nil).Once()
  1977  				svc.On("Delete", txtest.CtxWithDBMatcher(), resource.Application, id).Return(testErr).Once()
  1978  				return svc
  1979  			},
  1980  			APIDefFn: func() *automock.APIService {
  1981  				apiSvc := &automock.APIService{}
  1982  				apiSvc.On("DeleteAllByBundleID", txtest.CtxWithDBMatcher(), id).Return(nil).Once()
  1983  				return apiSvc
  1984  			},
  1985  			EventDefFn: func() *automock.EventService {
  1986  				eventSvc := &automock.EventService{}
  1987  				eventSvc.On("DeleteAllByBundleID", txtest.CtxWithDBMatcher(), id).Return(nil).Once()
  1988  				return eventSvc
  1989  			},
  1990  			ConverterFn: func() *automock.BundleConverter {
  1991  				conv := &automock.BundleConverter{}
  1992  				return conv
  1993  			},
  1994  			ExpectedBundle: nil,
  1995  			ExpectedErr:    testErr,
  1996  		},
  1997  		{
  1998  			Name:            "Return error when commit transaction fails",
  1999  			TransactionerFn: txGen.ThatFailsOnCommit,
  2000  			ServiceFn: func() *automock.BundleService {
  2001  				svc := &automock.BundleService{}
  2002  				svc.On("Get", txtest.CtxWithDBMatcher(), id).Return(modelBundle, nil).Once()
  2003  				svc.On("Delete", txtest.CtxWithDBMatcher(), resource.Application, id).Return(nil).Once()
  2004  				return svc
  2005  			},
  2006  			APIDefFn: func() *automock.APIService {
  2007  				apiSvc := &automock.APIService{}
  2008  				apiSvc.On("DeleteAllByBundleID", txtest.CtxWithDBMatcher(), id).Return(nil).Once()
  2009  				return apiSvc
  2010  			},
  2011  			EventDefFn: func() *automock.EventService {
  2012  				eventSvc := &automock.EventService{}
  2013  				eventSvc.On("DeleteAllByBundleID", txtest.CtxWithDBMatcher(), id).Return(nil).Once()
  2014  				return eventSvc
  2015  			},
  2016  			ConverterFn: func() *automock.BundleConverter {
  2017  				conv := &automock.BundleConverter{}
  2018  				conv.On("ToGraphQL", modelBundle).Return(gqlBundle, nil).Once()
  2019  				return conv
  2020  			},
  2021  			ExpectedBundle: nil,
  2022  			ExpectedErr:    testErr,
  2023  		},
  2024  		{
  2025  			Name:            "Success",
  2026  			TransactionerFn: txGen.ThatDoesntExpectCommit,
  2027  			ServiceFn: func() *automock.BundleService {
  2028  				svc := &automock.BundleService{}
  2029  				svc.On("Get", txtest.CtxWithDBMatcher(), id).Return(modelBundle, nil).Once()
  2030  				svc.On("Delete", txtest.CtxWithDBMatcher(), resource.Application, id).Return(nil).Once()
  2031  				return svc
  2032  			},
  2033  			APIDefFn: func() *automock.APIService {
  2034  				apiSvc := &automock.APIService{}
  2035  				apiSvc.On("DeleteAllByBundleID", txtest.CtxWithDBMatcher(), id).Return(nil).Once()
  2036  				return apiSvc
  2037  			},
  2038  			EventDefFn: func() *automock.EventService {
  2039  				eventSvc := &automock.EventService{}
  2040  				eventSvc.On("DeleteAllByBundleID", txtest.CtxWithDBMatcher(), id).Return(nil).Once()
  2041  				return eventSvc
  2042  			},
  2043  			ConverterFn: func() *automock.BundleConverter {
  2044  				conv := &automock.BundleConverter{}
  2045  				conv.On("ToGraphQL", modelBundle).Return(nil, testErr).Once()
  2046  				return conv
  2047  			},
  2048  			ExpectedBundle: nil,
  2049  			ExpectedErr:    testErr,
  2050  		},
  2051  	}
  2052  
  2053  	for _, testCase := range testCases {
  2054  		t.Run(testCase.Name, func(t *testing.T) {
  2055  			// GIVEN
  2056  			persist, transact := testCase.TransactionerFn()
  2057  			svc := testCase.ServiceFn()
  2058  			apiSvc := testCase.APIDefFn()
  2059  			eventSvc := testCase.EventDefFn()
  2060  			converter := testCase.ConverterFn()
  2061  
  2062  			resolver := bundle.NewResolver(transact, svc, nil, nil, apiSvc, eventSvc, nil, converter, nil, nil, nil, nil, nil, nil)
  2063  
  2064  			// WHEN
  2065  			result, err := resolver.DeleteBundle(context.TODO(), id)
  2066  
  2067  			// then
  2068  			assert.Equal(t, testCase.ExpectedBundle, result)
  2069  			if testCase.ExpectedErr != nil {
  2070  				require.Error(t, err)
  2071  				assert.Contains(t, err.Error(), testCase.ExpectedErr.Error())
  2072  			} else {
  2073  				require.Nil(t, err)
  2074  			}
  2075  
  2076  			svc.AssertExpectations(t)
  2077  			converter.AssertExpectations(t)
  2078  			transact.AssertExpectations(t)
  2079  			persist.AssertExpectations(t)
  2080  		})
  2081  	}
  2082  }
  2083  
  2084  func TestResolver_InstanceAuth(t *testing.T) {
  2085  	// GIVEN
  2086  	id := "foo"
  2087  	modelBundleInstanceAuth := fixModelBundleInstanceAuth(id)
  2088  	gqlBundleInstanceAuth := fixGQLBundleInstanceAuth(id)
  2089  	bndl := fixGQLBundle("foo", "foo", "foo")
  2090  	testErr := errors.New("Test error")
  2091  	txGen := txtest.NewTransactionContextGenerator(testErr)
  2092  
  2093  	testCases := []struct {
  2094  		Name                       string
  2095  		TransactionerFn            func() (*persistenceautomock.PersistenceTx, *persistenceautomock.Transactioner)
  2096  		ServiceFn                  func() *automock.BundleInstanceAuthService
  2097  		ConverterFn                func() *automock.BundleInstanceAuthConverter
  2098  		InputID                    string
  2099  		Bundle                     *graphql.Bundle
  2100  		ExpectedBundleInstanceAuth *graphql.BundleInstanceAuth
  2101  		ExpectedErr                error
  2102  	}{
  2103  		{
  2104  			Name:            "Success",
  2105  			TransactionerFn: txGen.ThatSucceeds,
  2106  			ServiceFn: func() *automock.BundleInstanceAuthService {
  2107  				svc := &automock.BundleInstanceAuthService{}
  2108  				svc.On("GetForBundle", txtest.CtxWithDBMatcher(), "foo", "foo").Return(modelBundleInstanceAuth, nil).Once()
  2109  
  2110  				return svc
  2111  			},
  2112  			ConverterFn: func() *automock.BundleInstanceAuthConverter {
  2113  				conv := &automock.BundleInstanceAuthConverter{}
  2114  				conv.On("ToGraphQL", modelBundleInstanceAuth).Return(gqlBundleInstanceAuth, nil).Once()
  2115  				return conv
  2116  			},
  2117  			InputID:                    "foo",
  2118  			Bundle:                     bndl,
  2119  			ExpectedBundleInstanceAuth: gqlBundleInstanceAuth,
  2120  			ExpectedErr:                nil,
  2121  		},
  2122  		{
  2123  			Name:            "Returns error when Bundle retrieval failed",
  2124  			TransactionerFn: txGen.ThatDoesntExpectCommit,
  2125  			ServiceFn: func() *automock.BundleInstanceAuthService {
  2126  				svc := &automock.BundleInstanceAuthService{}
  2127  				svc.On("GetForBundle", txtest.CtxWithDBMatcher(), "foo", "foo").Return(nil, testErr).Once()
  2128  
  2129  				return svc
  2130  			},
  2131  			ConverterFn: func() *automock.BundleInstanceAuthConverter {
  2132  				conv := &automock.BundleInstanceAuthConverter{}
  2133  				return conv
  2134  			},
  2135  			InputID:                    "foo",
  2136  			Bundle:                     bndl,
  2137  			ExpectedBundleInstanceAuth: nil,
  2138  			ExpectedErr:                testErr,
  2139  		},
  2140  		{
  2141  			Name:            "Returns error when conversion to graphql fails",
  2142  			TransactionerFn: txGen.ThatDoesntExpectCommit,
  2143  			ServiceFn: func() *automock.BundleInstanceAuthService {
  2144  				svc := &automock.BundleInstanceAuthService{}
  2145  				svc.On("GetForBundle", txtest.CtxWithDBMatcher(), "foo", "foo").Return(modelBundleInstanceAuth, nil).Once()
  2146  
  2147  				return svc
  2148  			},
  2149  			ConverterFn: func() *automock.BundleInstanceAuthConverter {
  2150  				conv := &automock.BundleInstanceAuthConverter{}
  2151  				conv.On("ToGraphQL", modelBundleInstanceAuth).Return(nil, testErr).Once()
  2152  				return conv
  2153  			},
  2154  			InputID:                    "foo",
  2155  			Bundle:                     bndl,
  2156  			ExpectedBundleInstanceAuth: nil,
  2157  			ExpectedErr:                testErr,
  2158  		},
  2159  		{
  2160  			Name:            "Returns nil when bundle instance auth for bundle not found",
  2161  			TransactionerFn: txGen.ThatSucceeds,
  2162  			ServiceFn: func() *automock.BundleInstanceAuthService {
  2163  				svc := &automock.BundleInstanceAuthService{}
  2164  				svc.On("GetForBundle", txtest.CtxWithDBMatcher(), "foo", "foo").Return(nil, apperrors.NewNotFoundError(resource.Bundle, "")).Once()
  2165  
  2166  				return svc
  2167  			},
  2168  			ConverterFn: func() *automock.BundleInstanceAuthConverter {
  2169  				conv := &automock.BundleInstanceAuthConverter{}
  2170  				return conv
  2171  			},
  2172  			InputID:                    "foo",
  2173  			Bundle:                     bndl,
  2174  			ExpectedBundleInstanceAuth: nil,
  2175  			ExpectedErr:                nil,
  2176  		},
  2177  		{
  2178  			Name:            "Returns error when commit begin error",
  2179  			TransactionerFn: txGen.ThatFailsOnBegin,
  2180  			ServiceFn: func() *automock.BundleInstanceAuthService {
  2181  				svc := &automock.BundleInstanceAuthService{}
  2182  
  2183  				return svc
  2184  			},
  2185  			ConverterFn: func() *automock.BundleInstanceAuthConverter {
  2186  				conv := &automock.BundleInstanceAuthConverter{}
  2187  				return conv
  2188  			},
  2189  			InputID:                    "foo",
  2190  			Bundle:                     bndl,
  2191  			ExpectedBundleInstanceAuth: nil,
  2192  			ExpectedErr:                testErr,
  2193  		},
  2194  		{
  2195  			Name:            "Returns error when commit failed",
  2196  			TransactionerFn: txGen.ThatFailsOnCommit,
  2197  			ServiceFn: func() *automock.BundleInstanceAuthService {
  2198  				svc := &automock.BundleInstanceAuthService{}
  2199  				svc.On("GetForBundle", txtest.CtxWithDBMatcher(), "foo", "foo").Return(modelBundleInstanceAuth, nil).Once()
  2200  				return svc
  2201  			},
  2202  			ConverterFn: func() *automock.BundleInstanceAuthConverter {
  2203  				conv := &automock.BundleInstanceAuthConverter{}
  2204  				conv.On("ToGraphQL", modelBundleInstanceAuth).Return(gqlBundleInstanceAuth, nil).Once()
  2205  				return conv
  2206  			},
  2207  			InputID:                    "foo",
  2208  			Bundle:                     bndl,
  2209  			ExpectedBundleInstanceAuth: nil,
  2210  			ExpectedErr:                testErr,
  2211  		},
  2212  	}
  2213  
  2214  	for _, testCase := range testCases {
  2215  		t.Run(testCase.Name, func(t *testing.T) {
  2216  			persist, transact := testCase.TransactionerFn()
  2217  			svc := testCase.ServiceFn()
  2218  			converter := testCase.ConverterFn()
  2219  
  2220  			resolver := bundle.NewResolver(transact, nil, svc, nil, nil, nil, nil, nil, converter, nil, nil, nil, nil, nil)
  2221  
  2222  			// WHEN
  2223  			result, err := resolver.InstanceAuth(context.TODO(), testCase.Bundle, testCase.InputID)
  2224  
  2225  			// then
  2226  			assert.Equal(t, testCase.ExpectedBundleInstanceAuth, result)
  2227  			assert.Equal(t, testCase.ExpectedErr, err)
  2228  
  2229  			svc.AssertExpectations(t)
  2230  			persist.AssertExpectations(t)
  2231  			transact.AssertExpectations(t)
  2232  			converter.AssertExpectations(t)
  2233  		})
  2234  	}
  2235  
  2236  	t.Run("Returns error when Bundle is nil", func(t *testing.T) {
  2237  		resolver := bundle.NewResolver(nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil)
  2238  		// WHEN
  2239  		_, err := resolver.InstanceAuth(context.TODO(), nil, "")
  2240  		// THEN
  2241  		require.Error(t, err)
  2242  		assert.EqualError(t, err, apperrors.NewInternalError("Bundle cannot be empty").Error())
  2243  	})
  2244  }
  2245  
  2246  func TestResolver_InstanceAuths(t *testing.T) {
  2247  	// GIVEN
  2248  	testErr := errors.New("test error")
  2249  
  2250  	bndl := fixGQLBundle(bundleID, "foo", "bar")
  2251  	modelBundleInstanceAuths := []*model.BundleInstanceAuth{
  2252  		fixModelBundleInstanceAuth("foo"),
  2253  		fixModelBundleInstanceAuth("bar"),
  2254  	}
  2255  
  2256  	gqlBundleInstanceAuths := []*graphql.BundleInstanceAuth{
  2257  		fixGQLBundleInstanceAuth("foo"),
  2258  		fixGQLBundleInstanceAuth("bar"),
  2259  	}
  2260  
  2261  	txGen := txtest.NewTransactionContextGenerator(testErr)
  2262  
  2263  	testCases := []struct {
  2264  		Name            string
  2265  		TransactionerFn func() (*persistenceautomock.PersistenceTx, *persistenceautomock.Transactioner)
  2266  		ServiceFn       func() *automock.BundleInstanceAuthService
  2267  		ConverterFn     func() *automock.BundleInstanceAuthConverter
  2268  		ExpectedResult  []*graphql.BundleInstanceAuth
  2269  		ExpectedErr     error
  2270  	}{
  2271  		{
  2272  			Name:            "Success",
  2273  			TransactionerFn: txGen.ThatSucceeds,
  2274  			ServiceFn: func() *automock.BundleInstanceAuthService {
  2275  				svc := &automock.BundleInstanceAuthService{}
  2276  				svc.On("List", txtest.CtxWithDBMatcher(), bundleID).Return(modelBundleInstanceAuths, nil).Once()
  2277  				return svc
  2278  			},
  2279  			ConverterFn: func() *automock.BundleInstanceAuthConverter {
  2280  				conv := &automock.BundleInstanceAuthConverter{}
  2281  				conv.On("MultipleToGraphQL", modelBundleInstanceAuths).Return(gqlBundleInstanceAuths, nil).Once()
  2282  				return conv
  2283  			},
  2284  			ExpectedResult: gqlBundleInstanceAuths,
  2285  			ExpectedErr:    nil,
  2286  		},
  2287  		{
  2288  			Name:            "Returns error when transaction begin failed",
  2289  			TransactionerFn: txGen.ThatFailsOnBegin,
  2290  			ServiceFn: func() *automock.BundleInstanceAuthService {
  2291  				svc := &automock.BundleInstanceAuthService{}
  2292  				return svc
  2293  			},
  2294  			ConverterFn: func() *automock.BundleInstanceAuthConverter {
  2295  				conv := &automock.BundleInstanceAuthConverter{}
  2296  				return conv
  2297  			},
  2298  			ExpectedResult: nil,
  2299  			ExpectedErr:    testErr,
  2300  		},
  2301  		{
  2302  			Name:            "Returns error when Bundle Instance Auths listing failed",
  2303  			TransactionerFn: txGen.ThatDoesntExpectCommit,
  2304  			ServiceFn: func() *automock.BundleInstanceAuthService {
  2305  				svc := &automock.BundleInstanceAuthService{}
  2306  				svc.On("List", txtest.CtxWithDBMatcher(), bundleID).Return(nil, testErr).Once()
  2307  				return svc
  2308  			},
  2309  			ConverterFn: func() *automock.BundleInstanceAuthConverter {
  2310  				conv := &automock.BundleInstanceAuthConverter{}
  2311  				return conv
  2312  			},
  2313  			ExpectedResult: nil,
  2314  			ExpectedErr:    testErr,
  2315  		},
  2316  		{
  2317  			Name:            "Returns error when Bundle Instance Auths conversion to graphql failed",
  2318  			TransactionerFn: txGen.ThatDoesntExpectCommit,
  2319  			ServiceFn: func() *automock.BundleInstanceAuthService {
  2320  				svc := &automock.BundleInstanceAuthService{}
  2321  				svc.On("List", txtest.CtxWithDBMatcher(), bundleID).Return(modelBundleInstanceAuths, nil).Once()
  2322  				return svc
  2323  			},
  2324  			ConverterFn: func() *automock.BundleInstanceAuthConverter {
  2325  				conv := &automock.BundleInstanceAuthConverter{}
  2326  				conv.On("MultipleToGraphQL", modelBundleInstanceAuths).Return(nil, testErr).Once()
  2327  				return conv
  2328  			},
  2329  			ExpectedResult: nil,
  2330  			ExpectedErr:    testErr,
  2331  		},
  2332  		{
  2333  			Name:            "Returns error when transaction commit failed",
  2334  			TransactionerFn: txGen.ThatFailsOnCommit,
  2335  			ServiceFn: func() *automock.BundleInstanceAuthService {
  2336  				svc := &automock.BundleInstanceAuthService{}
  2337  				svc.On("List", txtest.CtxWithDBMatcher(), bundleID).Return(modelBundleInstanceAuths, nil).Once()
  2338  				return svc
  2339  			},
  2340  			ConverterFn: func() *automock.BundleInstanceAuthConverter {
  2341  				conv := &automock.BundleInstanceAuthConverter{}
  2342  				conv.On("MultipleToGraphQL", modelBundleInstanceAuths).Return(gqlBundleInstanceAuths, nil).Once()
  2343  				return conv
  2344  			},
  2345  			ExpectedResult: nil,
  2346  			ExpectedErr:    testErr,
  2347  		},
  2348  	}
  2349  
  2350  	for _, testCase := range testCases {
  2351  		t.Run(testCase.Name, func(t *testing.T) {
  2352  			// GIVEN
  2353  			persist, transact := testCase.TransactionerFn()
  2354  			svc := testCase.ServiceFn()
  2355  			converter := testCase.ConverterFn()
  2356  
  2357  			resolver := bundle.NewResolver(transact, nil, svc, nil, nil, nil, nil, nil, converter, nil, nil, nil, nil, nil)
  2358  			// WHEN
  2359  			result, err := resolver.InstanceAuths(context.TODO(), bndl)
  2360  
  2361  			// then
  2362  			assert.Equal(t, testCase.ExpectedResult, result)
  2363  			assert.Equal(t, testCase.ExpectedErr, err)
  2364  
  2365  			persist.AssertExpectations(t)
  2366  			transact.AssertExpectations(t)
  2367  			svc.AssertExpectations(t)
  2368  			converter.AssertExpectations(t)
  2369  		})
  2370  	}
  2371  
  2372  	t.Run("Returns error when Bundle is nil", func(t *testing.T) {
  2373  		resolver := bundle.NewResolver(nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil)
  2374  		// WHEN
  2375  		_, err := resolver.InstanceAuths(context.TODO(), nil)
  2376  		// THEN
  2377  		require.Error(t, err)
  2378  		assert.EqualError(t, err, apperrors.NewInternalError("Bundle cannot be empty").Error())
  2379  	})
  2380  }
  2381  
  2382  func extractTargetURLFromJSONArray(jsonTargetURL json.RawMessage) string {
  2383  	strTargetURL := string(jsonTargetURL)
  2384  	strTargetURL = strings.TrimPrefix(strTargetURL, `["`)
  2385  	strTargetURL = strings.TrimSuffix(strTargetURL, `"]`)
  2386  
  2387  	return strTargetURL
  2388  }