|
1 | 1 | package provider
|
2 | 2 |
|
3 | 3 | import (
|
| 4 | + "fmt" |
4 | 5 | "net/http"
|
5 | 6 | "net/http/httptest"
|
| 7 | + "regexp" |
| 8 | + "strings" |
6 | 9 | "testing"
|
7 | 10 |
|
8 | 11 | "github.com/hashicorp/terraform-plugin-testing/helper/resource"
|
@@ -240,3 +243,240 @@ func TestAccTrackingPlanResource(t *testing.T) {
|
240 | 243 | },
|
241 | 244 | })
|
242 | 245 | }
|
| 246 | + |
| 247 | +func TestAccTrackingPlanResource_ErrorHandling(t *testing.T) { |
| 248 | + t.Parallel() |
| 249 | + |
| 250 | + t.Run("handles invalid JSON schema", func(t *testing.T) { |
| 251 | + t.Parallel() |
| 252 | + |
| 253 | + fakeServer := httptest.NewServer( |
| 254 | + http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { |
| 255 | + w.Header().Set("content-type", "application/json") |
| 256 | + if req.URL.Path == "/tracking-plans" { |
| 257 | + _, _ = w.Write([]byte(` |
| 258 | + { |
| 259 | + "data": { |
| 260 | + "trackingPlan": { |
| 261 | + "id": "test-id", |
| 262 | + "name": "Test Plan", |
| 263 | + "type": "LIVE" |
| 264 | + } |
| 265 | + } |
| 266 | + }`)) |
| 267 | + } else if req.Method == http.MethodDelete { |
| 268 | + _, _ = w.Write([]byte(`{"data": {}}`)) |
| 269 | + } else { |
| 270 | + w.WriteHeader(http.StatusBadRequest) |
| 271 | + _, _ = w.Write([]byte(`{"error": "Invalid JSON schema"}`)) |
| 272 | + } |
| 273 | + }), |
| 274 | + ) |
| 275 | + defer fakeServer.Close() |
| 276 | + |
| 277 | + providerConfig := ` |
| 278 | + provider "segment" { |
| 279 | + url = "` + fakeServer.URL + `" |
| 280 | + token = "abc123" |
| 281 | + } |
| 282 | + ` |
| 283 | + |
| 284 | + resource.Test(t, resource.TestCase{ |
| 285 | + ProtoV6ProviderFactories: testAccProtoV6ProviderFactories, |
| 286 | + Steps: []resource.TestStep{ |
| 287 | + { |
| 288 | + Config: providerConfig + ` |
| 289 | + resource "segment_tracking_plan" "test" { |
| 290 | + name = "Test Tracking Plan" |
| 291 | + type = "LIVE" |
| 292 | + rules = [ |
| 293 | + { |
| 294 | + key = "Test Rule" |
| 295 | + type = "TRACK" |
| 296 | + version = 1 |
| 297 | + json_schema = jsonencode({"invalid": "schema"}) |
| 298 | + } |
| 299 | + ] |
| 300 | + } |
| 301 | + `, |
| 302 | + ExpectError: regexp.MustCompile("Unable to create Tracking Plan rules"), |
| 303 | + }, |
| 304 | + }, |
| 305 | + }) |
| 306 | + }) |
| 307 | +} |
| 308 | + |
| 309 | +func TestAccTrackingPlanResource_PaginationHandling(t *testing.T) { |
| 310 | + t.Parallel() |
| 311 | + |
| 312 | + ruleRequestCount := 0 |
| 313 | + fakeServer := httptest.NewServer( |
| 314 | + http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { |
| 315 | + w.Header().Set("content-type", "application/json") |
| 316 | + |
| 317 | + if req.URL.Path == "/tracking-plans" { |
| 318 | + _, _ = w.Write([]byte(` |
| 319 | + { |
| 320 | + "data": { |
| 321 | + "trackingPlan": { |
| 322 | + "id": "test-tracking-plan-id", |
| 323 | + "name": "Test Tracking Plan", |
| 324 | + "type": "LIVE", |
| 325 | + "createdAt": "2021-11-16T00:06:19.000Z", |
| 326 | + "updatedAt": "2021-11-16T00:06:19.000Z" |
| 327 | + } |
| 328 | + } |
| 329 | + }`)) |
| 330 | + } else if req.URL.Path == "/tracking-plans/test-tracking-plan-id" { |
| 331 | + _, _ = w.Write([]byte(` |
| 332 | + { |
| 333 | + "data": { |
| 334 | + "trackingPlan": { |
| 335 | + "id": "test-tracking-plan-id", |
| 336 | + "name": "Test Tracking Plan", |
| 337 | + "type": "LIVE", |
| 338 | + "createdAt": "2021-11-16T00:06:19.000Z", |
| 339 | + "updatedAt": "2021-11-16T00:06:19.000Z" |
| 340 | + } |
| 341 | + } |
| 342 | + }`)) |
| 343 | + } else if req.URL.Path == "/tracking-plans/test-tracking-plan-id/rules" { |
| 344 | + ruleRequestCount++ |
| 345 | + |
| 346 | + // Simulate pagination - first page returns cursor, second page returns empty |
| 347 | + if ruleRequestCount == 1 { |
| 348 | + _, _ = w.Write([]byte(` |
| 349 | + { |
| 350 | + "data": { |
| 351 | + "rules": [ |
| 352 | + { |
| 353 | + "key": "Rule 1", |
| 354 | + "type": "TRACK", |
| 355 | + "version": 1, |
| 356 | + "jsonSchema": {"properties": {}}, |
| 357 | + "createdAt": "2023-09-08T19:02:55.000Z", |
| 358 | + "updatedAt": "2023-09-08T19:02:55.000Z" |
| 359 | + } |
| 360 | + ], |
| 361 | + "pagination": { |
| 362 | + "current": "MA==", |
| 363 | + "next": "Mg==", |
| 364 | + "totalEntries": 2 |
| 365 | + } |
| 366 | + } |
| 367 | + }`)) |
| 368 | + } else { |
| 369 | + _, _ = w.Write([]byte(` |
| 370 | + { |
| 371 | + "data": { |
| 372 | + "rules": [ |
| 373 | + { |
| 374 | + "key": "Rule 2", |
| 375 | + "type": "IDENTIFY", |
| 376 | + "version": 1, |
| 377 | + "jsonSchema": {"properties": {}}, |
| 378 | + "createdAt": "2023-09-08T19:02:55.000Z", |
| 379 | + "updatedAt": "2023-09-08T19:02:55.000Z" |
| 380 | + } |
| 381 | + ], |
| 382 | + "pagination": { |
| 383 | + "current": "Mg==", |
| 384 | + "totalEntries": 2 |
| 385 | + } |
| 386 | + } |
| 387 | + }`)) |
| 388 | + } |
| 389 | + |
| 390 | + if req.Method == http.MethodPost { |
| 391 | + // Handle rule replacement |
| 392 | + _, _ = w.Write([]byte(`{"data": {}}`)) |
| 393 | + } |
| 394 | + } else { |
| 395 | + _, _ = w.Write([]byte(`{"data": {}}`)) |
| 396 | + } |
| 397 | + }), |
| 398 | + ) |
| 399 | + defer fakeServer.Close() |
| 400 | + |
| 401 | + providerConfig := ` |
| 402 | + provider "segment" { |
| 403 | + url = "` + fakeServer.URL + `" |
| 404 | + token = "abc123" |
| 405 | + } |
| 406 | + ` |
| 407 | + |
| 408 | + resource.Test(t, resource.TestCase{ |
| 409 | + ProtoV6ProviderFactories: testAccProtoV6ProviderFactories, |
| 410 | + Steps: []resource.TestStep{ |
| 411 | + { |
| 412 | + Config: providerConfig + ` |
| 413 | + resource "segment_tracking_plan" "test" { |
| 414 | + name = "Test Tracking Plan" |
| 415 | + type = "LIVE" |
| 416 | + rules = [ |
| 417 | + { |
| 418 | + key = "Test Rule" |
| 419 | + type = "TRACK" |
| 420 | + version = 1 |
| 421 | + json_schema = jsonencode({}) |
| 422 | + } |
| 423 | + ] |
| 424 | + } |
| 425 | + `, |
| 426 | + Check: resource.ComposeAggregateTestCheckFunc( |
| 427 | + resource.TestCheckResourceAttr("segment_tracking_plan.test", "id", "test-tracking-plan-id"), |
| 428 | + resource.TestCheckResourceAttr("segment_tracking_plan.test", "name", "Test Tracking Plan"), |
| 429 | + ), |
| 430 | + }, |
| 431 | + }, |
| 432 | + }) |
| 433 | +} |
| 434 | + |
| 435 | +func TestAccTrackingPlanResource_MaxRulesValidation(t *testing.T) { |
| 436 | + t.Parallel() |
| 437 | + |
| 438 | + fakeServer := httptest.NewServer( |
| 439 | + http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { |
| 440 | + w.Header().Set("content-type", "application/json") |
| 441 | + _, _ = w.Write([]byte(`{"data": {}}`)) |
| 442 | + }), |
| 443 | + ) |
| 444 | + defer fakeServer.Close() |
| 445 | + |
| 446 | + providerConfig := ` |
| 447 | + provider "segment" { |
| 448 | + url = "` + fakeServer.URL + `" |
| 449 | + token = "abc123" |
| 450 | + } |
| 451 | + ` |
| 452 | + |
| 453 | + // Generate more than MAX_RULES (2000) rules to test validation |
| 454 | + var rulesConfig strings.Builder |
| 455 | + rulesConfig.WriteString("rules = [\n") |
| 456 | + for i := 0; i < 2001; i++ { |
| 457 | + rulesConfig.WriteString(fmt.Sprintf(` |
| 458 | + { |
| 459 | + key = "Rule %d" |
| 460 | + type = "TRACK" |
| 461 | + version = 1 |
| 462 | + json_schema = jsonencode({}) |
| 463 | + },`, i)) |
| 464 | + } |
| 465 | + rulesConfig.WriteString("\n]") |
| 466 | + |
| 467 | + resource.Test(t, resource.TestCase{ |
| 468 | + ProtoV6ProviderFactories: testAccProtoV6ProviderFactories, |
| 469 | + Steps: []resource.TestStep{ |
| 470 | + { |
| 471 | + Config: providerConfig + ` |
| 472 | + resource "segment_tracking_plan" "test" { |
| 473 | + name = "Test Tracking Plan" |
| 474 | + type = "LIVE" |
| 475 | + ` + rulesConfig.String() + ` |
| 476 | + } |
| 477 | + `, |
| 478 | + ExpectError: regexp.MustCompile("Attribute rules set must contain at most 2000 elements"), |
| 479 | + }, |
| 480 | + }, |
| 481 | + }) |
| 482 | +} |
0 commit comments