Skip to content

Commit d3abf2f

Browse files
committed
test: add comprehensive unit tests for secure token parsing
Add unit tests covering: - Standard SDK keys without secure tokens - Secure token format (sdkKey:apiKey) parsing - Edge cases: multiple colons, empty parts, empty headers - Integration test with notification event stream Ensures secure token parsing logic has proper test coverage.
1 parent e99eb47 commit d3abf2f

File tree

1 file changed

+121
-0
lines changed

1 file changed

+121
-0
lines changed

pkg/handlers/notification_test.go

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -503,3 +503,124 @@ func getMockNotificationReceiver(conf config.SyncConfig, returnError bool, msg .
503503
return dataChan, nil
504504
}
505505
}
506+
507+
func (suite *NotificationTestSuite) TestSecureTokenParsing() {
508+
conf := config.NewDefaultConfig()
509+
510+
testCases := []struct {
511+
name string
512+
sdkKeyHeader string
513+
expectedSDKKey string
514+
description string
515+
}{
516+
{
517+
name: "StandardSDKKey",
518+
sdkKeyHeader: "normal_sdk_key_123",
519+
expectedSDKKey: "normal_sdk_key_123",
520+
description: "Standard SDK key without secure token should remain unchanged",
521+
},
522+
{
523+
name: "SecureTokenFormat",
524+
sdkKeyHeader: "sdk_key_123:api_key_456",
525+
expectedSDKKey: "sdk_key_123",
526+
description: "SDK key with secure token should extract only the SDK key portion",
527+
},
528+
{
529+
name: "MultipleColons",
530+
sdkKeyHeader: "sdk_key:api_key:extra_part",
531+
expectedSDKKey: "sdk_key",
532+
description: "Multiple colons should split at first colon only",
533+
},
534+
{
535+
name: "EmptySDKKey",
536+
sdkKeyHeader: ":api_key_456",
537+
expectedSDKKey: "",
538+
description: "Empty SDK key portion should result in empty string",
539+
},
540+
{
541+
name: "EmptyAPIKey",
542+
sdkKeyHeader: "sdk_key_123:",
543+
expectedSDKKey: "sdk_key_123",
544+
description: "Empty API key portion should extract SDK key",
545+
},
546+
{
547+
name: "ColonOnly",
548+
sdkKeyHeader: ":",
549+
expectedSDKKey: "",
550+
description: "Colon only should result in empty SDK key",
551+
},
552+
{
553+
name: "EmptyHeader",
554+
sdkKeyHeader: "",
555+
expectedSDKKey: "",
556+
description: "Empty header should remain empty",
557+
},
558+
}
559+
560+
for _, tc := range testCases {
561+
suite.Run(tc.name, func() {
562+
// Create a mock notification receiver that captures the SDK key
563+
var capturedSDKKey string
564+
mockReceiver := func(ctx context.Context) (<-chan syncer.Event, error) {
565+
capturedSDKKey = ctx.Value(SDKKey).(string)
566+
dataChan := make(chan syncer.Event)
567+
close(dataChan) // Close immediately as we don't need events
568+
return dataChan, nil
569+
}
570+
571+
// Setup handler
572+
suite.mux.Get("/test-notifications", NotificationEventStreamHandler(mockReceiver))
573+
574+
// Create request with SDK key header
575+
req := httptest.NewRequest("GET", "/test-notifications", nil)
576+
if tc.sdkKeyHeader != "" {
577+
req.Header.Set(middleware.OptlySDKHeader, tc.sdkKeyHeader)
578+
}
579+
rec := httptest.NewRecorder()
580+
581+
// Execute request
582+
suite.mux.ServeHTTP(rec, req)
583+
584+
// Verify SDK key was parsed correctly
585+
suite.Equal(tc.expectedSDKKey, capturedSDKKey, tc.description)
586+
})
587+
}
588+
}
589+
590+
func (suite *NotificationTestSuite) TestSecureTokenParsingIntegration() {
591+
// Test that secure token parsing works end-to-end with actual notification flow
592+
conf := config.NewDefaultConfig()
593+
594+
// Test with secure token format
595+
req := httptest.NewRequest("GET", "/notifications/event-stream", nil)
596+
req.Header.Set(middleware.OptlySDKHeader, "test_sdk_key:test_api_key")
597+
rec := httptest.NewRecorder()
598+
599+
// Create a mock receiver that verifies the SDK key context
600+
mockReceiver := func(ctx context.Context) (<-chan syncer.Event, error) {
601+
sdkKey := ctx.Value(SDKKey).(string)
602+
suite.Equal("test_sdk_key", sdkKey, "SDK key should be extracted from secure token format")
603+
604+
dataChan := make(chan syncer.Event, 1)
605+
// Send a test event
606+
dataChan <- syncer.Event{
607+
Type: notification.Decision,
608+
Message: map[string]string{"test": "event"},
609+
}
610+
close(dataChan)
611+
return dataChan, nil
612+
}
613+
614+
suite.mux.Get("/test-secure-notifications", NotificationEventStreamHandler(mockReceiver))
615+
616+
// Create cancelable context for SSE
617+
ctx, cancel := context.WithTimeout(req.Context(), 1*time.Second)
618+
defer cancel()
619+
620+
suite.mux.ServeHTTP(rec, req.WithContext(ctx))
621+
622+
// Verify response
623+
suite.Equal(http.StatusOK, rec.Code)
624+
response := rec.Body.String()
625+
suite.Contains(response, `data: {"test":"event"}`, "Should receive the test event")
626+
}

0 commit comments

Comments
 (0)