github.com/kyma-incubator/compass/components/director@v0.0.0-20230623144113-d764f56ff805/pkg/graphql/formation_template_validation_test.go (about)

     1  package graphql_test
     2  
     3  import (
     4  	"strings"
     5  	"testing"
     6  
     7  	"github.com/kyma-incubator/compass/components/director/pkg/inputvalidation/inputvalidationtest"
     8  
     9  	"github.com/kyma-incubator/compass/components/director/pkg/graphql"
    10  
    11  	"github.com/stretchr/testify/require"
    12  )
    13  
    14  const (
    15  	runtimeArtifactKindField    = "RuntimeArtifactKind"
    16  	runtimeTypeDisplayNameField = "RuntimeTypeDisplayName"
    17  	runtimeTypesField           = "RuntimeTypes"
    18  )
    19  
    20  func TestFormationTemplateInput_ValidateName(t *testing.T) {
    21  	testCases := []struct {
    22  		Name          string
    23  		Value         string
    24  		ExpectedValid bool
    25  	}{
    26  		{
    27  			Name:          "Success",
    28  			Value:         "a normal name for once",
    29  			ExpectedValid: true,
    30  		},
    31  		{
    32  			Name:          "Name longer than 256",
    33  			Value:         strings.Repeat("some-name", 50),
    34  			ExpectedValid: false,
    35  		},
    36  		{
    37  			Name:          "Invalid",
    38  			Value:         "",
    39  			ExpectedValid: false,
    40  		},
    41  	}
    42  
    43  	for _, testCase := range testCases {
    44  		t.Run(testCase.Name, func(t *testing.T) {
    45  			//GIVEN
    46  			formationTemplateInput := fixValidFormationTemplateInput()
    47  			formationTemplateInput.Name = testCase.Value
    48  			// WHEN
    49  			err := formationTemplateInput.Validate()
    50  			// THEN
    51  			if testCase.ExpectedValid {
    52  				require.NoError(t, err)
    53  			} else {
    54  				require.Error(t, err)
    55  			}
    56  		})
    57  	}
    58  }
    59  
    60  func TestFormationTemplateInput_ValidateRuntimeDisplayName(t *testing.T) {
    61  	testCases := []struct {
    62  		Name          string
    63  		Value         string
    64  		ExpectedValid bool
    65  	}{
    66  		{
    67  			Name:          "Success",
    68  			Value:         "a normal name for once",
    69  			ExpectedValid: true,
    70  		},
    71  		{
    72  			Name:          "Name longer than 512",
    73  			Value:         strings.Repeat("some-name", 100),
    74  			ExpectedValid: false,
    75  		},
    76  		{
    77  			Name:          "Invalid",
    78  			Value:         "",
    79  			ExpectedValid: false,
    80  		},
    81  	}
    82  
    83  	for _, testCase := range testCases {
    84  		t.Run(testCase.Name, func(t *testing.T) {
    85  			//GIVEN
    86  			formationTemplateInput := fixValidFormationTemplateInput()
    87  			formationTemplateInput.RuntimeTypeDisplayName = &testCase.Value
    88  			// WHEN
    89  			err := formationTemplateInput.Validate()
    90  			// THEN
    91  			if testCase.ExpectedValid {
    92  				require.NoError(t, err)
    93  			} else {
    94  				require.Error(t, err)
    95  			}
    96  		})
    97  	}
    98  }
    99  
   100  func TestFormationTemplateInput_ValidateRuntimeArtifactKind(t *testing.T) {
   101  	testCases := []struct {
   102  		Name          string
   103  		Value         graphql.ArtifactType
   104  		ExpectedValid bool
   105  	}{
   106  		{
   107  			Name:          "Success - Service Instance",
   108  			Value:         graphql.ArtifactTypeServiceInstance,
   109  			ExpectedValid: true,
   110  		},
   111  		{
   112  			Name:          "Success - Subscription",
   113  			Value:         graphql.ArtifactTypeSubscription,
   114  			ExpectedValid: true,
   115  		},
   116  		{
   117  			Name:          "Success - Environment Instance",
   118  			Value:         graphql.ArtifactTypeEnvironmentInstance,
   119  			ExpectedValid: true,
   120  		},
   121  		{
   122  			Name:          "Invalid type",
   123  			Value:         graphql.ArtifactType("Invalid type"),
   124  			ExpectedValid: false,
   125  		},
   126  		{
   127  			Name:          "Invalid",
   128  			Value:         "",
   129  			ExpectedValid: false,
   130  		},
   131  	}
   132  
   133  	for _, testCase := range testCases {
   134  		t.Run(testCase.Name, func(t *testing.T) {
   135  			//GIVEN
   136  			formationTemplateInput := fixValidFormationTemplateInput()
   137  			formationTemplateInput.RuntimeArtifactKind = &testCase.Value
   138  			// WHEN
   139  			err := formationTemplateInput.Validate()
   140  			// THEN
   141  			if testCase.ExpectedValid {
   142  				require.NoError(t, err)
   143  			} else {
   144  				require.Error(t, err)
   145  			}
   146  		})
   147  	}
   148  }
   149  
   150  func TestFormationTemplateInput_ValidateApplicationTypes(t *testing.T) {
   151  	testCases := []struct {
   152  		Name          string
   153  		Value         []string
   154  		ExpectedValid bool
   155  	}{
   156  		{
   157  			Name:          "Success",
   158  			Value:         []string{"normal-type", "another-normal-type"},
   159  			ExpectedValid: true,
   160  		},
   161  		{
   162  			Name:          "Empty slice",
   163  			Value:         []string{},
   164  			ExpectedValid: false,
   165  		},
   166  		{
   167  			Name:          "Nil slice",
   168  			Value:         nil,
   169  			ExpectedValid: false,
   170  		},
   171  		{
   172  			Name:          "Empty elements in slice",
   173  			Value:         []string{""},
   174  			ExpectedValid: false,
   175  		},
   176  	}
   177  
   178  	for _, testCase := range testCases {
   179  		t.Run(testCase.Name, func(t *testing.T) {
   180  			//GIVEN
   181  			formationTemplateInput := fixValidFormationTemplateInput()
   182  			formationTemplateInput.ApplicationTypes = testCase.Value
   183  			// WHEN
   184  			err := formationTemplateInput.Validate()
   185  			// THEN
   186  			if testCase.ExpectedValid {
   187  				require.NoError(t, err)
   188  			} else {
   189  				require.Error(t, err)
   190  			}
   191  		})
   192  	}
   193  }
   194  
   195  func TestFormationTemplateInput_ValidateRuntimeTypes(t *testing.T) {
   196  	testCases := []struct {
   197  		Name          string
   198  		Value         []string
   199  		ExpectedValid bool
   200  	}{
   201  		{
   202  			Name:          "Success",
   203  			Value:         []string{"normal-type", "another-normal-type"},
   204  			ExpectedValid: true,
   205  		},
   206  		{
   207  			Name:          "Empty slice",
   208  			Value:         []string{},
   209  			ExpectedValid: false,
   210  		},
   211  		{
   212  			Name:          "Nil slice",
   213  			Value:         nil,
   214  			ExpectedValid: false,
   215  		},
   216  		{
   217  			Name:          "Empty elements in slice",
   218  			Value:         []string{""},
   219  			ExpectedValid: false,
   220  		},
   221  	}
   222  
   223  	for _, testCase := range testCases {
   224  		t.Run(testCase.Name, func(t *testing.T) {
   225  			//GIVEN
   226  			formationTemplateInput := fixValidFormationTemplateInput()
   227  			formationTemplateInput.RuntimeTypes = testCase.Value
   228  			// WHEN
   229  			err := formationTemplateInput.Validate()
   230  			// THEN
   231  			if testCase.ExpectedValid {
   232  				require.NoError(t, err)
   233  			} else {
   234  				require.Error(t, err)
   235  			}
   236  		})
   237  	}
   238  }
   239  
   240  func TestFormationTemplateInput_Validate_Webhooks(t *testing.T) {
   241  	webhookInput := fixValidWebhookInput(inputvalidationtest.ValidURL)
   242  	webhookInputWithInvalidOutputTemplate := fixValidWebhookInput(inputvalidationtest.ValidURL)
   243  	webhookInputWithInvalidMode := fixValidWebhookInput(inputvalidationtest.ValidURL)
   244  	webhookInputWithInvalidMode.Type = graphql.WebhookTypeFormationLifecycle
   245  	webhookInputWithInvalidMode.Mode = webhookModePtr(graphql.WebhookModeAsync)
   246  	webhookInputWithInvalidOutputTemplate.OutputTemplate = stringPtr(`{ "gone_status_code": 404, "success_status_code": 200}`)
   247  	webhookInputwithInvalidURL := fixValidWebhookInput(inputvalidationtest.ValidURL)
   248  	webhookInputwithInvalidURL.URL = nil
   249  	testCases := []struct {
   250  		Name  string
   251  		Value []*graphql.WebhookInput
   252  		Valid bool
   253  	}{
   254  		{
   255  			Name:  "Valid",
   256  			Value: []*graphql.WebhookInput{&webhookInput},
   257  			Valid: true,
   258  		},
   259  		{
   260  			Name:  "Valid - Empty",
   261  			Value: []*graphql.WebhookInput{},
   262  			Valid: true,
   263  		},
   264  		{
   265  			Name:  "Valid - nil",
   266  			Value: nil,
   267  			Valid: true,
   268  		},
   269  		{
   270  			Name:  "Invalid - type is 'FORMATION_LIFECYCLE' and mode is not 'SYNC'",
   271  			Value: []*graphql.WebhookInput{&webhookInputWithInvalidMode},
   272  			Valid: false,
   273  		},
   274  		{
   275  			Name:  "Invalid - some of the webhooks are in invalid state - invalid output template",
   276  			Value: []*graphql.WebhookInput{&webhookInputWithInvalidOutputTemplate},
   277  			Valid: false,
   278  		},
   279  		{
   280  			Name:  "Invalid - some of the webhooks are in invalid state - invalid URL",
   281  			Value: []*graphql.WebhookInput{&webhookInputwithInvalidURL},
   282  			Valid: false,
   283  		},
   284  	}
   285  
   286  	for _, testCase := range testCases {
   287  		t.Run(testCase.Name, func(t *testing.T) {
   288  			//GIVEN
   289  			sut := fixValidFormationTemplateInput()
   290  			sut.Webhooks = testCase.Value
   291  			// WHEN
   292  			err := sut.Validate()
   293  			// THEN
   294  			if testCase.Valid {
   295  				require.NoError(t, err)
   296  			} else {
   297  				require.Error(t, err)
   298  			}
   299  		})
   300  	}
   301  }
   302  
   303  func TestFormationTemplateInput_ValidateRuntimeRelatedFields(t *testing.T) {
   304  	testCases := []struct {
   305  		Name          string
   306  		EmptyFields   []string
   307  		ExpectedValid bool
   308  	}{
   309  		{
   310  			Name:          "Success all fields present",
   311  			EmptyFields:   []string{},
   312  			ExpectedValid: true,
   313  		},
   314  		{
   315  			Name:          "Success all fields missing",
   316  			EmptyFields:   []string{runtimeTypesField, runtimeTypeDisplayNameField, runtimeArtifactKindField},
   317  			ExpectedValid: true,
   318  		},
   319  		{
   320  			Name:          "Missing artifact kind",
   321  			EmptyFields:   []string{runtimeArtifactKindField},
   322  			ExpectedValid: false,
   323  		},
   324  		{
   325  			Name:          "Missing display name",
   326  			EmptyFields:   []string{runtimeTypeDisplayNameField},
   327  			ExpectedValid: false,
   328  		},
   329  		{
   330  			Name:          "Missing runtime types",
   331  			EmptyFields:   []string{runtimeTypesField},
   332  			ExpectedValid: false,
   333  		},
   334  		{
   335  			Name:          "Missing artifact kind and display name",
   336  			EmptyFields:   []string{runtimeArtifactKindField, runtimeTypeDisplayNameField},
   337  			ExpectedValid: false,
   338  		},
   339  		{
   340  			Name:          "Missing artifact kind and runtime types",
   341  			EmptyFields:   []string{runtimeArtifactKindField, runtimeTypesField},
   342  			ExpectedValid: false,
   343  		},
   344  		{
   345  			Name:          "Missing display name and runtime types",
   346  			EmptyFields:   []string{runtimeTypeDisplayNameField, runtimeTypesField},
   347  			ExpectedValid: false,
   348  		},
   349  	}
   350  
   351  	for _, testCase := range testCases {
   352  		t.Run(testCase.Name, func(t *testing.T) {
   353  			//GIVEN
   354  			formationTemplateInput := fixValidFormationTemplateInput()
   355  
   356  			for _, field := range testCase.EmptyFields {
   357  				switch field {
   358  				case runtimeTypesField:
   359  					formationTemplateInput.RuntimeTypes = []string{}
   360  				case runtimeArtifactKindField:
   361  					formationTemplateInput.RuntimeArtifactKind = nil
   362  				case runtimeTypeDisplayNameField:
   363  					formationTemplateInput.RuntimeTypeDisplayName = nil
   364  				}
   365  			}
   366  
   367  			// WHEN
   368  			err := formationTemplateInput.Validate()
   369  			// THEN
   370  			if testCase.ExpectedValid {
   371  				require.NoError(t, err)
   372  			} else {
   373  				require.Error(t, err)
   374  			}
   375  		})
   376  	}
   377  }
   378  
   379  func fixValidFormationTemplateInput() graphql.FormationTemplateInput {
   380  	kind := graphql.ArtifactTypeSubscription
   381  	return graphql.FormationTemplateInput{
   382  		Name:                   "formation-template-name",
   383  		ApplicationTypes:       []string{"some-application-type"},
   384  		RuntimeTypes:           []string{"some-runtime-type"},
   385  		RuntimeTypeDisplayName: stringPtr("display-name-for-runtime"),
   386  		RuntimeArtifactKind:    &kind,
   387  	}
   388  }