package auth import ( "bytes" "log/slog" "os" "reflect" "strings" "testing" ) func TestInitializeAuthConfig(t *testing.T) { // Setup test environment variables testEnv := map[string]string{ "AWS_REGION": "us-east-2", "COGNITO_USER_POOL_ID": "us-east-2_testpool", "COGNITO_CLIENT_ID": "test-client-id", "COGNITO_CLIENT_SECRET": "test-client-secret", "COGNITO_DOMAIN": "test-domain.auth.us-east-2.amazoncognito.com", "COGNITO_LOGIN_PATH": "/custom-login", "COGNITO_CALLBACK_PATH": "/custom-callback", "COGNITO_HOME_PATH": "/custom-home", "COGNITO_LOGOUT_PATH": "/custom-logout", "DEBUG": "true", } // Set environment variables for k, v := range testEnv { t.Setenv(k, v) } defer func() { // Cleanup environment variables after test for k := range testEnv { os.Unsetenv(k) } }() // Create test logger logHandler := slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{ Level: slog.LevelDebug, }) testLogger := slog.New(logHandler) // Test base URL baseURL := "https://example.com" // Create config instance cfg := &CognitoConfig{} err := cfg.InitializeAuthConfig(baseURL, testLogger) // Test initialization success if err != nil { t.Errorf("InitializeAuthConfig failed: %v", err) } // Test all fields tests := []struct { name string got string expected string }{ {"AuthRegion", cfg.AuthRegion, "us-east-2"}, {"AuthUserPoolID", cfg.AuthUserPoolID, "us-east-2_testpool"}, {"AuthClientID", cfg.AuthClientID, "test-client-id"}, {"AuthClientSecret", cfg.AuthClientSecret, "test-client-secret"}, {"AuthDomain", cfg.AuthDomain, "test-domain.auth.us-east-2.amazoncognito.com"}, {"AuthLoginPath", cfg.AuthLoginPath, "/custom-login"}, {"AuthCallbackPath", cfg.AuthCallbackPath, "/custom-callback"}, {"AuthHomePath", cfg.AuthHomePath, "/custom-home"}, {"AuthLogoutPath", cfg.AuthLogoutPath, "/custom-logout"}, {"AuthRedirectURI", cfg.AuthRedirectURI, "https://example.com/custom-callback"}, {"AuthTokenURL", cfg.AuthTokenURL, "test-domain.auth.us-east-2.amazoncognito.com/oauth2/token"}, {"AuthURL", cfg.AuthURL, "test-domain.auth.us-east-2.amazoncognito.com/oauth2/authorize"}, {"AuthJwksURL", cfg.AuthJwksURL, "https://cognito-idp.us-east-2.amazonaws.com/us-east-2_testpool/.well-known/jwks.json"}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if tt.got != tt.expected { t.Errorf("%s = %v, want %v", tt.name, tt.got, tt.expected) } }) } // Test logger if cfg.AuthLogger == nil { t.Error("AuthLogger is nil") } // Test route permissions map initialization if cfg.AuthRoutePermissions == nil { t.Error("AuthRoutePermissions map was not initialized") } } func TestInitializeAuthConfigWithDefaults(t *testing.T) { // Clear any existing environment variables envVars := []string{ "AWS_REGION", "COGNITO_LOGIN_PATH", "COGNITO_CALLBACK_PATH", "COGNITO_HOME_PATH", "COGNITO_LOGOUT_PATH", } for _, env := range envVars { os.Unsetenv(env) } // Set required variables t.Setenv("COGNITO_USER_POOL_ID", "us-east-2_testpool") t.Setenv("COGNITO_CLIENT_ID", "test-client-id") t.Setenv("COGNITO_CLIENT_SECRET", "test-client-secret") t.Setenv("COGNITO_DOMAIN", "test-domain.auth.us-east-2.amazoncognito.com") defer func() { for _, env := range append(envVars, "COGNITO_USER_POOL_ID", "COGNITO_CLIENT_ID", "COGNITO_CLIENT_SECRET", "COGNITO_DOMAIN") { os.Unsetenv(env) } }() cfg := &CognitoConfig{} err := cfg.InitializeAuthConfig("https://example.com", nil) if err != nil { t.Errorf("InitializeAuthConfig failed: %v", err) } // Test default values defaults := []struct { name string got string expected string }{ {"AuthRegion", cfg.AuthRegion, "us-east-2"}, {"AuthLoginPath", cfg.AuthLoginPath, "/login"}, {"AuthCallbackPath", cfg.AuthCallbackPath, "/login-callback"}, {"AuthHomePath", cfg.AuthHomePath, "/home"}, {"AuthLogoutPath", cfg.AuthLogoutPath, "/logout"}, } for _, tt := range defaults { t.Run(tt.name, func(t *testing.T) { if tt.got != tt.expected { t.Errorf("%s = %v, want %v", tt.name, tt.got, tt.expected) } }) } } func TestGettersAndSetters(t *testing.T) { // Create a test instance cfg := &CognitoConfig{} // Test logger logHandler := slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{ Level: slog.LevelDebug, }) testLogger := slog.New(logHandler) // Test route permissions testPermissions := map[string][]string{ "/api/test": {"read", "write"}, "/api/admin": {"admin"}, } // Test cases for all getter/setter pairs testCases := []struct { name string setter func() getter func() interface{} expected interface{} }{ { name: "AuthRegion", setter: func() { cfg.SetAuthRegion("us-west-2") }, getter: func() interface{} { return cfg.GetAuthRegion() }, expected: "us-west-2", }, { name: "AuthUserPoolID", setter: func() { cfg.SetAuthUserPoolID("us-west-2_testpool") }, getter: func() interface{} { return cfg.GetAuthUserPoolID() }, expected: "us-west-2_testpool", }, { name: "AuthClientSecret", setter: func() { cfg.SetAuthClientSecret("test-secret") }, getter: func() interface{} { return cfg.GetAuthClientSecret() }, expected: "test-secret", }, { name: "AuthDomain", setter: func() { cfg.SetAuthDomain("test-domain.com") }, getter: func() interface{} { return cfg.GetAuthDomain() }, expected: "test-domain.com", }, { name: "AuthClientID", setter: func() { cfg.SetAuthClientID("test-client-id") }, getter: func() interface{} { return cfg.GetAuthClientID() }, expected: "test-client-id", }, { name: "AuthRedirectURI", setter: func() { cfg.SetAuthRedirectURI("https://example.com/callback") }, getter: func() interface{} { return cfg.GetAuthRedirectURI() }, expected: "https://example.com/callback", }, { name: "AuthTokenURL", setter: func() { cfg.SetAuthTokenURL("https://example.com/token") }, getter: func() interface{} { return cfg.GetAuthTokenURL() }, expected: "https://example.com/token", }, { name: "AuthJwksURL", setter: func() { cfg.SetAuthJwksURL("https://example.com/jwks.json") }, getter: func() interface{} { return cfg.GetAuthJwksURL() }, expected: "https://example.com/jwks.json", }, { name: "AuthURL", setter: func() { cfg.SetAuthURL("https://example.com/auth") }, getter: func() interface{} { return cfg.GetAuthURL() }, expected: "https://example.com/auth", }, { name: "AuthLoginPath", setter: func() { cfg.SetAuthLoginPath("/custom-login") }, getter: func() interface{} { return cfg.GetAuthLoginPath() }, expected: "/custom-login", }, { name: "AuthCallbackPath", setter: func() { cfg.SetAuthCallbackPath("/custom-callback") }, getter: func() interface{} { return cfg.GetAuthCallbackPath() }, expected: "/custom-callback", }, { name: "AuthHomePath", setter: func() { cfg.SetAuthHomePath("/custom-home") }, getter: func() interface{} { return cfg.GetAuthHomePath() }, expected: "/custom-home", }, { name: "AuthLogoutPath", setter: func() { cfg.SetAuthLogoutPath("/custom-logout") }, getter: func() interface{} { return cfg.GetAuthLogoutPath() }, expected: "/custom-logout", }, { name: "AuthLogger", setter: func() { cfg.SetAuthLogger(testLogger) }, getter: func() interface{} { return cfg.GetAuthLogger() }, expected: testLogger, }, { name: "AuthRoutePermissions", setter: func() { cfg.SetAuthRoutePermissions(testPermissions) }, getter: func() interface{} { return cfg.GetAuthRoutePermissions() }, expected: testPermissions, }, } // Run all test cases for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { // Execute setter tc.setter() // Get value and compare with expected got := tc.getter() // Handle different types of comparisons switch expected := tc.expected.(type) { case map[string][]string: gotMap, ok := got.(map[string][]string) if !ok { t.Errorf("failed to convert to map[string][]string: got type %T", got) return } if !reflect.DeepEqual(gotMap, expected) { t.Errorf("got %v, want %v", gotMap, expected) } case *slog.Logger: gotLogger, ok := got.(*slog.Logger) if !ok { t.Errorf("failed to convert to *slog.Logger: got type %T", got) return } if gotLogger != expected { t.Errorf("got %v, want %v", gotLogger, expected) } default: if got != tc.expected { t.Errorf("got %v, want %v", got, tc.expected) } } }) } } func TestPrettyPrintDebugOnly(t *testing.T) { // Test with DEBUG=true t.Setenv("DEBUG", "true") defer os.Unsetenv("DEBUG") cfg := &CognitoConfig{ AuthClientID: "test-client-id", AuthClientSecret: "test-secret", AuthRedirectURI: "https://example.com/callback", AuthRoutePermissions: map[string][]string{ "/test": {"read"}, }, } // Create a buffer to capture log output var buf bytes.Buffer // Create a logger that writes to our buffer logHandler := slog.NewTextHandler(&buf, &slog.HandlerOptions{ Level: slog.LevelDebug, }) testLogger := slog.New(logHandler) // Set the logger in the config cfg.SetAuthLogger(testLogger) // Call the method cfg.PrettyPrintDebugOnly() // Get the output output := buf.String() // Verify output contains expected values - adjust these to match actual format expectedStrings := []string{ "level=DEBUG", "msg=\"CognitoConfig details\"", "AuthClientID=test-client-id", "AuthClientSecret=test-secret", "AuthRedirectURI=https://example.com/callback", } for _, expected := range expectedStrings { if !strings.Contains(output, expected) { t.Errorf("Expected output to contain %q", expected) } } // Verify route permissions are included if !strings.Contains(output, "/test") || !strings.Contains(output, "read") { t.Errorf("Expected output to contain route permissions for /test") } // Test with DEBUG=false t.Setenv("DEBUG", "false") buf.Reset() cfg.PrettyPrintDebugOnly() }