github.com/prebid/prebid-server@v0.275.0/endpoints/events/vtrack_test.go (about) 1 package events 2 3 import ( 4 "bytes" 5 "context" 6 "encoding/json" 7 "errors" 8 "fmt" 9 "io" 10 "net/http" 11 "net/http/httptest" 12 "strings" 13 "testing" 14 15 "github.com/prebid/prebid-server/config" 16 "github.com/prebid/prebid-server/prebid_cache_client" 17 "github.com/prebid/prebid-server/stored_requests" 18 "github.com/stretchr/testify/assert" 19 ) 20 21 const ( 22 maxSize = 1024 * 256 23 24 vastXmlWithImpressionWithContent = "<VAST version=\"3.0\"><Ad><Wrapper><AdSystem>prebid.org wrapper</AdSystem><VASTAdTagURI><![CDATA[adm2]]></VASTAdTagURI><Impression>content</Impression><Creatives></Creatives></Wrapper></Ad></VAST>" 25 vastXmlWithImpressionWithoutContent = "<VAST version=\"3.0\"><Ad><Wrapper><AdSystem>prebid.org wrapper</AdSystem><VASTAdTagURI><![CDATA[adm2]]></VASTAdTagURI><Impression></Impression><Creatives></Creatives></Wrapper></Ad></VAST>" 26 vastXmlWithoutImpression = "<VAST version=\"3.0\"><Ad><Wrapper><AdSystem>prebid.org wrapper</AdSystem><VASTAdTagURI><![CDATA[adm2]]></VASTAdTagURI><Creatives></Creatives></Wrapper></Ad></VAST>" 27 ) 28 29 // Mock pbs cache client 30 type vtrackMockCacheClient struct { 31 Fail bool 32 Error error 33 Uuids []string 34 } 35 36 func (m *vtrackMockCacheClient) PutJson(ctx context.Context, values []prebid_cache_client.Cacheable) ([]string, []error) { 37 if m.Fail { 38 return []string{}, []error{m.Error} 39 } 40 return m.Uuids, []error{} 41 } 42 func (m *vtrackMockCacheClient) GetExtCacheData() (scheme string, host string, path string) { 43 return 44 } 45 46 // Test 47 func TestShouldRespondWithBadRequestWhenAccountParameterIsMissing(t *testing.T) { 48 // mock pbs cache client 49 mockCacheClient := &vtrackMockCacheClient{} 50 51 // mock AccountsFetcher 52 mockAccountsFetcher := &mockAccountsFetcher{} 53 54 // mock config 55 cfg := &config.Configuration{ 56 AccountDefaults: config.Account{}, 57 } 58 cfg.MarshalAccountDefaults() 59 60 // prepare 61 reqData := "" 62 63 req := httptest.NewRequest("POST", "/vtrack", strings.NewReader(reqData)) 64 recorder := httptest.NewRecorder() 65 66 e := vtrackEndpoint{ 67 Cfg: cfg, 68 BidderInfos: nil, 69 Cache: mockCacheClient, 70 Accounts: mockAccountsFetcher, 71 } 72 73 // execute 74 e.Handle(recorder, req, nil) 75 76 d, err := io.ReadAll(recorder.Result().Body) 77 if err != nil { 78 t.Fatal(err) 79 } 80 81 // validate 82 assert.Equal(t, 400, recorder.Result().StatusCode, "Expected 400 on request with missing account parameter") 83 assert.Equal(t, "Account 'a' is required query parameter and can't be empty", string(d)) 84 } 85 86 func TestShouldRespondWithBadRequestWhenRequestBodyIsEmpty(t *testing.T) { 87 // mock pbs cache client 88 mockCacheClient := &vtrackMockCacheClient{} 89 90 // mock AccountsFetcher 91 mockAccountsFetcher := &mockAccountsFetcher{} 92 93 // config 94 cfg := &config.Configuration{ 95 MaxRequestSize: maxSize, 96 AccountDefaults: config.Account{}, 97 } 98 cfg.MarshalAccountDefaults() 99 100 // prepare 101 reqData := "" 102 103 req := httptest.NewRequest("POST", "/vtrack?a=events_enabled", strings.NewReader(reqData)) 104 105 recorder := httptest.NewRecorder() 106 107 e := vtrackEndpoint{ 108 Cfg: cfg, 109 BidderInfos: nil, 110 Cache: mockCacheClient, 111 Accounts: mockAccountsFetcher, 112 } 113 114 // execute 115 e.Handle(recorder, req, nil) 116 117 d, err := io.ReadAll(recorder.Result().Body) 118 if err != nil { 119 t.Fatal(err) 120 } 121 122 // validate 123 assert.Equal(t, 400, recorder.Result().StatusCode, "Expected 400 on request with empty body") 124 assert.Equal(t, "Invalid request: request body is empty\n", string(d)) 125 } 126 127 func TestShouldRespondWithBadRequestWhenRequestBodyIsInvalid(t *testing.T) { 128 // mock pbs cache client 129 mockCacheClient := &vtrackMockCacheClient{} 130 131 // mock AccountsFetcher 132 mockAccountsFetcher := &mockAccountsFetcher{} 133 134 // config 135 cfg := &config.Configuration{ 136 MaxRequestSize: maxSize, 137 AccountDefaults: config.Account{}, 138 } 139 cfg.MarshalAccountDefaults() 140 141 // prepare 142 reqData := "invalid" 143 144 req := httptest.NewRequest("POST", "/vtrack?a=events_enabled", strings.NewReader(reqData)) 145 146 recorder := httptest.NewRecorder() 147 148 e := vtrackEndpoint{ 149 Cfg: cfg, 150 BidderInfos: nil, 151 Cache: mockCacheClient, 152 Accounts: mockAccountsFetcher, 153 } 154 155 // execute 156 e.Handle(recorder, req, nil) 157 158 // validate 159 assert.Equal(t, 400, recorder.Result().StatusCode, "Expected 400 on request with invalid body") 160 } 161 162 func TestShouldRespondWithBadRequestWhenBidIdIsMissing(t *testing.T) { 163 // mock pbs cache client 164 mockCacheClient := &vtrackMockCacheClient{} 165 166 // mock AccountsFetcher 167 mockAccountsFetcher := &mockAccountsFetcher{} 168 169 // config 170 cfg := &config.Configuration{ 171 MaxRequestSize: maxSize, 172 AccountDefaults: config.Account{}, 173 } 174 cfg.MarshalAccountDefaults() 175 176 // prepare 177 data := &BidCacheRequest{ 178 Puts: []prebid_cache_client.Cacheable{ 179 {}, 180 }, 181 } 182 183 reqData, err := json.Marshal(data) 184 if err != nil { 185 t.Fatal(err) 186 } 187 188 req := httptest.NewRequest("POST", "/vtrack?a=events_enabled", strings.NewReader(string(reqData))) 189 190 recorder := httptest.NewRecorder() 191 192 e := vtrackEndpoint{ 193 Cfg: cfg, 194 BidderInfos: nil, 195 Cache: mockCacheClient, 196 Accounts: mockAccountsFetcher, 197 } 198 199 // execute 200 e.Handle(recorder, req, nil) 201 202 d, err := io.ReadAll(recorder.Result().Body) 203 if err != nil { 204 t.Fatal(err) 205 } 206 207 // validate 208 assert.Equal(t, 400, recorder.Result().StatusCode, "Expected 400 on request with elements missing bidid") 209 assert.Equal(t, "Invalid request: 'bidid' is required field and can't be empty\n", string(d)) 210 } 211 212 func TestShouldRespondWithBadRequestWhenBidderIsMissing(t *testing.T) { 213 // mock pbs cache client 214 mockCacheClient := &vtrackMockCacheClient{} 215 216 // mock AccountsFetcher 217 mockAccountsFetcher := &mockAccountsFetcher{} 218 219 // config 220 cfg := &config.Configuration{ 221 MaxRequestSize: maxSize, 222 AccountDefaults: config.Account{}, 223 } 224 cfg.MarshalAccountDefaults() 225 226 // prepare 227 data := &BidCacheRequest{ 228 Puts: []prebid_cache_client.Cacheable{ 229 { 230 BidID: "test", 231 }, 232 }, 233 } 234 235 reqData, err := json.Marshal(data) 236 if err != nil { 237 t.Fatal(err) 238 } 239 240 req := httptest.NewRequest("POST", "/vtrack?a=events_enabled", strings.NewReader(string(reqData))) 241 242 recorder := httptest.NewRecorder() 243 244 e := vtrackEndpoint{ 245 Cfg: cfg, 246 BidderInfos: nil, 247 Cache: mockCacheClient, 248 Accounts: mockAccountsFetcher, 249 } 250 251 // execute 252 e.Handle(recorder, req, nil) 253 254 d, err := io.ReadAll(recorder.Result().Body) 255 if err != nil { 256 t.Fatal(err) 257 } 258 259 // validate 260 assert.Equal(t, 400, recorder.Result().StatusCode, "Expected 400 on request with elements missing bidder") 261 assert.Equal(t, "Invalid request: 'bidder' is required field and can't be empty\n", string(d)) 262 } 263 264 func TestShouldRespondWithInternalServerErrorWhenPbsCacheClientFails(t *testing.T) { 265 // mock pbs cache client 266 mockCacheClient := &vtrackMockCacheClient{ 267 Fail: true, 268 Error: fmt.Errorf("pbs cache client failed"), 269 } 270 271 // mock AccountsFetcher 272 mockAccountsFetcher := &mockAccountsFetcher{} 273 274 // config 275 cfg := &config.Configuration{ 276 MaxRequestSize: maxSize, VTrack: config.VTrack{ 277 TimeoutMS: int64(2000), AllowUnknownBidder: true, 278 }, 279 AccountDefaults: config.Account{}, 280 } 281 cfg.MarshalAccountDefaults() 282 283 // prepare 284 data, err := getValidVTrackRequestBody(false, false) 285 if err != nil { 286 t.Fatal(err) 287 } 288 289 req := httptest.NewRequest("POST", "/vtrack?a=events_enabled", strings.NewReader(data)) 290 291 recorder := httptest.NewRecorder() 292 293 e := vtrackEndpoint{ 294 Cfg: cfg, 295 BidderInfos: nil, 296 Cache: mockCacheClient, 297 Accounts: mockAccountsFetcher, 298 } 299 300 // execute 301 e.Handle(recorder, req, nil) 302 303 d, err := io.ReadAll(recorder.Result().Body) 304 if err != nil { 305 t.Fatal(err) 306 } 307 308 // validate 309 assert.Equal(t, 500, recorder.Result().StatusCode, "Expected 500 when pbs cache client fails") 310 assert.Equal(t, "Error(s) updating vast: pbs cache client failed\n", string(d)) 311 } 312 313 func TestShouldTolerateAccountNotFound(t *testing.T) { 314 // mock pbs cache client 315 mockCacheClient := &vtrackMockCacheClient{} 316 317 // mock AccountsFetcher 318 mockAccountsFetcher := &mockAccountsFetcher{ 319 Fail: true, 320 Error: stored_requests.NotFoundError{}, 321 } 322 323 // config 324 cfg := &config.Configuration{ 325 MaxRequestSize: maxSize, VTrack: config.VTrack{ 326 TimeoutMS: int64(2000), AllowUnknownBidder: false, 327 }, 328 AccountDefaults: config.Account{}, 329 } 330 cfg.MarshalAccountDefaults() 331 332 // prepare 333 data, err := getValidVTrackRequestBody(true, false) 334 if err != nil { 335 t.Fatal(err) 336 } 337 338 req := httptest.NewRequest("POST", "/vtrack?a=1235", strings.NewReader(data)) 339 340 recorder := httptest.NewRecorder() 341 342 e := vtrackEndpoint{ 343 Cfg: cfg, 344 BidderInfos: nil, 345 Cache: mockCacheClient, 346 Accounts: mockAccountsFetcher, 347 } 348 349 // execute 350 e.Handle(recorder, req, nil) 351 352 // validate 353 assert.Equal(t, 200, recorder.Result().StatusCode, "Expected 200 when account is not found and request is valid") 354 assert.Equal(t, "application/json", recorder.Header().Get("Content-Type")) 355 } 356 357 func TestShouldSendToCacheExpectedPutsAndUpdatableBiddersWhenBidderVastNotAllowed(t *testing.T) { 358 // mock pbs cache client 359 mockCacheClient := &vtrackMockCacheClient{ 360 Fail: false, 361 Uuids: []string{"uuid1"}, 362 } 363 364 // mock AccountsFetcher 365 mockAccountsFetcher := &mockAccountsFetcher{ 366 Fail: false, 367 } 368 369 // config 370 cfg := &config.Configuration{ 371 MaxRequestSize: maxSize, VTrack: config.VTrack{ 372 TimeoutMS: int64(2000), AllowUnknownBidder: false, 373 }, 374 AccountDefaults: config.Account{}, 375 } 376 cfg.MarshalAccountDefaults() 377 378 // bidder info 379 bidderInfos := make(config.BidderInfos) 380 bidderInfos["bidder"] = config.BidderInfo{ 381 Disabled: false, 382 ModifyingVastXmlAllowed: false, 383 } 384 bidderInfos["updatable_bidder"] = config.BidderInfo{ 385 Disabled: false, 386 ModifyingVastXmlAllowed: true, 387 } 388 389 // prepare 390 data, err := getValidVTrackRequestBody(false, false) 391 if err != nil { 392 t.Fatal(err) 393 } 394 395 req := httptest.NewRequest("POST", "/vtrack?a=events_enabled", strings.NewReader(data)) 396 397 recorder := httptest.NewRecorder() 398 399 e := vtrackEndpoint{ 400 Cfg: cfg, 401 BidderInfos: bidderInfos, 402 Cache: mockCacheClient, 403 Accounts: mockAccountsFetcher, 404 } 405 406 // execute 407 e.Handle(recorder, req, nil) 408 409 d, err := io.ReadAll(recorder.Result().Body) 410 if err != nil { 411 t.Fatal(err) 412 } 413 414 // validate 415 assert.Equal(t, 200, recorder.Result().StatusCode, "Expected 200 when account is not found and request is valid") 416 assert.Equal(t, "{\"responses\":[{\"uuid\":\"uuid1\"}]}", string(d), "Expected 200 when account is found and request is valid") 417 assert.Equal(t, "application/json", recorder.Header().Get("Content-Type")) 418 } 419 420 func TestShouldSendToCacheExpectedPutsAndUpdatableBiddersWhenBidderVastAllowed(t *testing.T) { 421 // mock pbs cache client 422 mockCacheClient := &vtrackMockCacheClient{ 423 Fail: false, 424 Uuids: []string{"uuid1", "uuid2"}, 425 } 426 427 // mock AccountsFetcher 428 mockAccountsFetcher := &mockAccountsFetcher{ 429 Fail: false, 430 } 431 432 // config 433 cfg := &config.Configuration{ 434 MaxRequestSize: maxSize, VTrack: config.VTrack{ 435 TimeoutMS: int64(2000), AllowUnknownBidder: false, 436 }, 437 AccountDefaults: config.Account{}, 438 } 439 cfg.MarshalAccountDefaults() 440 441 // bidder info 442 bidderInfos := make(config.BidderInfos) 443 bidderInfos["bidder"] = config.BidderInfo{ 444 Disabled: false, 445 ModifyingVastXmlAllowed: true, 446 } 447 bidderInfos["updatable_bidder"] = config.BidderInfo{ 448 Disabled: false, 449 ModifyingVastXmlAllowed: true, 450 } 451 452 // prepare 453 data, err := getValidVTrackRequestBody(true, true) 454 if err != nil { 455 t.Fatal(err) 456 } 457 458 req := httptest.NewRequest("POST", "/vtrack?a=events_enabled", strings.NewReader(data)) 459 460 recorder := httptest.NewRecorder() 461 462 e := vtrackEndpoint{ 463 Cfg: cfg, 464 BidderInfos: bidderInfos, 465 Cache: mockCacheClient, 466 Accounts: mockAccountsFetcher, 467 } 468 469 // execute 470 e.Handle(recorder, req, nil) 471 472 d, err := io.ReadAll(recorder.Result().Body) 473 if err != nil { 474 t.Fatal(err) 475 } 476 477 // validate 478 assert.Equal(t, 200, recorder.Result().StatusCode, "Expected 200 when account is not found and request is valid") 479 assert.Equal(t, "{\"responses\":[{\"uuid\":\"uuid1\"},{\"uuid\":\"uuid2\"}]}", string(d), "Expected 200 when account is found and request is valid") 480 assert.Equal(t, "application/json", recorder.Header().Get("Content-Type")) 481 } 482 483 func TestShouldSendToCacheExpectedPutsAndUpdatableUnknownBiddersWhenUnknownBidderIsAllowed(t *testing.T) { 484 // mock pbs cache client 485 mockCacheClient := &vtrackMockCacheClient{ 486 Fail: false, 487 Uuids: []string{"uuid1", "uuid2"}, 488 } 489 490 // mock AccountsFetcher 491 mockAccountsFetcher := &mockAccountsFetcher{ 492 Fail: false, 493 } 494 495 // config 496 cfg := &config.Configuration{ 497 MaxRequestSize: maxSize, VTrack: config.VTrack{ 498 TimeoutMS: int64(2000), AllowUnknownBidder: true, 499 }, 500 AccountDefaults: config.Account{}, 501 } 502 cfg.MarshalAccountDefaults() 503 504 // bidder info 505 bidderInfos := make(config.BidderInfos) 506 507 // prepare 508 data, err := getValidVTrackRequestBody(true, false) 509 if err != nil { 510 t.Fatal(err) 511 } 512 513 req := httptest.NewRequest("POST", "/vtrack?a=events_enabled", strings.NewReader(data)) 514 515 recorder := httptest.NewRecorder() 516 517 e := vtrackEndpoint{ 518 Cfg: cfg, 519 BidderInfos: bidderInfos, 520 Cache: mockCacheClient, 521 Accounts: mockAccountsFetcher, 522 } 523 524 // execute 525 e.Handle(recorder, req, nil) 526 527 d, err := io.ReadAll(recorder.Result().Body) 528 if err != nil { 529 t.Fatal(err) 530 } 531 532 // validate 533 assert.Equal(t, 200, recorder.Result().StatusCode, "Expected 200 when account is not found and request is valid") 534 assert.Equal(t, "{\"responses\":[{\"uuid\":\"uuid1\"},{\"uuid\":\"uuid2\"}]}", string(d), "Expected 200 when account is found, request has unknown bidders but allowUnknownBidders is enabled") 535 assert.Equal(t, "application/json", recorder.Header().Get("Content-Type")) 536 } 537 538 func TestShouldReturnBadRequestWhenRequestExceedsMaxRequestSize(t *testing.T) { 539 // mock pbs cache client 540 mockCacheClient := &vtrackMockCacheClient{ 541 Fail: false, 542 Uuids: []string{"uuid1", "uuid2"}, 543 } 544 545 // mock AccountsFetcher 546 mockAccountsFetcher := &mockAccountsFetcher{ 547 Fail: false, 548 } 549 550 // config 551 cfg := &config.Configuration{ 552 MaxRequestSize: 1, 553 VTrack: config.VTrack{ 554 TimeoutMS: int64(2000), AllowUnknownBidder: true, 555 }, 556 AccountDefaults: config.Account{}, 557 } 558 cfg.MarshalAccountDefaults() 559 560 // bidder info 561 bidderInfos := make(config.BidderInfos) 562 563 // prepare 564 data, err := getValidVTrackRequestBody(true, false) 565 if err != nil { 566 t.Fatal(err) 567 } 568 569 req := httptest.NewRequest("POST", "/vtrack?a=events_enabled", strings.NewReader(data)) 570 571 recorder := httptest.NewRecorder() 572 573 e := vtrackEndpoint{ 574 Cfg: cfg, 575 BidderInfos: bidderInfos, 576 Cache: mockCacheClient, 577 Accounts: mockAccountsFetcher, 578 } 579 580 // execute 581 e.Handle(recorder, req, nil) 582 583 d, err := io.ReadAll(recorder.Result().Body) 584 if err != nil { 585 t.Fatal(err) 586 } 587 588 // validate 589 assert.Equal(t, 400, recorder.Result().StatusCode, "Expected 400 when request exceeds max request size") 590 assert.Equal(t, "Invalid request: request size exceeded max size of 1 bytes\n", string(d)) 591 } 592 593 func TestShouldRespondWithInternalErrorPbsCacheIsNotConfigured(t *testing.T) { 594 // mock AccountsFetcher 595 mockAccountsFetcher := &mockAccountsFetcher{ 596 Fail: false, 597 } 598 599 // config 600 cfg := &config.Configuration{ 601 MaxRequestSize: maxSize, VTrack: config.VTrack{ 602 TimeoutMS: int64(2000), AllowUnknownBidder: false, 603 }, 604 AccountDefaults: config.Account{}, 605 } 606 cfg.MarshalAccountDefaults() 607 608 // prepare 609 data, err := getValidVTrackRequestBody(true, true) 610 if err != nil { 611 t.Fatal(err) 612 } 613 614 req := httptest.NewRequest("POST", "/vtrack?a=events_enabled", strings.NewReader(data)) 615 recorder := httptest.NewRecorder() 616 617 e := vtrackEndpoint{ 618 Cfg: cfg, 619 BidderInfos: nil, 620 Cache: nil, 621 Accounts: mockAccountsFetcher, 622 } 623 624 // execute 625 e.Handle(recorder, req, nil) 626 627 d, err := io.ReadAll(recorder.Result().Body) 628 if err != nil { 629 t.Fatal(err) 630 } 631 632 // validate 633 assert.Equal(t, 500, recorder.Result().StatusCode, "Expected 500 when pbs cache is not configured") 634 assert.Equal(t, "PBS Cache client is not configured", string(d)) 635 } 636 637 func TestVastUrlShouldReturnExpectedUrl(t *testing.T) { 638 url := GetVastUrlTracking("http://external-url", "bidId", "bidder", "accountId", 1000, "integrationType") 639 assert.Equal(t, "http://external-url/event?t=imp&b=bidId&a=accountId&bidder=bidder&f=b&int=integrationType&ts=1000", url, "Invalid vast url") 640 } 641 642 func getValidVTrackRequestBody(withImpression bool, withContent bool) (string, error) { 643 d, e := getVTrackRequestData(withImpression, withContent) 644 645 if e != nil { 646 return "", e 647 } 648 649 req := &BidCacheRequest{ 650 Puts: []prebid_cache_client.Cacheable{ 651 { 652 Type: prebid_cache_client.TypeXML, 653 BidID: "bidId1", 654 Bidder: "bidder", 655 Data: d, 656 TTLSeconds: 3600, 657 Timestamp: 1000, 658 }, 659 { 660 Type: prebid_cache_client.TypeXML, 661 BidID: "bidId2", 662 Bidder: "updatable_bidder", 663 Data: d, 664 TTLSeconds: 3600, 665 Timestamp: 1000, 666 }, 667 }, 668 } 669 670 buf := &bytes.Buffer{} 671 enc := json.NewEncoder(buf) 672 enc.SetEscapeHTML(false) 673 674 e = enc.Encode(req) 675 676 return buf.String(), e 677 } 678 679 func getVTrackRequestData(wi bool, wic bool) (db []byte, e error) { 680 data := &bytes.Buffer{} 681 enc := json.NewEncoder(data) 682 enc.SetEscapeHTML(false) 683 684 if wi && wic { 685 e = enc.Encode(vastXmlWithImpressionWithContent) 686 return data.Bytes(), e 687 } else if wi { 688 e = enc.Encode(vastXmlWithImpressionWithoutContent) 689 } else { 690 enc.Encode(vastXmlWithoutImpression) 691 } 692 693 return data.Bytes(), e 694 } 695 696 func TestGetIntegrationType(t *testing.T) { 697 testCases := []struct { 698 description string 699 givenHttpRequest *http.Request 700 expectedIntegrationType string 701 expectedError error 702 }{ 703 { 704 description: "Integration type in http request is valid, expect same integration time and no errors", 705 givenHttpRequest: httptest.NewRequest("GET", "/event?t=win&b=bidId&f=b&ts=1000&x=1&a=accountId&bidder=bidder&int=TestIntegrationType", strings.NewReader("")), 706 expectedIntegrationType: "TestIntegrationType", 707 expectedError: nil, 708 }, 709 { 710 description: "Integration type in http request is too long, expect too long error", 711 givenHttpRequest: httptest.NewRequest("GET", "/event?t=win&b=bidId&f=b&ts=1000&x=1&a=accountId&bidder=bidder&int=TestIntegrationTypeTooLongTestIntegrationTypeTooLongTestIntegrationType", strings.NewReader("")), 712 expectedError: errors.New("integration type length is too long"), 713 }, 714 { 715 description: "Integration type in http request contains invalid character, expect invalid character error", 716 givenHttpRequest: httptest.NewRequest("GET", "/event?t=win&b=bidId&f=b&ts=1000&x=1&a=accountId&bidder=bidder&int=Te$tIntegrationType", strings.NewReader("")), 717 expectedError: errors.New("integration type can only contain numbers, letters and these characters '-', '_'"), 718 }, 719 } 720 721 for _, test := range testCases { 722 integrationType, err := getIntegrationType(test.givenHttpRequest) 723 if test.expectedError != nil { 724 assert.Equal(t, test.expectedError, err, test.description) 725 } else { 726 assert.Empty(t, err, test.description) 727 assert.Equalf(t, test.expectedIntegrationType, integrationType, test.description) 728 } 729 } 730 }