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