github.com/Axway/agent-sdk@v1.1.101/pkg/apic/provisioning/propertybuilder_test.go (about) 1 package provisioning 2 3 import ( 4 "strings" 5 "testing" 6 7 "github.com/stretchr/testify/assert" 8 ) 9 10 func TestNewSchemaPropertyBuilder(t *testing.T) { 11 builder := NewSchemaPropertyBuilder() 12 assert.NotNil(t, builder) 13 14 schemaProperty := builder.(*schemaProperty) 15 16 // test all the default values 17 assert.Nil(t, schemaProperty.err) 18 assert.Empty(t, schemaProperty.name) 19 assert.Empty(t, schemaProperty.description) 20 //assert.Len(t, schemaProperty.enums, 0) 21 assert.False(t, schemaProperty.required) 22 assert.False(t, schemaProperty.readOnly) 23 assert.Empty(t, schemaProperty.dataType) 24 } 25 26 func TestSubscriptionSchemaPropertyBuilderSetters(t *testing.T) { 27 // No name 28 prop, err := NewSchemaPropertyBuilder().Build() 29 30 assert.NotNil(t, err) 31 assert.Nil(t, prop) 32 33 // No datatype 34 prop, err = NewSchemaPropertyBuilder(). 35 SetName("name"). 36 Build() 37 38 assert.NotNil(t, err) 39 assert.Nil(t, prop) 40 41 // Datatype twice 42 //prop, err = NewSchemaPropertyBuilder(). 43 // SetName("name"). 44 // IsString(). 45 // Build() 46 47 //assert.NotNil(t, err) 48 //assert.Nil(t, prop) 49 50 // No datatype in dependent property 51 builder := NewSchemaPropertyBuilder(). 52 SetName("name"). 53 IsString(). 54 SetEnumValues([]string{"a", "b"}). 55 AddDependency("a", NewSchemaPropertyBuilder(). 56 SetName("noDataType")) 57 58 prop, err = builder.Build() 59 assert.Nil(t, err) 60 assert.NotNil(t, prop) 61 62 dep, err := builder.BuildDependencies() 63 assert.NotNil(t, err) 64 assert.Nil(t, dep) 65 66 // No datatype in child dependent property 67 builder = NewSchemaPropertyBuilder(). 68 SetName("name"). 69 IsString(). 70 SetEnumValues([]string{"a", "b"}). 71 AddDependency("a", NewSchemaPropertyBuilder(). 72 SetName("child"). 73 IsString(). 74 SetEnumValues([]string{"c", "d"}). 75 AddDependency("c", NewSchemaPropertyBuilder(). 76 SetName("child"))) 77 78 prop, err = builder.Build() 79 assert.Nil(t, err) 80 assert.NotNil(t, prop) 81 82 dep, err = builder.BuildDependencies() 83 assert.NotNil(t, err) 84 assert.Nil(t, dep) 85 86 // good path, no enums 87 prop, err = NewSchemaPropertyBuilder(). 88 SetName("name"). 89 SetDescription("description"). 90 SetRequired(). 91 SetReadOnly(). 92 SetHidden(). 93 IsString(). 94 Build() 95 96 assert.Nil(t, err) 97 assert.NotNil(t, prop) 98 assert.Len(t, prop.Enum, 0) 99 assert.Equal(t, "name", prop.Name) 100 assert.Equal(t, "description", prop.Description) 101 assert.True(t, prop.Required) 102 assert.True(t, prop.ReadOnly) 103 assert.Equal(t, prop.Format, "hidden") 104 105 // good path, set enums 106 prop, err = NewSchemaPropertyBuilder(). 107 SetName("name"). 108 IsString(). 109 SetEnumValues([]string{"a", "b", "c", "c"}). 110 Build() 111 112 assert.Nil(t, err) 113 assert.NotNil(t, prop) 114 assert.Len(t, prop.Enum, 3) 115 assert.Equal(t, "name", prop.Name) 116 assert.Equal(t, "", prop.Description) 117 assert.False(t, prop.Required) 118 assert.False(t, prop.ReadOnly) 119 assert.Equal(t, prop.Format, "") 120 121 // good path, add enums 122 prop, err = NewSchemaPropertyBuilder(). 123 SetName("name"). 124 IsString(). 125 AddEnumValue("a"). 126 AddEnumValue("b"). 127 AddEnumValue("c"). 128 AddEnumValue("c"). 129 Build() 130 131 assert.Nil(t, err) 132 assert.NotNil(t, prop) 133 assert.Len(t, prop.Enum, 3) 134 assert.Equal(t, "name", prop.Name) 135 assert.Equal(t, "", prop.Description) 136 assert.False(t, prop.Required) 137 assert.False(t, prop.ReadOnly) 138 assert.Equal(t, prop.Format, "") 139 140 // good path, sort enums & add first item 141 prop, err = NewSchemaPropertyBuilder(). 142 SetName("name"). 143 IsString(). 144 AddEnumValue("c"). 145 AddEnumValue("a"). 146 AddEnumValue("b"). 147 SetSortEnumValues(). 148 SetFirstEnumValue("xxx"). 149 Build() 150 151 assert.Nil(t, err) 152 assert.NotNil(t, prop) 153 assert.Len(t, prop.Enum, 4) 154 assert.Equal(t, "name", prop.Name) 155 assert.Equal(t, "", prop.Description) 156 assert.False(t, prop.Required) 157 assert.False(t, prop.ReadOnly) 158 assert.Equal(t, prop.Format, "") 159 assert.Equal(t, "xxx", prop.Enum[0]) 160 assert.Equal(t, "a", prop.Enum[1]) 161 } 162 163 func getFloat64Pointer(value float64) *float64 { 164 return &value 165 } 166 167 func getUintPointer(value uint) *uint { 168 return &value 169 } 170 171 func Test_SubscriptionPropertyBuilder_Build_with_valid_values(t *testing.T) { 172 tests := []struct { 173 name string 174 builder PropertyBuilder 175 expectedDef propertyDefinition 176 expectedDependencies *oneOfPropertyDefinitions 177 }{ 178 {"Minimal String property", 179 NewSchemaPropertyBuilder(). 180 SetName("TheName"). 181 SetLabel("The Label"). 182 IsString(), 183 propertyDefinition{ 184 Name: "TheName", 185 Title: "The Label", 186 Type: DataTypeString, 187 }, 188 nil}, 189 {"String property with dependencies", 190 NewSchemaPropertyBuilder(). 191 SetName("TheName"). 192 SetLabel("The Label"). 193 IsString(). 194 SetEnumValues([]string{"a", "b", "c"}). 195 AddDependency("a", NewSchemaPropertyBuilder(). 196 SetName("TheDependent"). 197 SetLabel("The Dependent").IsString()), 198 propertyDefinition{ 199 Name: "TheName", 200 Title: "The Label", 201 Type: DataTypeString, 202 Enum: []string{"a", "b", "c"}, 203 }, 204 &oneOfPropertyDefinitions{ 205 OneOf: []*propertyDefinition{ 206 { 207 Properties: map[string]propertyDefinition{ 208 "TheName": { 209 Enum: []string{"a"}, 210 }, 211 "TheDependent": { 212 Type: DataTypeString, 213 Name: "TheDependent", 214 Title: "The Dependent", 215 }, 216 }, 217 }, 218 { 219 Properties: map[string]propertyDefinition{ 220 "TheName": { 221 Enum: []string{"b"}, 222 }, 223 }, 224 }, 225 { 226 Properties: map[string]propertyDefinition{ 227 "TheName": { 228 Enum: []string{"c"}, 229 }, 230 }, 231 }, 232 }, 233 }, 234 }, 235 {"String child property with dependencies", 236 NewSchemaPropertyBuilder(). 237 SetName("TheName"). 238 SetLabel("The Label"). 239 IsString(). 240 SetEnumValues([]string{"a", "b"}). 241 AddDependency("a", NewSchemaPropertyBuilder(). 242 SetName("TheChild"). 243 SetLabel("The Child"). 244 IsString(). 245 SetEnumValues([]string{"a", "b"}). 246 AddDependency("a", NewSchemaPropertyBuilder(). 247 SetName("TheDependent"). 248 SetLabel("The Dependent"). 249 IsString()), 250 ), 251 propertyDefinition{ 252 Name: "TheName", 253 Title: "The Label", 254 Type: DataTypeString, 255 Enum: []string{"a", "b"}, 256 }, 257 &oneOfPropertyDefinitions{ 258 OneOf: []*propertyDefinition{ 259 { 260 Properties: map[string]propertyDefinition{ 261 "TheName": { 262 Enum: []string{"a"}, 263 }, 264 "TheChild": { 265 Type: DataTypeString, 266 Name: "TheChild", 267 Title: "The Child", 268 Enum: []string{"a", "b"}, 269 }, 270 }, 271 Dependencies: map[string]*oneOfPropertyDefinitions{ 272 "TheChild": { 273 OneOf: []*propertyDefinition{ 274 { 275 Properties: map[string]propertyDefinition{ 276 "TheChild": { 277 Enum: []string{"a"}, 278 }, 279 "TheDependent": { 280 Type: DataTypeString, 281 Name: "TheDependent", 282 Title: "The Dependent", 283 }, 284 }, 285 }, 286 }, 287 }, 288 }, 289 }, 290 { 291 Properties: map[string]propertyDefinition{ 292 "TheName": { 293 Enum: []string{"b"}, 294 }, 295 }, 296 }, 297 }, 298 }, 299 }, 300 {"Full String property with unsorted enum and first value", 301 NewSchemaPropertyBuilder(). 302 SetName("TheName"). 303 SetLabel("The Label"). 304 SetDescription("TheDescription"). 305 SetRequired(). 306 SetHidden(). 307 SetReadOnly(). 308 IsString(). 309 IsEncrypted(). 310 SetAsTextArea(). 311 SetEnumValues([]string{"c", "a", "b"}). 312 AddEnumValue("addedValue"). 313 SetFirstEnumValue("firstValue"). 314 SetDefaultValue("a"), 315 propertyDefinition{ 316 Name: "TheName", 317 Title: "The Label", 318 Description: "TheDescription", 319 Required: true, 320 Format: "hidden", 321 ReadOnly: true, 322 IsEncrypted: true, 323 Widget: "textArea", 324 Type: DataTypeString, 325 Enum: []string{"firstValue", "c", "a", "b", "addedValue"}, 326 DefaultValue: "a", 327 }, 328 nil}, 329 {"Full String property with sorted enum and first value", 330 NewSchemaPropertyBuilder(). 331 SetName("TheName"). 332 SetLabel("The Label"). 333 SetDescription("TheDescription"). 334 SetRequired(). 335 SetHidden(). 336 SetReadOnly(). 337 IsString(). 338 IsEncrypted(). 339 SetAsTextArea(). 340 SetEnumValues([]string{"c", "a", "b"}). 341 AddEnumValue("addedValue"). 342 SetFirstEnumValue("firstValue"). 343 SetSortEnumValues(). 344 SetDefaultValue("a"), 345 propertyDefinition{ 346 Name: "TheName", 347 Title: "The Label", 348 Description: "TheDescription", 349 Required: true, 350 Format: "hidden", 351 ReadOnly: true, 352 IsEncrypted: true, 353 Widget: "textArea", 354 Type: DataTypeString, 355 Enum: []string{"firstValue", "a", "addedValue", "b", "c"}, 356 DefaultValue: "a", 357 }, 358 nil}, 359 {"Minimal Number property", 360 NewSchemaPropertyBuilder(). 361 SetName("TheName"). 362 SetLabel("The Label"). 363 IsNumber(), 364 propertyDefinition{ 365 Name: "TheName", 366 Title: "The Label", 367 Type: DataTypeNumber, 368 }, 369 nil}, 370 {"Full Number property", 371 NewSchemaPropertyBuilder(). 372 SetName("TheName"). 373 SetLabel("The Label"). 374 SetDescription("TheDescription"). 375 SetRequired(). 376 SetHidden(). 377 SetReadOnly(). 378 IsNumber(). 379 SetMinValue(0.0). 380 SetMaxValue(100.5). 381 SetDefaultValue(50.5), 382 propertyDefinition{ 383 Name: "TheName", 384 Title: "The Label", 385 Description: "TheDescription", 386 Required: true, 387 Format: "hidden", 388 ReadOnly: true, 389 Type: DataTypeNumber, 390 Minimum: getFloat64Pointer(0.0), 391 Maximum: getFloat64Pointer(100.5), 392 DefaultValue: getFloat64Pointer(50.5), 393 }, 394 nil}, 395 {"Minimal Integer property", 396 NewSchemaPropertyBuilder(). 397 SetName("TheName"). 398 SetLabel("The Label"). 399 IsInteger(), 400 propertyDefinition{ 401 Name: "TheName", 402 Title: "The Label", 403 Type: DataTypeInteger, 404 }, 405 nil}, 406 {"Full Integer property", 407 NewSchemaPropertyBuilder(). 408 SetName("TheName"). 409 SetLabel("The Label"). 410 SetDescription("TheDescription"). 411 SetRequired(). 412 SetHidden(). 413 SetReadOnly(). 414 IsInteger(). 415 SetMinValue(0). 416 SetMaxValue(100). 417 SetDefaultValue(50), 418 propertyDefinition{ 419 Name: "TheName", 420 Title: "The Label", 421 Description: "TheDescription", 422 Required: true, 423 Format: "hidden", 424 ReadOnly: true, 425 Type: DataTypeInteger, 426 Minimum: getFloat64Pointer(0), 427 Maximum: getFloat64Pointer(100), 428 DefaultValue: getFloat64Pointer(50), 429 }, 430 nil}, 431 {"Minimal Array property", 432 NewSchemaPropertyBuilder(). 433 SetName("TheName"). 434 SetLabel("The Label"). 435 IsArray(), 436 propertyDefinition{ 437 Name: "TheName", 438 Title: "The Label", 439 Type: DataTypeArray, 440 }, 441 nil}, 442 {"Full Array property", 443 NewSchemaPropertyBuilder(). 444 SetName("TheName"). 445 SetLabel("The Label"). 446 SetDescription("TheDescription"). 447 SetRequired(). 448 SetHidden(). 449 SetReadOnly(). 450 IsArray(). 451 AddItem(NewSchemaPropertyBuilder(). 452 SetName("ItemName"). 453 SetLabel("Item Label"). 454 IsString()). 455 SetMinItems(0). 456 SetMaxItems(1), 457 propertyDefinition{ 458 Name: "TheName", 459 Title: "The Label", 460 Description: "TheDescription", 461 Required: true, 462 Format: "hidden", 463 ReadOnly: true, 464 Type: DataTypeArray, 465 Items: &anyOfPropertyDefinitions{ 466 AnyOf: []propertyDefinition{ 467 { 468 Name: "ItemName", 469 Title: "Item Label", 470 Type: DataTypeString, 471 }, 472 }, 473 }, 474 MinItems: getUintPointer(0), 475 MaxItems: getUintPointer(1), 476 UniqueItems: true, 477 }, 478 nil}, 479 {"Minimal Object property", 480 NewSchemaPropertyBuilder(). 481 SetName("TheName"). 482 IsObject(), 483 propertyDefinition{ 484 Name: "TheName", 485 Type: DataTypeObject, 486 }, 487 nil}, 488 {"Full Object property", 489 NewSchemaPropertyBuilder(). 490 SetName("TheName"). 491 SetLabel("The Label"). 492 SetDescription("TheDescription"). 493 SetRequired(). 494 SetHidden(). 495 SetReadOnly(). 496 IsObject(). 497 AddProperty(NewSchemaPropertyBuilder(). 498 SetName("PropertyName"). 499 SetLabel("Property Label"). 500 SetRequired(). 501 IsString()), 502 propertyDefinition{ 503 Name: "TheName", 504 Title: "The Label", 505 Description: "TheDescription", 506 Required: true, 507 Format: "hidden", 508 ReadOnly: true, 509 Type: DataTypeObject, 510 Properties: map[string]propertyDefinition{ 511 "PropertyName": { 512 Name: "PropertyName", 513 Title: "Property Label", 514 Type: DataTypeString, 515 Required: true, 516 }, 517 }, 518 RequiredProperties: []string{ 519 "PropertyName", 520 }, 521 }, 522 nil}, 523 } 524 for _, tt := range tests { 525 t.Run(tt.name, func(t *testing.T) { 526 def, err := tt.builder.Build() 527 assert.Nil(t, err) 528 assert.Equal(t, tt.expectedDef, *def) 529 deps, err := tt.builder.BuildDependencies() 530 assert.Nil(t, err) 531 assertDependencies(t, def.Name, tt.expectedDependencies, deps) 532 }) 533 } 534 } 535 536 func assertDependencies(t *testing.T, propName string, expectedDependencies, deps *oneOfPropertyDefinitions) { 537 if expectedDependencies == nil { 538 assert.Nil(t, deps) 539 return 540 } 541 assert.NotNil(t, deps) 542 for index, expectedDepDef := range expectedDependencies.OneOf { 543 depDef := deps.OneOf[index] 544 expectedEnumDepProps := make(map[string]propertyDefinition) 545 enumDepProps := make(map[string]propertyDefinition) 546 for name, expectedProperty := range expectedDepDef.Properties { 547 assert.Contains(t, depDef.Properties, name) 548 if expectedProperty.Name == propName { 549 expectedEnumDepProps[expectedProperty.Enum[0]] = expectedProperty 550 } 551 } 552 553 for _, expectedProperty := range depDef.Properties { 554 if expectedProperty.Name == propName { 555 enumDepProps[expectedProperty.Enum[0]] = expectedProperty 556 } 557 } 558 assert.Equal(t, len(enumDepProps), len(expectedEnumDepProps)) 559 for enum, expectedProperty := range expectedEnumDepProps { 560 depProp := enumDepProps[enum] 561 assert.Equal(t, expectedProperty, depProp) 562 } 563 if expectedDepDef.Dependencies != nil { 564 assert.NotNil(t, depDef.Dependencies) 565 } 566 for name, expectedChildDependencies := range expectedDepDef.Dependencies { 567 childDeps, ok := depDef.Dependencies[name] 568 assert.True(t, ok) 569 assertDependencies(t, expectedDepDef.Name, expectedChildDependencies, childDeps) 570 } 571 } 572 } 573 574 func Test_SubscriptionPropertyBuilder_Build_with_error(t *testing.T) { 575 tests := []struct { 576 name string 577 builder PropertyBuilder 578 errorPattern string 579 }{ 580 {"String property without name", NewSchemaPropertyBuilder(). 581 IsString(), "without a name"}, 582 {"String property with default value not present in enum list", NewSchemaPropertyBuilder(). 583 SetName("aString"). 584 IsString(). 585 SetEnumValues([]string{"a", "b"}). 586 SetDefaultValue("z"), "must be present in the enum list"}, 587 {"Number property without name", NewSchemaPropertyBuilder(). 588 IsNumber(), "without a name"}, 589 {"Number property with min greater than max", NewSchemaPropertyBuilder(). 590 SetName("aNumber"). 591 IsNumber(). 592 SetMinValue(2). 593 SetMaxValue(1), "greater than"}, 594 {"Number property with default value greater than max", NewSchemaPropertyBuilder(). 595 SetName("aNumber"). 596 IsNumber(). 597 SetMaxValue(1). 598 SetDefaultValue(2), "must be equal or lower than max value"}, 599 {"Number property with default value lower than min", NewSchemaPropertyBuilder(). 600 SetName("aNumber"). 601 IsNumber(). 602 SetMinValue(2). 603 SetDefaultValue(1), "must be equal or greater than min value"}, 604 {"Integer property without name", NewSchemaPropertyBuilder(). 605 IsInteger(), 606 "without a name"}, 607 {"Integer property with min greater than max", NewSchemaPropertyBuilder(). 608 SetName("anInteger"). 609 IsInteger(). 610 SetMinValue(2). 611 SetMaxValue(1), "greater than"}, 612 {"Integer property with default value greater than max", NewSchemaPropertyBuilder(). 613 SetName("aNumber"). 614 IsInteger(). 615 SetMaxValue(1). 616 SetDefaultValue(2), "must be equal or lower than max value"}, 617 {"Integer property with default value lower than min", NewSchemaPropertyBuilder(). 618 SetName("aNumber"). 619 IsInteger(). 620 SetMinValue(2). 621 SetDefaultValue(1), "must be equal or greater than min value"}, 622 {"Array property without name", NewSchemaPropertyBuilder(). 623 IsArray(), "without a name"}, 624 {"Array property with min items greater than max items", NewSchemaPropertyBuilder(). 625 SetName("anArray"). 626 IsArray(). 627 SetMinItems(2). 628 SetMaxItems(1), "greater than"}, 629 {"Array property with wrong max items", NewSchemaPropertyBuilder(). 630 SetName("anArray"). 631 IsArray(). 632 SetMaxItems(0), "greater than 0"}, 633 {"Array property with error on added item", NewSchemaPropertyBuilder(). 634 SetName("anArray"). 635 IsArray(). 636 AddItem(NewSchemaPropertyBuilder()), "without a name"}, 637 {"Object property without name", NewSchemaPropertyBuilder(). 638 IsObject(), "without a name"}, 639 {"Object property with error on added property", NewSchemaPropertyBuilder(). 640 SetName("anObject"). 641 IsObject(). 642 AddProperty(NewSchemaPropertyBuilder()), "without a name"}, 643 } 644 for _, tt := range tests { 645 t.Run(tt.name, func(t *testing.T) { 646 prop, err := tt.builder.Build() 647 assert.NotNil(t, err) 648 assert.True(t, strings.Contains(err.Error(), tt.errorPattern)) 649 assert.Nil(t, prop) 650 }) 651 } 652 }