github.com/kyma-incubator/compass/components/director@v0.0.0-20230623144113-d764f56ff805/internal/domain/webhook/converter_test.go (about) 1 package webhook_test 2 3 import ( 4 "database/sql" 5 "encoding/json" 6 "testing" 7 "time" 8 9 "github.com/kyma-incubator/compass/components/director/pkg/auth" 10 11 "github.com/kyma-incubator/compass/components/director/internal/repo" 12 13 "github.com/pkg/errors" 14 "github.com/stretchr/testify/require" 15 16 "github.com/kyma-incubator/compass/components/director/internal/domain/webhook" 17 "github.com/kyma-incubator/compass/components/director/internal/domain/webhook/automock" 18 "github.com/kyma-incubator/compass/components/director/internal/model" 19 "github.com/kyma-incubator/compass/components/director/pkg/graphql" 20 "github.com/stretchr/testify/assert" 21 ) 22 23 var ( 24 givenAppID = "givenApplicationID" 25 modelWebhookMode = model.WebhookModeSync 26 graphqlWebhookMode = graphql.WebhookModeSync 27 ) 28 29 func TestConverter_ToGraphQL(t *testing.T) { 30 // GIVEN 31 testCases := []struct { 32 Name string 33 Input *model.Webhook 34 Expected *graphql.Webhook 35 }{ 36 { 37 Name: "All properties given", 38 Input: fixApplicationModelWebhook("1", "foo", "", "bar", time.Time{}), 39 Expected: fixApplicationGQLWebhook("1", "foo", "bar"), 40 }, 41 { 42 Name: "Empty", 43 Input: &model.Webhook{}, 44 Expected: &graphql.Webhook{}, 45 }, 46 { 47 Name: "Nil", 48 Input: nil, 49 Expected: nil, 50 }, 51 } 52 53 for _, testCase := range testCases { 54 t.Run(testCase.Name, func(t *testing.T) { 55 authConv := &automock.AuthConverter{} 56 if testCase.Input != nil { 57 authConv.On("ToGraphQL", testCase.Input.Auth).Return(testCase.Expected.Auth, nil) 58 } 59 converter := webhook.NewConverter(authConv) 60 61 // WHEN 62 res, err := converter.ToGraphQL(testCase.Input) 63 64 // THEN 65 assert.NoError(t, err) 66 assert.Equal(t, testCase.Expected, res) 67 authConv.AssertExpectations(t) 68 }) 69 } 70 } 71 72 func TestConverter_ToModel(t *testing.T) { 73 id := "id" 74 objectID := "objectID" 75 url := "url" 76 77 appInput := fixApplicationGQLWebhook(id, objectID, url) 78 expectedApp := fixApplicationModelWebhook(id, objectID, "", url, time.Time{}) 79 var err error 80 expectedApp.Auth, err = auth.ToModel(appInput.Auth) 81 assert.NoError(t, err) 82 83 runtimeInput := fixRuntimeGQLWebhook(id, objectID, url) 84 expectedRuntime := fixRuntimeModelWebhook(id, objectID, url) 85 expectedRuntime.Auth, err = auth.ToModel(runtimeInput.Auth) 86 assert.NoError(t, err) 87 88 appTmplInput := fixApplicationTemplateGQLWebhook(id, objectID, url) 89 expectedAppTmpl := fixApplicationTemplateModelWebhook(id, objectID, url) 90 expectedAppTmpl.Auth, err = auth.ToModel(appTmplInput.Auth) 91 assert.NoError(t, err) 92 93 formationTmplInput := fixFormationTemplateGQLWebhook(id, objectID, url) 94 expectedFormationTmpl := fixFormationTemplateModelWebhook(id, objectID, url) 95 expectedFormationTmpl.Auth, err = auth.ToModel(formationTmplInput.Auth) 96 assert.NoError(t, err) 97 98 intSysInput := fixIntegrationSystemGQLWebhook(id, objectID, url) 99 expectedIntSys := fixIntegrationSystemModelWebhook(id, objectID, url) 100 expectedIntSys.Auth, err = auth.ToModel(intSysInput.Auth) 101 assert.NoError(t, err) 102 103 unknownInput := fixGenericGQLWebhook(id, url) 104 expectedUnknown := fixGenericModelWebhook(id, "", url) 105 expectedUnknown.Auth, err = auth.ToModel(unknownInput.Auth) 106 assert.NoError(t, err) 107 108 testCases := []struct { 109 Name string 110 Input *graphql.Webhook 111 Expected *model.Webhook 112 }{ 113 { 114 Name: "Success when object type is application", 115 Input: appInput, 116 Expected: expectedApp, 117 }, 118 { 119 Name: "Success when object type is runtime", 120 Input: runtimeInput, 121 Expected: expectedRuntime, 122 }, 123 { 124 Name: "Success when object type is application template", 125 Input: appTmplInput, 126 Expected: expectedAppTmpl, 127 }, 128 { 129 Name: "Success when object type is formation template", 130 Input: formationTmplInput, 131 Expected: expectedFormationTmpl, 132 }, 133 { 134 Name: "Success when object type is integration system", 135 Input: intSysInput, 136 Expected: expectedIntSys, 137 }, 138 { 139 Name: "Success when object type is unknown", 140 Input: unknownInput, 141 Expected: expectedUnknown, 142 }, 143 { 144 Name: "Success when input is nil", 145 }, 146 } 147 148 for _, testCase := range testCases { 149 t.Run(testCase.Name, func(t *testing.T) { 150 converter := webhook.NewConverter(&automock.AuthConverter{}) 151 152 // WHEN 153 res, err := converter.ToModel(testCase.Input) 154 155 // THEN 156 assert.NoError(t, err) 157 assert.Equal(t, testCase.Expected, res) 158 }) 159 } 160 } 161 162 func TestConverter_MultipleToGraphQL(t *testing.T) { 163 // GIVEN 164 input := []*model.Webhook{ 165 fixApplicationModelWebhook("1", "foo", "", "baz", time.Time{}), 166 fixApplicationModelWebhook("2", "bar", "", "bez", time.Time{}), 167 {}, 168 nil, 169 } 170 expected := []*graphql.Webhook{ 171 fixApplicationGQLWebhook("1", "foo", "baz"), 172 fixApplicationGQLWebhook("2", "bar", "bez"), 173 {}, 174 } 175 authConv := &automock.AuthConverter{} 176 authConv.On("ToGraphQL", input[0].Auth).Return(expected[0].Auth, nil) 177 authConv.On("ToGraphQL", (*model.Auth)(nil)).Return(nil, nil) 178 converter := webhook.NewConverter(authConv) 179 180 // WHEN 181 res, err := converter.MultipleToGraphQL(input) 182 183 // THEN 184 assert.NoError(t, err) 185 assert.Equal(t, expected, res) 186 authConv.AssertExpectations(t) 187 } 188 189 func TestConverter_InputFromGraphQL(t *testing.T) { 190 // GIVEN 191 testCases := []struct { 192 Name string 193 Input *graphql.WebhookInput 194 Expected *model.WebhookInput 195 Error error 196 }{ 197 { 198 Name: "All properties given", 199 Input: fixGQLWebhookInput("https://test-domain.com"), 200 Expected: fixModelWebhookInput("https://test-domain.com"), 201 Error: nil, 202 }, 203 { 204 Name: "Empty", 205 Input: &graphql.WebhookInput{}, 206 Expected: &model.WebhookInput{}, 207 Error: nil, 208 }, 209 { 210 Name: "Nil", 211 Input: nil, 212 Expected: nil, 213 Error: nil, 214 }, 215 } 216 217 for _, testCase := range testCases { 218 t.Run(testCase.Name, func(t *testing.T) { 219 authConv := &automock.AuthConverter{} 220 if testCase.Input != nil && testCase.Error == nil { 221 authConv.On("InputFromGraphQL", testCase.Input.Auth).Return(testCase.Expected.Auth, nil) 222 } 223 converter := webhook.NewConverter(authConv) 224 225 // WHEN 226 res, err := converter.InputFromGraphQL(testCase.Input) 227 228 // then 229 if testCase.Error == nil { 230 assert.NoError(t, err) 231 assert.Equal(t, testCase.Expected, res) 232 } else { 233 assert.Error(t, err, testCase.Error) 234 } 235 authConv.AssertExpectations(t) 236 }) 237 } 238 } 239 240 func TestConverter_MultipleInputFromGraphQL(t *testing.T) { 241 // GIVEN 242 input := []*graphql.WebhookInput{ 243 fixGQLWebhookInput("https://test-domain.com"), 244 fixGQLWebhookInput("https://test-domain.com"), 245 nil, 246 } 247 expected := []*model.WebhookInput{ 248 fixModelWebhookInput("https://test-domain.com"), 249 fixModelWebhookInput("https://test-domain.com"), 250 } 251 authConv := &automock.AuthConverter{} 252 authConv.On("InputFromGraphQL", input[0].Auth).Return(expected[0].Auth, nil) 253 converter := webhook.NewConverter(authConv) 254 255 // WHEN 256 res, err := converter.MultipleInputFromGraphQL(input) 257 258 // then 259 assert.NoError(t, err) 260 assert.Equal(t, expected, res) 261 authConv.AssertExpectations(t) 262 } 263 264 func TestConverter_ToEntity(t *testing.T) { 265 sut := webhook.NewConverter(nil) 266 267 b, err := json.Marshal(fixBasicAuth()) 268 require.NoError(t, err) 269 expectedBasicAuthAsString := string(b) 270 271 testCases := map[string]struct { 272 in *model.Webhook 273 expected *webhook.Entity 274 }{ 275 "success when Auth not provided": { 276 in: &model.Webhook{ 277 ID: "givenID", 278 ObjectID: givenAppID, 279 ObjectType: model.ApplicationWebhookReference, 280 URL: stringPtr("https://test-domain.com"), 281 Type: model.WebhookTypeConfigurationChanged, 282 Mode: &modelWebhookMode, 283 URLTemplate: &emptyTemplate, 284 InputTemplate: &emptyTemplate, 285 HeaderTemplate: &emptyTemplate, 286 OutputTemplate: &emptyTemplate, 287 }, 288 expected: &webhook.Entity{ 289 ID: "givenID", 290 ApplicationID: repo.NewValidNullableString(givenAppID), 291 URL: repo.NewValidNullableString("https://test-domain.com"), 292 Type: "CONFIGURATION_CHANGED", 293 Auth: sql.NullString{Valid: false}, 294 Mode: repo.NewValidNullableString("SYNC"), 295 URLTemplate: repo.NewValidNullableString(emptyTemplate), 296 InputTemplate: repo.NewValidNullableString(emptyTemplate), 297 HeaderTemplate: repo.NewValidNullableString(emptyTemplate), 298 OutputTemplate: repo.NewValidNullableString(emptyTemplate), 299 }, 300 }, 301 "success when Auth provided": { 302 in: &model.Webhook{ 303 Auth: fixBasicAuth(), 304 }, 305 expected: &webhook.Entity{ 306 Auth: sql.NullString{Valid: true, String: expectedBasicAuthAsString}, 307 }, 308 }, 309 } 310 311 for tn, tc := range testCases { 312 t.Run(tn, func(t *testing.T) { 313 // WHEN 314 actual, err := sut.ToEntity(tc.in) 315 // THEN 316 require.NoError(t, err) 317 assert.Equal(t, tc.expected, actual) 318 }) 319 } 320 } 321 322 func TestConverter_FromEntity(t *testing.T) { 323 // GIVEN 324 sut := webhook.NewConverter(nil) 325 b, err := json.Marshal(fixBasicAuth()) 326 require.NoError(t, err) 327 328 testCases := map[string]struct { 329 inEntity *webhook.Entity 330 expectedModel *model.Webhook 331 expectedErr error 332 }{ 333 "success when Auth not provided": { 334 inEntity: &webhook.Entity{ 335 ID: "givenID", 336 Type: "CONFIGURATION_CHANGED", 337 URL: repo.NewValidNullableString("https://test-domain.com"), 338 ApplicationID: repo.NewValidNullableString(givenAppID), 339 Mode: repo.NewValidNullableString("SYNC"), 340 URLTemplate: repo.NewValidNullableString(emptyTemplate), 341 InputTemplate: repo.NewValidNullableString(emptyTemplate), 342 HeaderTemplate: repo.NewValidNullableString(emptyTemplate), 343 OutputTemplate: repo.NewValidNullableString(emptyTemplate), 344 }, 345 expectedModel: &model.Webhook{ 346 ID: "givenID", 347 Type: "CONFIGURATION_CHANGED", 348 URL: stringPtr("https://test-domain.com"), 349 ObjectID: givenAppID, 350 ObjectType: model.ApplicationWebhookReference, 351 Auth: nil, 352 Mode: &modelWebhookMode, 353 URLTemplate: &emptyTemplate, 354 InputTemplate: &emptyTemplate, 355 HeaderTemplate: &emptyTemplate, 356 OutputTemplate: &emptyTemplate, 357 }, 358 }, 359 "success when Auth provided": { 360 inEntity: &webhook.Entity{ 361 ID: "givenID", 362 ApplicationID: repo.NewValidNullableString("appID"), 363 Auth: sql.NullString{ 364 Valid: true, 365 String: string(b), 366 }, 367 }, 368 expectedModel: &model.Webhook{ 369 ID: "givenID", 370 ObjectID: "appID", 371 ObjectType: model.ApplicationWebhookReference, 372 Auth: fixBasicAuth(), 373 }, 374 }, 375 "got error on unmarshaling JSON": { 376 inEntity: &webhook.Entity{ 377 Auth: sql.NullString{ 378 Valid: true, 379 String: "it is not even a proper JSON!", 380 }, 381 }, 382 expectedErr: errors.New("while unmarshaling Auth: invalid character 'i' looking for beginning of value"), 383 }, 384 } 385 386 for tn, tc := range testCases { 387 t.Run(tn, func(t *testing.T) { 388 actual, err := sut.FromEntity(tc.inEntity) 389 if tc.expectedErr != nil { 390 require.EqualError(t, err, tc.expectedErr.Error()) 391 return 392 } 393 require.NoError(t, err) 394 assert.Equal(t, tc.expectedModel, actual) 395 }) 396 } 397 }