Repository: VictorAvelar/mollie-api-go
Pull request #333 (2024-03-04 09:22:50)

check client_links resources against api reference
<!--- Provide a general summary of your changes in the Title above -->

# Description

Ensures that the `client_links` resource delivers API parity. 

## Motivation and context

Ensures the library has full API parity.

## How has this been tested?

Please describe in detail how you tested your changes.

Include details of your testing environment, and the tests you ran to
see how your change affects other areas of the code, etc.

- [x] Unit tests added / updated
- [x] The tests run on docker (using `make test`)
- [ ] The required `test data` has been added / updated

If you are running the tests locally, please specify:

- OS: macos
- Go version 1.22

## Types of changes

What types of changes does your code introduce? Put an `x` in all the boxes that apply:

- [ ] Bug fix (non-breaking change which fixes an issue)
- [ ] New feature (non-breaking change which adds functionality)
- [x] Breaking change (fix or feature that would cause existing functionality to change)
- [ ] This change requires a documentation update

## Checklist

Go over all the following points, and put an `x` in all the boxes that apply.

Please, please, please, don't send your pull request until all of the boxes are ticked. Once your pull request is created, it will trigger a build on our continuous integration server to make sure your [tests and code style pass](https://help.github.com/articles/about-required-status-checks/).

- [x] I have read the **[CONTRIBUTING](CONTRIBUTING.md)** document.
- [x] My pull request addresses exactly one patch/feature.
- [x] I have created a branch for this patch/feature.
- [x] Each individual commit in the pull request is meaningful.
- [x] If my change requires a change to the documentation, I have updated it accordingly.

<!-- If you're unsure about any of these, don't hesitate to ask. We're here to help! -->



