github.com/LukasHeimann/cloudfoundrycli/v8@v8.4.4/command/translatableerror/convert_to_translatable_error_test.go (about)

     1  package translatableerror_test
     2  
     3  import (
     4  	"encoding/json"
     5  	"errors"
     6  	"time"
     7  
     8  	"github.com/LukasHeimann/cloudfoundrycli/v8/actor/actionerror"
     9  	"github.com/LukasHeimann/cloudfoundrycli/v8/api/cloudcontroller/ccerror"
    10  	"github.com/LukasHeimann/cloudfoundrycli/v8/api/plugin/pluginerror"
    11  	"github.com/LukasHeimann/cloudfoundrycli/v8/api/uaa"
    12  	. "github.com/LukasHeimann/cloudfoundrycli/v8/command/translatableerror"
    13  	"github.com/LukasHeimann/cloudfoundrycli/v8/util/clissh/ssherror"
    14  	"github.com/LukasHeimann/cloudfoundrycli/v8/util/download"
    15  	"github.com/LukasHeimann/cloudfoundrycli/v8/util/manifest"
    16  	. "github.com/onsi/ginkgo"
    17  	. "github.com/onsi/ginkgo/extensions/table"
    18  	. "github.com/onsi/gomega"
    19  )
    20  
    21  var _ = Describe("ConvertToTranslatableError", func() {
    22  	err := errors.New("some-error")
    23  	genericErr := errors.New("some-generic-error")
    24  	jsonErr := new(json.SyntaxError)
    25  	unprocessableEntityError := ccerror.UnprocessableEntityError{Message: "another message"}
    26  
    27  	DescribeTable("error translations",
    28  		func(passedInErr error, expectedErr error) {
    29  			actualErr := ConvertToTranslatableError(passedInErr)
    30  			Expect(actualErr).To(MatchError(expectedErr))
    31  		},
    32  
    33  		// Action Errors
    34  		Entry("actionerror.AddPluginRepositoryError -> AddPluginRepositoryError",
    35  			actionerror.AddPluginRepositoryError{Name: "some-repo", URL: "some-URL", Message: "404"},
    36  			AddPluginRepositoryError{Name: "some-repo", URL: "some-URL", Message: "404"}),
    37  
    38  		Entry("actionerror.ApplicationNotFoundError -> ApplicationNotFoundError",
    39  			actionerror.ApplicationNotFoundError{Name: "some-app"},
    40  			ApplicationNotFoundError{Name: "some-app"}),
    41  
    42  		Entry("actionerror.ApplicationNotStartedError -> ApplicationNotStartedError",
    43  			actionerror.ApplicationNotStartedError{Name: "some-app"},
    44  			ApplicationNotStartedError{Name: "some-app"}),
    45  
    46  		Entry("actionerror.AppNotFoundInManifestError -> AppNotFoundInManifestError",
    47  			actionerror.AppNotFoundInManifestError{Name: "some-app"},
    48  			AppNotFoundInManifestError{Name: "some-app"}),
    49  
    50  		Entry("actionerror.AssignDropletError -> AssignDropletError",
    51  			actionerror.AssignDropletError{Message: "some-message"},
    52  			AssignDropletError{Message: "some-message"}),
    53  
    54  		Entry("actionerror.ServicePlanNotFoundError -> ServicePlanNotFoundError",
    55  			actionerror.ServicePlanNotFoundError{PlanName: "some-plan", OfferingName: "some-service"},
    56  			ServicePlanNotFoundError{PlanName: "some-plan", OfferingName: "some-service"}),
    57  
    58  		Entry("actionerror.BuildpackNotFoundError -> BuildpackNotFoundError",
    59  			actionerror.BuildpackNotFoundError{},
    60  			BuildpackNotFoundError{}),
    61  
    62  		Entry("actionerror.BuildpackStackChangeError-> BuildpackStackChangeError",
    63  			actionerror.BuildpackStackChangeError{},
    64  			BuildpackStackChangeError{}),
    65  
    66  		Entry("actionerror.CommandLineOptionsWithMultipleAppsError -> CommandLineArgsWithMultipleAppsError",
    67  			actionerror.CommandLineOptionsWithMultipleAppsError{},
    68  			CommandLineArgsWithMultipleAppsError{}),
    69  
    70  		Entry("actionerror.DockerPasswordNotSetError -> DockerPasswordNotSetError",
    71  			actionerror.DockerPasswordNotSetError{},
    72  			DockerPasswordNotSetError{}),
    73  
    74  		Entry("actionerror.DomainNotFoundError -> DomainNotFoundError",
    75  			actionerror.DomainNotFoundError{Name: "some-domain-name", GUID: "some-domain-guid"},
    76  			DomainNotFoundError{Name: "some-domain-name", GUID: "some-domain-guid"}),
    77  
    78  		Entry("actionerror.EmptyBuildpacksError -> EmptyBuildpacksError",
    79  			manifest.EmptyBuildpacksError{},
    80  			EmptyBuildpacksError{},
    81  		),
    82  
    83  		Entry("actionerror.EmptyArchiveError -> EmptyDirectoryError",
    84  			actionerror.EmptyArchiveError{Path: "some-filename"},
    85  			EmptyDirectoryError{Path: "some-filename"}),
    86  
    87  		Entry("actionerror.EmptyDirectoryError -> EmptyDirectoryError",
    88  			actionerror.EmptyDirectoryError{Path: "some-filename"},
    89  			EmptyDirectoryError{Path: "some-filename"}),
    90  
    91  		Entry("actionerror.EmptyBuildpackDirectoryError -> EmptyBuildpackDirectoryError",
    92  			actionerror.EmptyBuildpackDirectoryError{Path: "some-path"},
    93  			EmptyBuildpackDirectoryError{Path: "some-path"}),
    94  
    95  		Entry("actionerror.FileChangedError -> FileChangedError",
    96  			actionerror.FileChangedError{Filename: "some-filename"},
    97  			FileChangedError{Filename: "some-filename"}),
    98  
    99  		Entry("actionerror.GettingPluginRepositoryError -> GettingPluginRepositoryError",
   100  			actionerror.GettingPluginRepositoryError{Name: "some-repo", Message: "404"},
   101  			GettingPluginRepositoryError{Name: "some-repo", Message: "404"}),
   102  
   103  		Entry("actionerror.HostnameWithTCPDomainError -> HostnameWithTCPDomainError",
   104  			actionerror.HostnameWithTCPDomainError{},
   105  			HostnameWithTCPDomainError{}),
   106  
   107  		Entry("actionerror.HTTPHealthCheckInvalidError -> HTTPHealthCheckInvalidError",
   108  			actionerror.HTTPHealthCheckInvalidError{},
   109  			HTTPHealthCheckInvalidError{}),
   110  
   111  		Entry("actionerror.InvalidBuildpacksError -> InvalidBuildpacksError",
   112  			actionerror.InvalidBuildpacksError{},
   113  			InvalidBuildpacksError{}),
   114  
   115  		Entry("actionerror.InvalidHTTPRouteSettings -> PortNotAllowedWithHTTPDomainError",
   116  			actionerror.InvalidHTTPRouteSettings{Domain: "some-domain"},
   117  			PortNotAllowedWithHTTPDomainError{Domain: "some-domain"}),
   118  
   119  		Entry("actionerror.InvalidRouteError -> InvalidRouteError",
   120  			actionerror.InvalidRouteError{Route: "some-invalid-route"},
   121  			InvalidRouteError{Route: "some-invalid-route"}),
   122  
   123  		Entry("actionerror.InvalidTCPRouteSettings -> HostAndPathNotAllowedWithTCPDomainError",
   124  			actionerror.InvalidTCPRouteSettings{Domain: "some-domain"},
   125  			HostAndPathNotAllowedWithTCPDomainError{Domain: "some-domain"}),
   126  
   127  		Entry("actionerror.MissingNameError -> AppNameOrManifestRequiredError",
   128  			actionerror.MissingNameError{},
   129  			AppNameOrManifestRequiredError{}),
   130  
   131  		Entry("actionerror.MultipleBuildpacksFoundError -> MultipleBuildpacksFoundError",
   132  			actionerror.MultipleBuildpacksFoundError{BuildpackName: "some-bp-name"},
   133  			MultipleBuildpacksFoundError{BuildpackName: "some-bp-name"}),
   134  
   135  		Entry("actionerror.NoCompatibleBinaryError -> NoCompatibleBinaryError",
   136  			actionerror.NoCompatibleBinaryError{},
   137  			NoCompatibleBinaryError{}),
   138  
   139  		Entry("actionerror.NoDomainsFoundError -> NoDomainsFoundError",
   140  			actionerror.NoDomainsFoundError{OrganizationGUID: "some-guid"},
   141  			NoDomainsFoundError{}),
   142  
   143  		Entry("actionerror.NoHostnameAndSharedDomainError -> NoHostnameAndSharedDomainError",
   144  			actionerror.NoHostnameAndSharedDomainError{},
   145  			NoHostnameAndSharedDomainError{}),
   146  
   147  		Entry("actionerror.NoMatchingDomainError -> NoMatchingDomainError",
   148  			actionerror.NoMatchingDomainError{Route: "some-route.com"},
   149  			NoMatchingDomainError{Route: "some-route.com"}),
   150  
   151  		Entry("actionerror.NonexistentAppPathError -> FileNotFoundError",
   152  			actionerror.NonexistentAppPathError{Path: "some-path"},
   153  			FileNotFoundError{Path: "some-path"}),
   154  
   155  		Entry("actionerror.NoOrganizationTargetedError -> NoOrganizationTargetedError",
   156  			actionerror.NoOrganizationTargetedError{BinaryName: "faceman"},
   157  			NoOrganizationTargetedError{BinaryName: "faceman"}),
   158  
   159  		Entry("actionerror.NoSpaceTargetedError -> NoSpaceTargetedError",
   160  			actionerror.NoSpaceTargetedError{BinaryName: "faceman"},
   161  			NoSpaceTargetedError{BinaryName: "faceman"}),
   162  
   163  		Entry("actionerror.NotLoggedInError -> NotLoggedInError",
   164  			actionerror.NotLoggedInError{BinaryName: "faceman"},
   165  			NotLoggedInError{BinaryName: "faceman"}),
   166  
   167  		Entry("actionerror.OrganizationNotFoundError -> OrgNotFoundError",
   168  			actionerror.OrganizationNotFoundError{Name: "some-org"},
   169  			OrganizationNotFoundError{Name: "some-org"}),
   170  
   171  		Entry("actionerror.QuotaNotFoundForNameError -> QuotaNotFoundForNameError",
   172  			actionerror.QuotaNotFoundForNameError{Name: "some-quota"},
   173  			QuotaNotFoundForNameError{Name: "some-quota"}),
   174  
   175  		Entry("actionerror.PasswordGrantTypeLogoutRequiredError -> PasswordGrantTypeLogoutRequiredError",
   176  			actionerror.PasswordGrantTypeLogoutRequiredError{},
   177  			PasswordGrantTypeLogoutRequiredError{}),
   178  
   179  		Entry("actionerror.PluginCommandConflictError -> PluginCommandConflictError",
   180  			actionerror.PluginCommandsConflictError{
   181  				PluginName:     "some-plugin",
   182  				PluginVersion:  "1.1.1",
   183  				CommandNames:   []string{"some-command", "some-other-command"},
   184  				CommandAliases: []string{"sc", "soc"},
   185  			},
   186  			PluginCommandsConflictError{
   187  				PluginName:     "some-plugin",
   188  				PluginVersion:  "1.1.1",
   189  				CommandNames:   []string{"some-command", "some-other-command"},
   190  				CommandAliases: []string{"sc", "soc"},
   191  			}),
   192  
   193  		Entry("actionerror.PluginInvalidError -> PluginInvalidError",
   194  			actionerror.PluginInvalidError{},
   195  			PluginInvalidError{}),
   196  
   197  		Entry("actionerror.PluginInvalidError -> PluginInvalidError",
   198  			actionerror.PluginInvalidError{Err: genericErr},
   199  			PluginInvalidError{Err: genericErr}),
   200  
   201  		Entry("actionerror.PluginNotFoundError -> PluginNotFoundError",
   202  			actionerror.PluginNotFoundError{PluginName: "some-plugin"},
   203  			PluginNotFoundError{PluginName: "some-plugin"}),
   204  
   205  		Entry("actionerror.ProcessInstanceNotFoundError -> ProcessInstanceNotFoundError",
   206  			actionerror.ProcessInstanceNotFoundError{ProcessType: "some-process-type", InstanceIndex: 42},
   207  			ProcessInstanceNotFoundError{ProcessType: "some-process-type", InstanceIndex: 42}),
   208  
   209  		Entry("actionerror.ProcessInstanceNotRunningError -> ProcessInstanceNotRunningError",
   210  			actionerror.ProcessInstanceNotRunningError{ProcessType: "some-process-type", InstanceIndex: 42},
   211  			ProcessInstanceNotRunningError{ProcessType: "some-process-type", InstanceIndex: 42}),
   212  
   213  		Entry("actionerror.ProcessNotFoundError -> ProcessNotFoundError",
   214  			actionerror.ProcessNotFoundError{ProcessType: "some-process-type"},
   215  			ProcessNotFoundError{ProcessType: "some-process-type"}),
   216  
   217  		Entry("actionerror.PropertyCombinationError -> PropertyCombinationError",
   218  			actionerror.PropertyCombinationError{Properties: []string{"property-1", "property-2"}},
   219  			PropertyCombinationError{Properties: []string{"property-1", "property-2"}}),
   220  
   221  		Entry("actionerror.RepositoryNameTakenError -> RepositoryNameTakenError",
   222  			actionerror.RepositoryNameTakenError{Name: "some-repo"},
   223  			RepositoryNameTakenError{Name: "some-repo"}),
   224  
   225  		Entry("actionerror.RepositoryNotRegisteredError -> RepositoryNotRegisteredError",
   226  			actionerror.RepositoryNotRegisteredError{Name: "some-repo"},
   227  			RepositoryNotRegisteredError{Name: "some-repo"}),
   228  
   229  		Entry("actionerror.RevisionNotFoundErrors-> RevisionNotFoundError",
   230  			actionerror.RevisionNotFoundError{Version: 1},
   231  			RevisionNotFoundError{Version: 1}),
   232  
   233  		Entry("actionerror.RevisionAmbiguousError-> RevisionAmbiguousError",
   234  			actionerror.RevisionAmbiguousError{Version: 1},
   235  			RevisionAmbiguousError{Version: 1}),
   236  
   237  		Entry("actionerror.RouteInDifferentSpaceError -> RouteInDifferentSpaceError",
   238  			actionerror.RouteInDifferentSpaceError{Route: "some-route"},
   239  			RouteInDifferentSpaceError{Route: "some-route"}),
   240  
   241  		Entry("actionerror.RoutePathWithTCPDomainError -> RoutePathWithTCPDomainError",
   242  			actionerror.RoutePathWithTCPDomainError{},
   243  			RoutePathWithTCPDomainError{}),
   244  
   245  		Entry("actionerror.RouterGroupNotFoundError -> RouterGroupNotFoundError",
   246  			actionerror.RouterGroupNotFoundError{Name: "some-group"},
   247  			RouterGroupNotFoundError{Name: "some-group"},
   248  		),
   249  
   250  		Entry("actionerror.SecurityGroupNotFoundError -> SecurityGroupNotFoundError",
   251  			actionerror.SecurityGroupNotFoundError{Name: "some-security-group"},
   252  			SecurityGroupNotFoundError{Name: "some-security-group"}),
   253  
   254  		Entry("actionerror.ServiceInstanceNotFoundError -> ServiceInstanceNotFoundError",
   255  			actionerror.ServiceInstanceNotFoundError{Name: "some-service-instance"},
   256  			ServiceInstanceNotFoundError{Name: "some-service-instance"}),
   257  
   258  		Entry("actionerror.ServiceInstanceNotShareableError -> ServiceInstanceNotShareableError",
   259  			actionerror.ServiceInstanceNotShareableError{
   260  				FeatureFlagEnabled:          true,
   261  				ServiceBrokerSharingEnabled: false},
   262  			ServiceInstanceNotShareableError{
   263  				FeatureFlagEnabled:          true,
   264  				ServiceBrokerSharingEnabled: false}),
   265  
   266  		Entry("actionerror.SharedServiceInstanceNotFoundError -> SharedServiceInstanceNotFoundError",
   267  			actionerror.SharedServiceInstanceNotFoundError{},
   268  			SharedServiceInstanceNotFoundError{}),
   269  
   270  		Entry("actionerror.SpaceNotFoundError -> SpaceNotFoundError",
   271  			actionerror.SpaceNotFoundError{Name: "some-space"},
   272  			SpaceNotFoundError{Name: "some-space"}),
   273  
   274  		Entry("actionerror.StackNotFoundError -> StackNotFoundError",
   275  			actionerror.StackNotFoundError{Name: "some-stack-name", GUID: "some-stack-guid"},
   276  			StackNotFoundError{Name: "some-stack-name", GUID: "some-stack-guid"}),
   277  
   278  		Entry("actionerror.TaskWorkersUnavailableError -> RunTaskError",
   279  			actionerror.TaskWorkersUnavailableError{Message: "fooo: Banana Pants"},
   280  			RunTaskError{Message: "Task workers are unavailable."}),
   281  
   282  		Entry("actionerror.TCPRouteOptionsNotProvidedError-> TCPRouteOptionsNotProvidedError",
   283  			actionerror.TCPRouteOptionsNotProvidedError{},
   284  			TCPRouteOptionsNotProvidedError{}),
   285  
   286  		Entry("actionerror.TriggerLegacyPushError -> TriggerLegacyPushError",
   287  			actionerror.TriggerLegacyPushError{DomainHostRelated: []string{"domain", "host"}},
   288  			TriggerLegacyPushError{DomainHostRelated: []string{"domain", "host"}}),
   289  
   290  		Entry("actionerror.UploadFailedError -> UploadFailedError",
   291  			actionerror.UploadFailedError{Err: actionerror.NoDomainsFoundError{}},
   292  			UploadFailedError{Err: NoDomainsFoundError{}}),
   293  
   294  		Entry("v3action.StagingTimeoutError -> StagingTimeoutError",
   295  			actionerror.StagingTimeoutError{AppName: "some-app", Timeout: time.Nanosecond},
   296  			StagingTimeoutError{AppName: "some-app", Timeout: time.Nanosecond}),
   297  
   298  		Entry("actionerror.CommandLineOptionsAndManifestConflictError -> CommandLineOptionsAndManifestConflictError",
   299  			actionerror.CommandLineOptionsAndManifestConflictError{
   300  				ManifestAttribute:  "some-attribute",
   301  				CommandLineOptions: []string{"option-1", "option-2"},
   302  			},
   303  			CommandLineOptionsAndManifestConflictError{
   304  				ManifestAttribute:  "some-attribute",
   305  				CommandLineOptions: []string{"option-1", "option-2"},
   306  			}),
   307  
   308  		Entry("actionerror.ServiceInstanceNotSharedToSpaceError -> ServiceInstanceNotSharedToSpaceError",
   309  			actionerror.ServiceInstanceNotSharedToSpaceError{ServiceInstanceName: "some-service-instance-name"},
   310  			ServiceInstanceNotSharedToSpaceError{ServiceInstanceName: "some-service-instance-name"}),
   311  
   312  		Entry("TipDecoratorError calls translates error on base error",
   313  			TipDecoratorError{BaseError: ccerror.APINotFoundError{URL: "some-url"}},
   314  			TipDecoratorError{BaseError: APINotFoundError{URL: "some-url"}}),
   315  
   316  		// CC Errors
   317  		Entry("ccerror.APINotFoundError -> APINotFoundError",
   318  			ccerror.APINotFoundError{URL: "some-url"},
   319  			APINotFoundError{URL: "some-url"}),
   320  
   321  		Entry("ccerror.V2JobFailedError -> V2JobFailedError",
   322  			ccerror.V2JobFailedError{JobGUID: "some-job-guid", Message: "some-message"},
   323  			JobFailedError{JobGUID: "some-job-guid", Message: "some-message"}),
   324  
   325  		Entry("ccerror.V3JobFailedError -> V3JobFailedError",
   326  			ccerror.V3JobFailedError{JobGUID: "some-job-guid", Detail: "some-detail"},
   327  			JobFailedError{JobGUID: "some-job-guid", Message: "some-detail"}),
   328  
   329  		Entry("ccerror.JobTimeoutError -> JobTimeoutError",
   330  			ccerror.JobTimeoutError{JobGUID: "some-job-guid"},
   331  			JobTimeoutError{JobGUID: "some-job-guid"}),
   332  
   333  		Entry("ccerror.JobFailedNoErrorError -> JobFailedNoErrorError",
   334  			ccerror.JobFailedNoErrorError{JobGUID: "some-job-guid"},
   335  			JobFailedNoErrorError{JobGUID: "some-job-guid"}),
   336  
   337  		Entry("ccerror.MultiError -> MultiError",
   338  			ccerror.MultiError{ResponseCode: 418, Errors: []ccerror.V3Error{
   339  				{
   340  					Code:   282010,
   341  					Detail: "detail 1",
   342  					Title:  "title-1",
   343  				},
   344  				{
   345  					Code:   10242013,
   346  					Detail: "detail 2",
   347  					Title:  "title-2",
   348  				},
   349  			}},
   350  			MultiError{Messages: []string{"detail 1", "detail 2"}},
   351  		),
   352  
   353  		Entry("ccerror.RequestError -> APIRequestError",
   354  			ccerror.RequestError{Err: err},
   355  			APIRequestError{Err: err}),
   356  
   357  		Entry("ccerror.SSLValidationHostnameError -> SSLCertErrorError",
   358  			ccerror.SSLValidationHostnameError{Message: "some-message"},
   359  			SSLCertError{Message: "some-message"}),
   360  
   361  		Entry("ccerror.UnverifiedServerError -> InvalidSSLCertError",
   362  			ccerror.UnverifiedServerError{URL: "some-url"},
   363  			InvalidSSLCertError{URL: "some-url", SuggestedCommand: "api"}),
   364  
   365  		Entry("ccerror.UnprocessableEntityError with droplet message -> RunTaskError",
   366  			ccerror.UnprocessableEntityError{Message: "The request is semantically invalid: Task must have a droplet. Specify droplet or assign current droplet to app."},
   367  			RunTaskError{Message: "App is not staged."}),
   368  
   369  		// This changed in CF254
   370  		Entry("ccerror.UnprocessableEntityError with droplet message -> RunTaskError",
   371  			ccerror.UnprocessableEntityError{Message: "Task must have a droplet. Specify droplet or assign current droplet to app."},
   372  			RunTaskError{Message: "App is not staged."}),
   373  
   374  		Entry("ccerror.UnprocessableEntityError without droplet message -> original error",
   375  			unprocessableEntityError,
   376  			unprocessableEntityError),
   377  
   378  		Entry("download.RawHTTPStatusError -> HTTPStatusError",
   379  			download.RawHTTPStatusError{Status: "some status"},
   380  			HTTPStatusError{Status: "some status"},
   381  		),
   382  
   383  		Entry("json.SyntaxError -> JSONSyntaxError",
   384  			jsonErr,
   385  			JSONSyntaxError{Err: jsonErr},
   386  		),
   387  
   388  		// Manifest Errors
   389  		Entry("manifest.ManifestCreationError -> ManifestCreationError",
   390  			manifest.ManifestCreationError{Err: errors.New("some-error")},
   391  			FileCreationError{Err: errors.New("some-error")}),
   392  
   393  		Entry("manifest.InheritanceFieldError -> TriggerLegacyPushError",
   394  			manifest.InheritanceFieldError{},
   395  			TriggerLegacyPushError{InheritanceRelated: true}),
   396  
   397  		Entry("manifest.GlobalFieldError -> TriggerLegacyPushError",
   398  			manifest.GlobalFieldsError{Fields: []string{"some-field"}},
   399  			TriggerLegacyPushError{GlobalRelated: []string{"some-field"}}),
   400  
   401  		Entry("manifest.InterpolationError -> InterpolationError",
   402  			manifest.InterpolationError{Err: errors.New("an-error")},
   403  			InterpolationError{Err: errors.New("an-error")}),
   404  
   405  		// Plugin Errors
   406  		Entry("pluginerror.RawHTTPStatusError -> DownloadPluginHTTPError",
   407  			pluginerror.RawHTTPStatusError{Status: "some status"},
   408  			DownloadPluginHTTPError{Message: "some status"},
   409  		),
   410  		Entry("pluginerror.SSLValidationHostnameError -> DownloadPluginHTTPError",
   411  			pluginerror.SSLValidationHostnameError{Message: "some message"},
   412  			DownloadPluginHTTPError{Message: "some message"},
   413  		),
   414  		Entry("pluginerror.UnverifiedServerError -> DownloadPluginHTTPError",
   415  			pluginerror.UnverifiedServerError{URL: "some URL"},
   416  			DownloadPluginHTTPError{Message: "x509: certificate signed by unknown authority"},
   417  		),
   418  
   419  		// SSH Error
   420  		Entry("ssherror.UnableToAuthenticateError -> UnableToAuthenticateError",
   421  			ssherror.UnableToAuthenticateError{},
   422  			SSHUnableToAuthenticateError{}),
   423  
   424  		// UAA Errors
   425  		Entry("uaa.BadCredentialsError -> BadCredentialsError",
   426  			uaa.UnauthorizedError{Message: "some message"},
   427  			UnauthorizedError{Message: "some message"}),
   428  
   429  		Entry("uaa.AccountLockedError -> AccountLockedError",
   430  			uaa.AccountLockedError{Message: "locked out"},
   431  			AccountLockedError{Message: "locked out"}),
   432  
   433  		Entry("uaa.InsufficientScopeError -> UnauthorizedToPerformActionError",
   434  			uaa.InsufficientScopeError{},
   435  			UnauthorizedToPerformActionError{}),
   436  
   437  		Entry("uaa.InvalidAuthTokenError -> InvalidRefreshTokenError",
   438  			uaa.InvalidAuthTokenError{},
   439  			InvalidRefreshTokenError{}),
   440  
   441  		Entry("default case -> original error",
   442  			err,
   443  			err),
   444  	)
   445  
   446  	It("returns nil for a nil error", func() {
   447  		nilErr := ConvertToTranslatableError(nil)
   448  		Expect(nilErr).To(BeNil())
   449  	})
   450  })