Patch:
diff --git a/docs/README.md b/docs/README.md
index b7bf8eb..0418b94 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -84,13 +84,12 @@ REST also implies a nice and clean structure for URLs or endpoints. This means y
   - [func \(c \*Client\) NewAPIRequest\(ctx context.Context, method string, uri string, body interface\{\}\) \(req \*http.Request, err error\)](<#Client.NewAPIRequest>)
   - [func \(c \*Client\) SetIdempotencyKeyGenerator\(kg idempotency.KeyGenerator\)](<#Client.SetIdempotencyKeyGenerator>)
   - [func \(c \*Client\) WithAuthenticationValue\(k string\) error](<#Client.WithAuthenticationValue>)
-- [type ClientDetails](<#ClientDetails>)
 - [type ClientLink](<#ClientLink>)
-- [type ClientLinkFinalizeOptions](<#ClientLinkFinalizeOptions>)
+- [type ClientLinkAuthorizeOptions](<#ClientLinkAuthorizeOptions>)
 - [type ClientLinkLinks](<#ClientLinkLinks>)
 - [type ClientLinksService](<#ClientLinksService>)
-  - [func \(cls \*ClientLinksService\) CreateClientLink\(ctx context.Context, cd \*ClientDetails\) \(res \*Response, cl \*ClientLink, err error\)](<#ClientLinksService.CreateClientLink>)
-  - [func \(cls \*ClientLinksService\) CreateFinalizeClientLink\(ctx context.Context, clientLink string, options \*ClientLinkFinalizeOptions\) \(clientLinkURI string\)](<#ClientLinksService.CreateFinalizeClientLink>)
+  - [func \(cls \*ClientLinksService\) Create\(ctx context.Context, cd CreateClientLink\) \(res \*Response, cl \*ClientLink, err error\)](<#ClientLinksService.Create>)
+  - [func \(cls \*ClientLinksService\) GetFinalClientLink\(ctx context.Context, clientLink string, options \*ClientLinkAuthorizeOptions\) \(clientLinkURI string\)](<#ClientLinksService.GetFinalClientLink>)
 - [type Commission](<#Commission>)
 - [type Company](<#Company>)
 - [type Config](<#Config>)
@@ -106,6 +105,7 @@ REST also implies a nice and clean structure for URLs or endpoints. This means y
 - [type ContextValues](<#ContextValues>)
   - [func \(cv \*ContextValues\) UnmarshalJSON\(data \[\]byte\) error](<#ContextValues.UnmarshalJSON>)
 - [type CreateCapture](<#CreateCapture>)
+- [type CreateClientLink](<#CreateClientLink>)
 - [type CreateMollieConnectPaymentFields](<#CreateMollieConnectPaymentFields>)
 - [type CreatePayment](<#CreatePayment>)
 - [type CreatePaymentAccessTokenFields](<#CreatePaymentAccessTokenFields>)
@@ -1457,23 +1457,8 @@ WithAuthenticationValue offers a convenient setter for any of the valid authenti
 
 Ideally your API key will be provided from and environment variable or a secret management engine. This should only be used when environment variables are "impossible" to be used.
 
-<a name="ClientDetails"></a>
-## type [ClientDetails](<https://github.com/VictorAvelar/mollie-api-go/blob/master/mollie/client_links.go#L17-L23>)
-
-ClientDetails contains information to link a new organization to an OAuth application.
-
-```go
-type ClientDetails struct {
-    Owner              Owner    `json:"owner,omitempty"`
-    Name               string   `json:"name,omitempty"`
-    Address            *Address `json:"address,omitempty"`
-    RegistrationNumber string   `json:"registrationNumber,omitempty"`
-    VATNumber          string   `json:"vatNumber,omitempty"`
-}
-```
-
 <a name="ClientLink"></a>
-## type [ClientLink](<https://github.com/VictorAvelar/mollie-api-go/blob/master/mollie/client_links.go#L33-L37>)
+## type [ClientLink](<https://github.com/VictorAvelar/mollie-api-go/blob/master/mollie/client_links.go#L29-L33>)
 
 ClientLink object with redirect target.
 
@@ -1485,22 +1470,22 @@ type ClientLink struct {
 }
 ```
 
-<a name="ClientLinkFinalizeOptions"></a>
-## type [ClientLinkFinalizeOptions](<https://github.com/VictorAvelar/mollie-api-go/blob/master/mollie/client_links.go#L70-L75>)
+<a name="ClientLinkAuthorizeOptions"></a>
+## type [ClientLinkAuthorizeOptions](<https://github.com/VictorAvelar/mollie-api-go/blob/master/mollie/client_links.go#L70-L75>)
 
-ClientLinkFinalizeOptions subset of the parameters allowed for the Authorize endpoint.
+ClientLinkAuthorizeOptions subset of the parameters allowed for the Authorize endpoint.
 
 ```go
-type ClientLinkFinalizeOptions struct {
-    ClientID       string `url:"clientID,omitempty"`
-    State          string `url:"state,omitempty"`
-    Scope          string `url:"scope,omitempty"`
-    ApprovalPrompt string `url:"approvalPrompt,omitempty"`
+type ClientLinkAuthorizeOptions struct {
+    ClientID       string               `url:"clientId,omitempty"`
+    State          string               `url:"state,omitempty"`
+    Scope          []PermissionGrant    `del:"+"                        url:"scope,omitempty"`
+    ApprovalPrompt ApprovalPromptAction `url:"approvalPrompt,omitempty"`
 }
 ```
 
 <a name="ClientLinkLinks"></a>
-## type [ClientLinkLinks](<https://github.com/VictorAvelar/mollie-api-go/blob/master/mollie/client_links.go#L27-L30>)
+## type [ClientLinkLinks](<https://github.com/VictorAvelar/mollie-api-go/blob/master/mollie/client_links.go#L23-L26>)
 
 ClientLinkLinks describes all the possible links to be returned with a client links response object.
 
@@ -1512,7 +1497,7 @@ type ClientLinkLinks struct {
 ```
 
 <a name="ClientLinksService"></a>
-## type [ClientLinksService](<https://github.com/VictorAvelar/mollie-api-go/blob/master/mollie/client_links.go#L13>)
+## type [ClientLinksService](<https://github.com/VictorAvelar/mollie-api-go/blob/master/mollie/client_links.go#L37>)
 
 ClientLinksService interacts with the Client Links API to create new organizations for your customers.
 
@@ -1520,25 +1505,25 @@ ClientLinksService interacts with the Client Links API to create new organizatio
 type ClientLinksService service
 ```
 
-<a name="ClientLinksService.CreateClientLink"></a>
-### func \(\*ClientLinksService\) [CreateClientLink](<https://github.com/VictorAvelar/mollie-api-go/blob/master/mollie/client_links.go#L42-L46>)
+<a name="ClientLinksService.Create"></a>
+### func \(\*ClientLinksService\) [Create](<https://github.com/VictorAvelar/mollie-api-go/blob/master/mollie/client_links.go#L42-L46>)
 
 ```go
-func (cls *ClientLinksService) CreateClientLink(ctx context.Context, cd *ClientDetails) (res *Response, cl *ClientLink, err error)
+func (cls *ClientLinksService) Create(ctx context.Context, cd CreateClientLink) (res *Response, cl *ClientLink, err error)
 ```
 
-CreateClientLink based on the provided ClientDetails.
+Create a client link based on the provided CreateClientLink values.
 
 See: https://docs.mollie.com/reference/v2/client-links-api/create-client-link
 
-<a name="ClientLinksService.CreateFinalizeClientLink"></a>
-### func \(\*ClientLinksService\) [CreateFinalizeClientLink](<https://github.com/VictorAvelar/mollie-api-go/blob/master/mollie/client_links.go#L77-L83>)
+<a name="ClientLinksService.GetFinalClientLink"></a>
+### func \(\*ClientLinksService\) [GetFinalClientLink](<https://github.com/VictorAvelar/mollie-api-go/blob/master/mollie/client_links.go#L78-L84>)
 
 ```go
-func (cls *ClientLinksService) CreateFinalizeClientLink(ctx context.Context, clientLink string, options *ClientLinkFinalizeOptions) (clientLinkURI string)
+func (cls *ClientLinksService) GetFinalClientLink(ctx context.Context, clientLink string, options *ClientLinkAuthorizeOptions) (clientLinkURI string)
 ```
 
-
+GetFinalClientLink returns the final client link URI with the provided options.
 
 <a name="Commission"></a>
 ## type [Commission](<https://github.com/VictorAvelar/mollie-api-go/blob/master/mollie/partners.go#L38-L41>)
@@ -1826,6 +1811,21 @@ type CreateCapture struct {
 }
 ```
 
+<a name="CreateClientLink"></a>
+## type [CreateClientLink](<https://github.com/VictorAvelar/mollie-api-go/blob/master/mollie/client_links.go#L13-L19>)
+
+CreateClientLink contains information to link a new organization to an OAuth application.
+
+```go
+type CreateClientLink struct {
+    Owner              Owner    `json:"owner,omitempty"`
+    Name               string   `json:"name,omitempty"`
+    Address            *Address `json:"address,omitempty"`
+    RegistrationNumber string   `json:"registrationNumber,omitempty"`
+    VATNumber          string   `json:"vatNumber,omitempty"`
+}
+```
+
 <a name="CreateMollieConnectPaymentFields"></a>
 ## type [CreateMollieConnectPaymentFields](<https://github.com/VictorAvelar/mollie-api-go/blob/master/mollie/payments.go#L134-L137>)
 
@@ -4251,7 +4251,7 @@ const (
     ShipmentsWrite     PermissionGrant = "shipments.write"
     OrganizationsRead  PermissionGrant = "organizations.read"
     OrganizationsWrite PermissionGrant = "organizations.write"
-    OnboardingRead     PermissionGrant = "onbording.read"
+    OnboardingRead     PermissionGrant = "onboarding.read"
     OnboardingWrite    PermissionGrant = "onbording.write"
 )
 ```
diff --git a/mollie/client_links.go b/mollie/client_links.go
index 3646293..a833132 100644
--- a/mollie/client_links.go
+++ b/mollie/client_links.go
@@ -8,13 +8,9 @@ import (
 	"github.com/google/go-querystring/query"
 )
 
-// ClientLinksService interacts with the Client Links API to create
-// new organizations for your customers.
-type ClientLinksService service
-
-// ClientDetails contains information to link a new organization to an
+// CreateClientLink contains information to link a new organization to an
 // OAuth application.
-type ClientDetails struct {
+type CreateClientLink struct {
 	Owner              Owner    `json:"owner,omitempty"`
 	Name               string   `json:"name,omitempty"`
 	Address            *Address `json:"address,omitempty"`
@@ -36,10 +32,14 @@ type ClientLink struct {
 	Links    ClientLinkLinks `json:"_links,omitempty"`
 }
 
-// CreateClientLink based on the provided ClientDetails.
+// ClientLinksService interacts with the Client Links API to create
+// new organizations for your customers.
+type ClientLinksService service
+
+// Create a client link based on the provided CreateClientLink values.
 //
 // See: https://docs.mollie.com/reference/v2/client-links-api/create-client-link
-func (cls *ClientLinksService) CreateClientLink(ctx context.Context, cd *ClientDetails) (
+func (cls *ClientLinksService) Create(ctx context.Context, cd CreateClientLink) (
 	res *Response,
 	cl *ClientLink,
 	err error,
@@ -66,18 +66,19 @@ const (
 	AutoApproval  ApprovalPromptAction = "auto"
 )
 
-// ClientLinkFinalizeOptions subset of the parameters allowed for the Authorize endpoint.
-type ClientLinkFinalizeOptions struct {
-	ClientID       string `url:"clientID,omitempty"`
-	State          string `url:"state,omitempty"`
-	Scope          string `url:"scope,omitempty"`
-	ApprovalPrompt string `url:"approvalPrompt,omitempty"`
+// ClientLinkAuthorizeOptions subset of the parameters allowed for the Authorize endpoint.
+type ClientLinkAuthorizeOptions struct {
+	ClientID       string               `url:"clientId,omitempty"`
+	State          string               `url:"state,omitempty"`
+	Scope          []PermissionGrant    `del:"+"                        url:"scope,omitempty"`
+	ApprovalPrompt ApprovalPromptAction `url:"approvalPrompt,omitempty"`
 }
 
-func (cls *ClientLinksService) CreateFinalizeClientLink(
+// GetFinalClientLink returns the final client link URI with the provided options.
+func (cls *ClientLinksService) GetFinalClientLink(
 	ctx context.Context,
 	clientLink string,
-	options *ClientLinkFinalizeOptions,
+	options *ClientLinkAuthorizeOptions,
 ) (
 	clientLinkURI string,
 ) {
diff --git a/mollie/permissions.go b/mollie/permissions.go
index 8822d7c..9e44e30 100644
--- a/mollie/permissions.go
+++ b/mollie/permissions.go
@@ -30,7 +30,7 @@ const (
 	ShipmentsWrite     PermissionGrant = "shipments.write"
 	OrganizationsRead  PermissionGrant = "organizations.read"
 	OrganizationsWrite PermissionGrant = "organizations.write"
-	OnboardingRead     PermissionGrant = "onbording.read"
+	OnboardingRead     PermissionGrant = "onboarding.read"
 	OnboardingWrite    PermissionGrant = "onbording.write"
 )
 


Test patch:
diff --git a/mollie/client_links_test.go b/mollie/client_links_test.go
index 624e01a..66dd3f7 100644
--- a/mollie/client_links_test.go
+++ b/mollie/client_links_test.go
@@ -10,13 +10,13 @@ import (
 	"github.com/stretchr/testify/assert"
 )
 
-func TestCreateClientLink(t *testing.T) {
+func TestClientLinkService_Create(t *testing.T) {
 	setEnv()
 	defer unsetEnv()
 
 	type args struct {
 		ctx context.Context
-		cd  *ClientDetails
+		cd  CreateClientLink
 	}
 
 	cases := []struct {
@@ -31,7 +31,7 @@ func TestCreateClientLink(t *testing.T) {
 			"create new client link",
 			args{
 				context.Background(),
-				&ClientDetails{},
+				CreateClientLink{},
 			},
 			false,
 			nil,
@@ -50,7 +50,7 @@ func TestCreateClientLink(t *testing.T) {
 			"create client link, an error is returned from the server",
 			args{
 				context.Background(),
-				&ClientDetails{},
+				CreateClientLink{},
 			},
 			true,
 			fmt.Errorf("500 Internal Server Error: An internal server error occurred while processing your request."),
@@ -61,7 +61,7 @@ func TestCreateClientLink(t *testing.T) {
 			"create client link, an error occurs when parsing json",
 			args{
 				context.Background(),
-				&ClientDetails{},
+				CreateClientLink{},
 			},
 			true,
 			fmt.Errorf("invalid character 'h' looking for beginning of object key string"),
@@ -72,7 +72,7 @@ func TestCreateClientLink(t *testing.T) {
 			"create client link, invalid url when building request",
 			args{
 				context.Background(),
-				&ClientDetails{},
+				CreateClientLink{},
 			},
 			true,
 			errBadBaseURL,
@@ -91,7 +91,7 @@ func TestCreateClientLink(t *testing.T) {
 			)
 			c.pre()
 
-			res, cb, err := tClient.ClientLinks.CreateClientLink(c.args.ctx, c.args.cd)
+			res, cb, err := tClient.ClientLinks.Create(c.args.ctx, c.args.cd)
 			if c.wantErr {
 				assert.Error(t, err)
 				assert.EqualError(t, err, c.err.Error())
@@ -105,11 +105,14 @@ func TestCreateClientLink(t *testing.T) {
 	}
 }
 
-func TestCreateFinalizeClientLink(t *testing.T) {
+func TestClientLinkService_GetFinalClientLink(t *testing.T) {
+	setEnv()
+	defer unsetEnv()
+
 	type args struct {
 		ctx        context.Context
 		clientLink string
-		options    *ClientLinkFinalizeOptions
+		options    *ClientLinkAuthorizeOptions
 	}
 	tests := []struct {
 		name              string
@@ -121,43 +124,45 @@ func TestCreateFinalizeClientLink(t *testing.T) {
 			args{
 				context.Background(),
 				"https://my.mollie.com/dashboard/client-link/finalize/csr_vZCnNQsV2UtfXxYifWKWH",
-				&ClientLinkFinalizeOptions{
+				&ClientLinkAuthorizeOptions{
 					ClientID: "app_j9Pakf56Ajta6Y65AkdTtAv",
-					State:    "decafbad",
-					Scope:    "onboarding.read+organization.read+payments.write+payments.read+profiles.write",
+					State:    "unique_string_to_compare",
+					Scope:    []PermissionGrant{OnboardingRead, OnboardingWrite},
 				},
 			},
-			"https://my.mollie.com/dashboard/client-link/finalize/csr_vZCnNQsV2UtfXxYifWKWH?clientID=app_j9Pakf56Ajta6Y65AkdTtAv&scope=onboarding.read%2Borganization.read%2Bpayments.write%2Bpayments.read%2Bprofiles.write&state=decafbad",
+			"https://my.mollie.com/dashboard/client-link/finalize/csr_vZCnNQsV2UtfXxYifWKWH?clientId=app_j9Pakf56Ajta6Y65AkdTtAv&scope=onboarding.read%2Bonbording.write&state=unique_string_to_compare",
 		},
 		{
 			"constructs client link finalize with complex values",
 			args{
 				context.Background(),
 				"https://my.mollie.com/dashboard/client-link/finalize/csr_vZCnNQsV2UtfXxYifWKWH",
-				&ClientLinkFinalizeOptions{
+				&ClientLinkAuthorizeOptions{
 					ClientID: "",
 					State:    "\ns\\s\\s\\s\n",
-					Scope:    "",
+					Scope:    []PermissionGrant{},
 				},
 			},
 			"https://my.mollie.com/dashboard/client-link/finalize/csr_vZCnNQsV2UtfXxYifWKWH?state=%0As%5Cs%5Cs%5Cs%0A",
 		},
 		{
-			"constructs client link finalize with complex values",
+			"constructs client link finalize with no query params",
 			args{
 				context.Background(),
 				"https://my.mollie.com/dashboard/client-link/finalize/csr_vZCnNQsV2UtfXxYifWKWH",
-				&ClientLinkFinalizeOptions{},
+				&ClientLinkAuthorizeOptions{},
 			},
 			"https://my.mollie.com/dashboard/client-link/finalize/csr_vZCnNQsV2UtfXxYifWKWH?",
 		},
 	}
+
+	setup()
+	defer teardown()
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
-			gotClientLinkURI := tClient.ClientLinks.CreateFinalizeClientLink(tt.args.ctx, tt.args.clientLink, tt.args.options)
-			if gotClientLinkURI != tt.wantClientLinkURI {
-				t.Errorf("ClientLinksService.CreateFinalizeClientLink() = %v, want %v", gotClientLinkURI, tt.wantClientLinkURI)
-			}
+			gotClientLinkURI := tClient.ClientLinks.GetFinalClientLink(tt.args.ctx, tt.args.clientLink, tt.args.options)
+
+			assert.Equal(t, tt.wantClientLinkURI, gotClientLinkURI)
 		})
 	}
 }