Repository: ctreminiom/go-atlassian
Pull request #252 (2023-12-07 05:41:20)

:sparkles: Added the ability to manipulates de Issue Properties.


Patch:
diff --git a/go.mod b/go.mod
index 8face51..483629a 100644
--- a/go.mod
+++ b/go.mod
@@ -3,7 +3,7 @@ module github.com/ctreminiom/go-atlassian
 go 1.14
 
 require (
-	github.com/google/uuid v1.4.0
+	github.com/google/uuid v1.3.1
 	github.com/imdario/mergo v0.3.16
 	github.com/stretchr/testify v1.8.4
 	github.com/tidwall/gjson v1.17.0
diff --git a/go.sum b/go.sum
index 24f6296..86987de 100644
--- a/go.sum
+++ b/go.sum
@@ -1,8 +1,8 @@
 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
 github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
-github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4=
-github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4=
+github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
 github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4=
 github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY=
 github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
diff --git a/jira/internal/issue_impl.go b/jira/internal/issue_impl.go
index 560a05e..facab5e 100644
--- a/jira/internal/issue_impl.go
+++ b/jira/internal/issue_impl.go
@@ -27,6 +27,7 @@ type IssueServices struct {
 	Watcher         *WatcherService
 	WorklogAdf      *WorklogADFService
 	WorklogRichText *WorklogRichTextService
+	Property        *IssuePropertyService
 }
 
 func NewIssueService(client service.Connector, version string, services *IssueServices) (*IssueRichTextService, *IssueADFService, error) {
@@ -64,6 +65,7 @@ func NewIssueService(client service.Connector, version string, services *IssueSe
 		adfService.Vote = services.Vote
 		adfService.Watcher = services.Watcher
 		adfService.Worklog = services.WorklogAdf
+		adfService.Property = services.Property
 
 		richTextService.Comment = services.CommentRT
 		richTextService.Attachment = services.Attachment
@@ -78,6 +80,7 @@ func NewIssueService(client service.Connector, version string, services *IssueSe
 		richTextService.Vote = services.Vote
 		richTextService.Watcher = services.Watcher
 		richTextService.Worklog = services.WorklogRichText
+		richTextService.Property = services.Property
 
 	}
 
diff --git a/jira/internal/issue_impl_adf.go b/jira/internal/issue_impl_adf.go
index 0e43281..dfc4d9b 100644
--- a/jira/internal/issue_impl_adf.go
+++ b/jira/internal/issue_impl_adf.go
@@ -27,6 +27,7 @@ type IssueADFService struct {
 	Vote           *VoteService
 	Watcher        *WatcherService
 	Worklog        *WorklogADFService
+	Property       *IssuePropertyService
 }
 
 // Delete deletes an issue.
diff --git a/jira/internal/issue_impl_rich_text.go b/jira/internal/issue_impl_rich_text.go
index 68043b1..584d235 100644
--- a/jira/internal/issue_impl_rich_text.go
+++ b/jira/internal/issue_impl_rich_text.go
@@ -27,6 +27,7 @@ type IssueRichTextService struct {
 	Vote           *VoteService
 	Watcher        *WatcherService
 	Worklog        *WorklogRichTextService
+	Property       *IssuePropertyService
 }
 
 // Delete deletes an issue.
diff --git a/jira/internal/issue_property_impl.go b/jira/internal/issue_property_impl.go
new file mode 100644
index 0000000..b628310
--- /dev/null
+++ b/jira/internal/issue_property_impl.go
@@ -0,0 +1,192 @@
+package internal
+
+import (
+	"context"
+	"fmt"
+	model "github.com/ctreminiom/go-atlassian/pkg/infra/models"
+	"github.com/ctreminiom/go-atlassian/service"
+	"github.com/ctreminiom/go-atlassian/service/jira"
+	"net/http"
+)
+
+func NewIssuePropertyService(client service.Connector, version string) (*IssuePropertyService, error) {
+
+	if version == "" {
+		return nil, model.ErrNoVersionProvided
+	}
+
+	return &IssuePropertyService{
+		internalClient: &internalIssuePropertyImpl{c: client, version: version},
+	}, nil
+}
+
+type IssuePropertyService struct {
+	internalClient jira.IssuePropertyConnector
+}
+
+/*
+Gets returns the URLs and keys of an issue's properties.
+  - This operation can be accessed anonymously.
+
+Permissions required:
+  - Browse projects project permission for the project containing the issue.
+  - If issue-level security is configured, issue-level security permission to view the issue.
+
+Endpoint: GET /rest/api/{apiVersion}/issue/{issueIdOrKey}/properties
+
+You can refer to the documentation: [Get issue property keys]
+
+[Get issue property keys]: https://docs.go-atlassian.io/jira-software-cloud/issues/properties#get-issue-property-keys
+*/
+func (i *IssuePropertyService) Gets(ctx context.Context, issueIdOrKey string) (*model.PropertyPageScheme, *model.ResponseScheme, error) {
+	return i.internalClient.Gets(ctx, issueIdOrKey)
+}
+
+/*
+Get returns the key and value of an issue's property.
+  - This operation can be accessed anonymously.
+
+Permissions required:
+  - Browse projects project permission for the project containing the issue.
+  - If issue-level security is configured, issue-level security permission to view the issue.
+
+Endpoint: GET /rest/api/{apiVersion}/issue/{issueIdOrKey}/properties/{propertyKey}
+
+You can refer to the documentation: [Get issue property]
+
+[Get issue property]: https://docs.go-atlassian.io/jira-software-cloud/issues/properties#get-issue-property
+*/
+func (i *IssuePropertyService) Get(ctx context.Context, issueKey, propertyKey string) (*model.EntityPropertyScheme, *model.ResponseScheme, error) {
+	return i.internalClient.Get(ctx, issueKey, propertyKey)
+}
+
+/*
+Set sets the value of an issue's property. Use this resource to store custom data against an issue.
+  - The value of the request body must be a valid, non-empty JSON blob. The maximum length is 32768 characters.
+  - This operation can be accessed anonymously.
+
+Permissions required:
+  - Browse projects and Edit issues project permissions for the project containing the issue.
+  - If issue-level security is configured, issue-level security permission to view the issue.
+
+Endpoint: PUT /rest/api/{apiVersion}/issue/{issueIdOrKey}/properties/{propertyKey}
+
+You can refer to the documentation: [Set issue property]
+
+[Set issue property]: https://docs.go-atlassian.io/jira-software-cloud/issues/properties#set-issue-property
+*/
+func (i *IssuePropertyService) Set(ctx context.Context, issueKey, propertyKey string, payload interface{}) (*model.ResponseScheme, error) {
+	return i.internalClient.Set(ctx, issueKey, propertyKey, payload)
+}
+
+/*
+Delete deletes an issue's property.
+  - This operation can be accessed anonymously.
+
+Permissions required:
+  - Browse projects and Edit issues project permissions for the project containing the issue.
+  - If issue-level security is configured, issue-level security permission to view the issue.
+
+Endpoint: DELETE /rest/api/{apiVersion}/issue/{issueIdOrKey}/properties/{propertyKey}
+
+You can refer to the documentation: [Delete issue property]
+
+[Delete issue property]: https://docs.go-atlassian.io/jira-software-cloud/issues/properties#delete-issue-property
+*/
+func (i *IssuePropertyService) Delete(ctx context.Context, issueKey, propertyKey string) (*model.ResponseScheme, error) {
+	return i.internalClient.Delete(ctx, issueKey, propertyKey)
+}
+
+type internalIssuePropertyImpl struct {
+	c       service.Connector
+	version string
+}
+
+func (i *internalIssuePropertyImpl) Gets(ctx context.Context, issueIdOrKey string) (*model.PropertyPageScheme, *model.ResponseScheme, error) {
+
+	if issueIdOrKey == "" {
+		return nil, nil, model.ErrNoIssueKeyOrIDError
+	}
+
+	endpoint := fmt.Sprintf("rest/api/%v/issue/%v/properties", i.version, issueIdOrKey)
+
+	request, err := i.c.NewRequest(ctx, http.MethodGet, endpoint, "", nil)
+	if err != nil {
+		return nil, nil, err
+	}
+
+	properties := new(model.PropertyPageScheme)
+	response, err := i.c.Call(request, properties)
+	if err != nil {
+		return nil, response, err
+	}
+
+	return properties, response, nil
+
+}
+
+func (i *internalIssuePropertyImpl) Get(ctx context.Context, issueKey, propertyKey string) (*model.EntityPropertyScheme, *model.ResponseScheme, error) {
+
+	if issueKey == "" {
+		return nil, nil, model.ErrNoIssueKeyOrIDError
+	}
+
+	if propertyKey == "" {
+		return nil, nil, model.ErrNoPropertyKeyError
+	}
+
+	endpoint := fmt.Sprintf("rest/api/%v/issue/%v/properties/%v", i.version, issueKey, propertyKey)
+
+	request, err := i.c.NewRequest(ctx, http.MethodGet, endpoint, "", nil)
+	if err != nil {
+		return nil, nil, err
+	}
+
+	property := new(model.EntityPropertyScheme)
+	response, err := i.c.Call(request, property)
+	if err != nil {
+		return nil, response, err
+	}
+
+	return property, response, nil
+}
+
+func (i *internalIssuePropertyImpl) Set(ctx context.Context, issueKey, propertyKey string, payload interface{}) (*model.ResponseScheme, error) {
+
+	if issueKey == "" {
+		return nil, model.ErrNoIssueKeyOrIDError
+	}
+
+	if propertyKey == "" {
+		return nil, model.ErrNoPropertyKeyError
+	}
+
+	endpoint := fmt.Sprintf("rest/api/%v/issue/%v/properties/%v", i.version, issueKey, propertyKey)
+
+	request, err := i.c.NewRequest(ctx, http.MethodPut, endpoint, "", payload)
+	if err != nil {
+		return nil, err
+	}
+
+	return i.c.Call(request, nil)
+}
+
+func (i *internalIssuePropertyImpl) Delete(ctx context.Context, issueKey, propertyKey string) (*model.ResponseScheme, error) {
+
+	if issueKey == "" {
+		return nil, model.ErrNoIssueKeyOrIDError
+	}
+
+	if propertyKey == "" {
+		return nil, model.ErrNoPropertyKeyError
+	}
+
+	endpoint := fmt.Sprintf("rest/api/%v/issue/%v/properties/%v", i.version, issueKey, propertyKey)
+
+	request, err := i.c.NewRequest(ctx, http.MethodDelete, endpoint, "", nil)
+	if err != nil {
+		return nil, err
+	}
+
+	return i.c.Call(request, nil)
+}
diff --git a/jira/internal/project_property_impl.go b/jira/internal/project_property_impl.go
index 7918d82..6fc191e 100644
--- a/jira/internal/project_property_impl.go
+++ b/jira/internal/project_property_impl.go
@@ -29,7 +29,7 @@ type ProjectPropertyService struct {
 // GET /rest/api/{2-3}/project/{projectIdOrKey}/properties
 //
 // https://docs.go-atlassian.io/jira-software-cloud/projects/properties#get-project-properties-keys
-func (p *ProjectPropertyService) Gets(ctx context.Context, projectKeyOrId string) (*model.ProjectPropertyPageScheme, *model.ResponseScheme, error) {
+func (p *ProjectPropertyService) Gets(ctx context.Context, projectKeyOrId string) (*model.PropertyPageScheme, *model.ResponseScheme, error) {
 	return p.internalClient.Gets(ctx, projectKeyOrId)
 }
 
@@ -71,7 +71,7 @@ type internalProjectPropertyImpl struct {
 	version string
 }
 
-func (i *internalProjectPropertyImpl) Gets(ctx context.Context, projectKeyOrId string) (*model.ProjectPropertyPageScheme, *model.ResponseScheme, error) {
+func (i *internalProjectPropertyImpl) Gets(ctx context.Context, projectKeyOrId string) (*model.PropertyPageScheme, *model.ResponseScheme, error) {
 
 	if projectKeyOrId == "" {
 		return nil, nil, model.ErrNoProjectIDOrKeyError
@@ -84,7 +84,7 @@ func (i *internalProjectPropertyImpl) Gets(ctx context.Context, projectKeyOrId s
 		return nil, nil, err
 	}
 
-	properties := new(model.ProjectPropertyPageScheme)
+	properties := new(model.PropertyPageScheme)
 	response, err := i.c.Call(request, properties)
 	if err != nil {
 		return nil, response, err
diff --git a/jira/v2/api_client_impl.go b/jira/v2/api_client_impl.go
index 168d449..91bbfe2 100644
--- a/jira/v2/api_client_impl.go
+++ b/jira/v2/api_client_impl.go
@@ -187,6 +187,11 @@ func New(httpClient common.HttpClient, site string) (*Client, error) {
 		return nil, err
 	}
 
+	issueProperty, err := internal.NewIssuePropertyService(client, ApiVersion)
+	if err != nil {
+		return nil, err
+	}
+
 	issueServices := &internal.IssueServices{
 		Attachment:      issueAttachmentService,
 		CommentRT:       commentService,
@@ -201,6 +206,7 @@ func New(httpClient common.HttpClient, site string) (*Client, error) {
 		Vote:            vote,
 		Watcher:         watcher,
 		WorklogRichText: worklog,
+		Property:        issueProperty,
 	}
 
 	issueService, _, err := internal.NewIssueService(client, ApiVersion, issueServices)
diff --git a/jira/v3/api_client_impl.go b/jira/v3/api_client_impl.go
index 05586ee..b47cb70 100644
--- a/jira/v3/api_client_impl.go
+++ b/jira/v3/api_client_impl.go
@@ -187,6 +187,11 @@ func New(httpClient common.HttpClient, site string) (*Client, error) {
 		return nil, err
 	}
 
+	issueProperty, err := internal.NewIssuePropertyService(client, ApiVersion)
+	if err != nil {
+		return nil, err
+	}
+
 	issueServices := &internal.IssueServices{
 		Attachment: issueAttachmentService,
 		CommentADF: commentService,
@@ -201,6 +206,7 @@ func New(httpClient common.HttpClient, site string) (*Client, error) {
 		Vote:       vote,
 		Watcher:    watcher,
 		WorklogAdf: worklog,
+		Property:   issueProperty,
 	}
 
 	mySelf, err := internal.NewMySelfService(client, ApiVersion)
diff --git a/pkg/infra/models/jira_project_property.go b/pkg/infra/models/jira_project_property.go
index 35fa22f..410bb47 100644
--- a/pkg/infra/models/jira_project_property.go
+++ b/pkg/infra/models/jira_project_property.go
@@ -1,10 +1,10 @@
 package models
 
-type ProjectPropertyPageScheme struct {
-	Keys []*ProjectPropertyScheme `json:"keys,omitempty"`
+type PropertyPageScheme struct {
+	Keys []*PropertyScheme `json:"keys,omitempty"`
 }
 
-type ProjectPropertyScheme struct {
+type PropertyScheme struct {
 	Self string `json:"self,omitempty"`
 	Key  string `json:"key,omitempty"`
 }
diff --git a/service/bitbucket/repository.go b/service/bitbucket/repository.go
new file mode 100644
index 0000000..2832a59
--- /dev/null
+++ b/service/bitbucket/repository.go
@@ -0,0 +1,76 @@
+package bitbucket
+
+import (
+	"context"
+	"github.com/ctreminiom/go-atlassian/pkg/infra/models"
+)
+
+// RepositoryConnector represents the Bitbucket Cloud repositories.
+//
+// A Git repository is a virtual storage of your project. It allows you to save versions of your code, which you can access when needed.
+//
+// The repo resource allows you to access public repos, or repos that belong to a specific workspace.
+type RepositoryConnector interface {
+
+	// Get returns the object describing this repository.
+	//
+	// GET /2.0/repositories/{workspace}/{repo_slug}
+	Get(ctx context.Context, workspace, repoSlug string) (*models.RepositoryScheme, *models.ResponseScheme, error)
+
+	// Update updates a Bitbucket repository
+	//
+	// PUT /2.0/repositories/{workspace}/{repo_slug}
+	//
+	// Note: Changing the name of the repository will cause the location to be changed.
+	//
+	// This is because the URL of the repo is derived from the name (a process called slugification).
+	//
+	// In such a scenario, it is possible for the request to fail if the newly created slug conflicts with an existing repository's slug.
+	Update(ctx context.Context, workspace, repoSlug string, payload *models.RepositoryScheme) (*models.RepositoryScheme, *models.ResponseScheme, error)
+
+	// Delete deletes the repository. This is an irreversible operation and this does not affect its forks.
+	//
+	// DELETE /2.0/repositories/{workspace}/{repo_slug}
+	Delete(ctx context.Context, workspace, repoSlug, redirectTo string) (*models.ResponseScheme, error)
+
+	// Create creates a new repository.
+	Create(ctx context.Context, workspace, repoSlug string, payload *models.RepositoryScheme) (*models.RepositoryScheme, *models.ResponseScheme, error)
+
+	// Watchers returns a paginated list of all the watchers on the specified repository.
+	//
+	// GET /2.0/repositories/{workspace}/{repo_slug}/watchers
+	Watchers(ctx context.Context, workspace, repoSlug string)
+}
+
+type RepositoryForkConnector interface {
+	Gets(ctx context.Context)
+	Execute(ctx context.Context)
+}
+
+type RepositoryWebhookConnector interface {
+	Gets(ctx context.Context)
+	Get(ctx context.Context)
+	Create(ctx context.Context)
+	Update(ctx context.Context)
+	Delete(ctx context.Context)
+}
+
+type RepositorySettingConnector interface {
+	Gets(ctx context.Context)
+	Set(ctx context.Context)
+}
+
+type RepositoryGroupPermissionConnector interface {
+	Gets(ctx context.Context)
+	Get(ctx context.Context)
+	Update(ctx context.Context)
+	Delete(ctx context.Context)
+}
+
+type RepositoryUserPermissionConnector interface {
+	Gets(ctx context.Context)
+	Get(ctx context.Context)
+	Update(ctx context.Context)
+	Delete(ctx context.Context)
+	Check(ctx context.Context)
+}
diff --git a/service/jira/fieldConfig.go b/service/jira/field-config.go
similarity index 100%
rename from service/jira/fieldConfig.go
rename to service/jira/field-config.go
diff --git a/service/jira/fieldContext.go b/service/jira/field-context.go
similarity index 100%
rename from service/jira/fieldContext.go
rename to service/jira/field-context.go
diff --git a/service/jira/project.go b/service/jira/project.go
index b9a0289..5f2d3b5 100644
--- a/service/jira/project.go
+++ b/service/jira/project.go
@@ -225,7 +225,7 @@ type ProjectPropertyConnector interface {
 	// GET /rest/api/{2-3}/project/{projectIdOrKey}/properties
 	//
 	// https://docs.go-atlassian.io/jira-software-cloud/projects/properties#get-project-properties-keys
-	Gets(ctx context.Context, projectKeyOrId string) (*model.ProjectPropertyPageScheme, *model.ResponseScheme, error)
+	Gets(ctx context.Context, projectKeyOrId string) (*model.PropertyPageScheme, *model.ResponseScheme, error)
 
 	// Get returns the value of a project property.
 	//
diff --git a/service/jira/properties.go b/service/jira/properties.go
new file mode 100644
index 0000000..ad75583
--- /dev/null
+++ b/service/jira/properties.go
@@ -0,0 +1,81 @@
+package jira
+
+import (
+	"context"
+	model "github.com/ctreminiom/go-atlassian/pkg/infra/models"
+)
+
+/*
+IssuePropertyConnector represents issue properties, which provides for storing custom data against an issue.
+
+Use it to get, set, and delete issue properties as well as obtain details of all properties on an issue.
+
+Operations to bulk update and delete issue properties are also provided.
+*/
+type IssuePropertyConnector interface {
+
+	/*
+		Gets returns the URLs and keys of an issue's properties.
+			- This operation can be accessed anonymously.
+
+		Permissions required:
+			- Browse projects project permission for the project containing the issue.
+			- If issue-level security is configured, issue-level security permission to view the issue.
+
+		Endpoint: GET /rest/api/{apiVersion}/issue/{issueIdOrKey}/properties
+
+		You can refer to the documentation: [Get issue property keys]
+
+		[Get issue property keys]: https://docs.go-atlassian.io/jira-software-cloud/issues/properties#get-issue-property-keys
+	*/
+	Gets(ctx context.Context, issueIdOrKey string) (*model.PropertyPageScheme, *model.ResponseScheme, error)
+
+	/*
+		Get returns the key and value of an issue's property.
+			- This operation can be accessed anonymously.
+
+		Permissions required:
+			- Browse projects project permission for the project containing the issue.
+			- If issue-level security is configured, issue-level security permission to view the issue.
+
+		Endpoint: GET /rest/api/{apiVersion}/issue/{issueIdOrKey}/properties/{propertyKey}
+
+		You can refer to the documentation: [Get issue property]
+
+		[Get issue property]: https://docs.go-atlassian.io/jira-software-cloud/issues/properties#get-issue-property
+	*/
+	Get(ctx context.Context, issueKey, propertyKey string) (*model.EntityPropertyScheme, *model.ResponseScheme, error)
+
+	/*
+		Set sets the value of an issue's property. Use this resource to store custom data against an issue.
+			- The value of the request body must be a valid, non-empty JSON blob. The maximum length is 32768 characters.
+			- This operation can be accessed anonymously.
+
+		Permissions required:
+			- Browse projects and Edit issues project permissions for the project containing the issue.
+			- If issue-level security is configured, issue-level security permission to view the issue.
+
+		Endpoint: PUT /rest/api/{apiVersion}/issue/{issueIdOrKey}/properties/{propertyKey}
+
+		You can refer to the documentation: [Set issue property]
+
+		[Set issue property]: https://docs.go-atlassian.io/jira-software-cloud/issues/properties#set-issue-property
+	*/
+	Set(ctx context.Context, issueKey, propertyKey string, payload interface{}) (*model.ResponseScheme, error)
+
+	/*
+		Delete deletes an issue's property.
+			- This operation can be accessed anonymously.
+
+		Permissions required:
+			- Browse projects and Edit issues project permissions for the project containing the issue.
+			- If issue-level security is configured, issue-level security permission to view the issue.
+
+		Endpoint: DELETE /rest/api/{apiVersion}/issue/{issueIdOrKey}/properties/{propertyKey}
+
+		You can refer to the documentation: [Delete issue property]
+
+		[Delete issue property]: https://docs.go-atlassian.io/jira-software-cloud/issues/properties#delete-issue-property
+	*/
+	Delete(ctx context.Context, issueKey, propertyKey string) (*model.ResponseScheme, error)
+}


Test patch:
diff --git a/jira/internal/attachment_impl_test.go b/jira/internal/attachment_impl_test.go
index f4add1f..28c58a1 100644
--- a/jira/internal/attachment_impl_test.go
+++ b/jira/internal/attachment_impl_test.go
@@ -38,7 +38,7 @@ func Test_internalIssueAttachmentServiceImpl_Settings(t *testing.T) {
 			name:   "when the api version is v2",
 			fields: fields{version: "2"},
 			args: args{
-				ctx: context.TODO(),
+				ctx: context.Background(),
 			},
 			on: func(fields *fields) {
 
@@ -66,7 +66,7 @@ func Test_internalIssueAttachmentServiceImpl_Settings(t *testing.T) {
 			name:   "when the api version is v3",
 			fields: fields{version: "3"},
 			args: args{
-				ctx: context.TODO(),
+				ctx: context.Background(),
 			},
 			on: func(fields *fields) {
 
@@ -94,7 +94,7 @@ func Test_internalIssueAttachmentServiceImpl_Settings(t *testing.T) {
 			name:   "when the http request cannot be created",
 			fields: fields{version: "2"},
 			args: args{
-				ctx: context.TODO(),
+				ctx: context.Background(),
 			},
 			on: func(fields *fields) {
 
@@ -171,7 +171,7 @@ func Test_internalIssueAttachmentServiceImpl_Metadata(t *testing.T) {
 			name:   "when the api version is v2",
 			fields: fields{version: "2"},
 			args: args{
-				ctx:          context.TODO(),
+				ctx:          context.Background(),
 				attachmentId: "1110",
 			},
 			on: func(fields *fields) {
@@ -199,7 +199,7 @@ func Test_internalIssueAttachmentServiceImpl_Metadata(t *testing.T) {
 			name:   "when the api version is v3",
 			fields: fields{version: "3"},
 			args: args{
-				ctx:          context.TODO(),
+				ctx:          context.Background(),
 				attachmentId: "1110",
 			},
 			on: func(fields *fields) {
@@ -228,7 +228,7 @@ func Test_internalIssueAttachmentServiceImpl_Metadata(t *testing.T) {
 			name:   "when the attachment id is not provided",
 			fields: fields{version: "2"},
 			args: args{
-				ctx:          context.TODO(),
+				ctx:          context.Background(),
 				attachmentId: "",
 			},
 			on: func(fields *fields) {
@@ -242,7 +242,7 @@ func Test_internalIssueAttachmentServiceImpl_Metadata(t *testing.T) {
 			name:   "when the http request cannot be created",
 			fields: fields{version: "2"},
 			args: args{
-				ctx:          context.TODO(),
+				ctx:          context.Background(),
 				attachmentId: "1110",
 			},
 			on: func(fields *fields) {
@@ -320,7 +320,7 @@ func Test_internalIssueAttachmentServiceImpl_Human(t *testing.T) {
 			name:   "when the api version is v2",
 			fields: fields{version: "2"},
 			args: args{
-				ctx:          context.TODO(),
+				ctx:          context.Background(),
 				attachmentId: "1110",
 			},
 			on: func(fields *fields) {
@@ -348,7 +348,7 @@ func Test_internalIssueAttachmentServiceImpl_Human(t *testing.T) {
 			name:   "when the api version is v3",
 			fields: fields{version: "3"},
 			args: args{
-				ctx:          context.TODO(),
+				ctx:          context.Background(),
 				attachmentId: "1110",
 			},
 			on: func(fields *fields) {
@@ -377,7 +377,7 @@ func Test_internalIssueAttachmentServiceImpl_Human(t *testing.T) {
 			name:   "when the attachment id is not provided",
 			fields: fields{version: "2"},
 			args: args{
-				ctx:          context.TODO(),
+				ctx:          context.Background(),
 				attachmentId: "",
 			},
 			on: func(fields *fields) {
@@ -391,7 +391,7 @@ func Test_internalIssueAttachmentServiceImpl_Human(t *testing.T) {
 			name:   "when the http request cannot be created",
 			fields: fields{version: "2"},
 			args: args{
-				ctx:          context.TODO(),
+				ctx:          context.Background(),
 				attachmentId: "1110",
 			},
 			on: func(fields *fields) {
@@ -469,7 +469,7 @@ func Test_internalIssueAttachmentServiceImpl_Delete(t *testing.T) {
 			name:   "when the api version is v2",
 			fields: fields{version: "2"},
 			args: args{
-				ctx:          context.TODO(),
+				ctx:          context.Background(),
 				attachmentId: "1110",
 			},
 			on: func(fields *fields) {
@@ -497,7 +497,7 @@ func Test_internalIssueAttachmentServiceImpl_Delete(t *testing.T) {
 			name:   "when the api version is v3",
 			fields: fields{version: "3"},
 			args: args{
-				ctx:          context.TODO(),
+				ctx:          context.Background(),
 				attachmentId: "1110",
 			},
 			on: func(fields *fields) {
@@ -526,7 +526,7 @@ func Test_internalIssueAttachmentServiceImpl_Delete(t *testing.T) {
 			name:   "when the attachment id is not provided",
 			fields: fields{version: "2"},
 			args: args{
-				ctx:          context.TODO(),
+				ctx:          context.Background(),
 				attachmentId: "",
 			},
 			on: func(fields *fields) {
@@ -540,7 +540,7 @@ func Test_internalIssueAttachmentServiceImpl_Delete(t *testing.T) {
 			name:   "when the http request cannot be created",
 			fields: fields{version: "2"},
 			args: args{
-				ctx:          context.TODO(),
+				ctx:          context.Background(),
 				attachmentId: "1110",
 			},
 			on: func(fields *fields) {
@@ -628,7 +628,7 @@ func Test_internalIssueAttachmentServiceImpl_Add(t *testing.T) {
 			name:   "when the api version is v2",
 			fields: fields{version: "2"},
 			args: args{
-				ctx:          context.TODO(),
+				ctx:          context.Background(),
 				issueKeyOrId: "DUMMY-1",
 				fileName:     "LICENSE",
 				file:         fileMocked,
@@ -658,7 +658,7 @@ func Test_internalIssueAttachmentServiceImpl_Add(t *testing.T) {
 			name:   "when the api version is v3",
 			fields: fields{version: "3"},
 			args: args{
-				ctx:          context.TODO(),
+				ctx:          context.Background(),
 				issueKeyOrId: "DUMMY-1",
 				fileName:     "LICENSE",
 				file:         fileMocked,
@@ -688,7 +688,7 @@ func Test_internalIssueAttachmentServiceImpl_Add(t *testing.T) {
 			name:   "when the issue key or id is not provided",
 			fields: fields{version: "2"},
 			args: args{
-				ctx:          context.TODO(),
+				ctx:          context.Background(),
 				issueKeyOrId: "",
 				fileName:     "LICENSE",
 				file:         fileMocked,
@@ -701,7 +701,7 @@ func Test_internalIssueAttachmentServiceImpl_Add(t *testing.T) {
 			name:   "when the file name is not provided",
 			fields: fields{version: "2"},
 			args: args{
-				ctx:          context.TODO(),
+				ctx:          context.Background(),
 				issueKeyOrId: "DUMMY-1",
 				fileName:     "",
 				file:         fileMocked,
@@ -714,7 +714,7 @@ func Test_internalIssueAttachmentServiceImpl_Add(t *testing.T) {
 			name:   "when the field reader is not provided",
 			fields: fields{version: "2"},
 			args: args{
-				ctx:          context.TODO(),
+				ctx:          context.Background(),
 				issueKeyOrId: "DUMMY-1",
 				fileName:     "LICENSE",
 				file:         nil,
@@ -727,7 +727,7 @@ func Test_internalIssueAttachmentServiceImpl_Add(t *testing.T) {
 			name:   "when the http request cannot be created",
 			fields: fields{version: "2"},
 			args: args{
-				ctx:          context.TODO(),
+				ctx:          context.Background(),
 				issueKeyOrId: "DUMMY-1",
 				fileName:     "LICENSE",
 				file:         fileMocked,
@@ -808,7 +808,7 @@ func Test_internalIssueAttachmentServiceImpl_Download(t *testing.T) {
 			name:   "when the api version is v2",
 			fields: fields{version: "2"},
 			args: args{
-				ctx:          context.TODO(),
+				ctx:          context.Background(),
 				attachmentId: "1110",
 				redirect:     false,
 			},
@@ -837,7 +837,7 @@ func Test_internalIssueAttachmentServiceImpl_Download(t *testing.T) {
 			name:   "when the api version is v3",
 			fields: fields{version: "3"},
 			args: args{
-				ctx:          context.TODO(),
+				ctx:          context.Background(),
 				attachmentId: "1110",
 				redirect:     true,
 			},
@@ -867,7 +867,7 @@ func Test_internalIssueAttachmentServiceImpl_Download(t *testing.T) {
 			name:   "when the attachment id is not provided",
 			fields: fields{version: "2"},
 			args: args{
-				ctx:          context.TODO(),
+				ctx:          context.Background(),
 				attachmentId: "",
 			},
 			on: func(fields *fields) {
@@ -881,7 +881,7 @@ func Test_internalIssueAttachmentServiceImpl_Download(t *testing.T) {
 			name:   "when the http request cannot be created",
 			fields: fields{version: "2"},
 			args: args{
-				ctx:          context.TODO(),
+				ctx:          context.Background(),
 				attachmentId: "1110",
 				redirect:     true,
 			},
diff --git a/jira/internal/issue_property_impl_test.go b/jira/internal/issue_property_impl_test.go
new file mode 100644
index 0000000..13a9645
--- /dev/null
+++ b/jira/internal/issue_property_impl_test.go
@@ -0,0 +1,694 @@
+package internal
+
+import (
+	"context"
+	"errors"
+	model "github.com/ctreminiom/go-atlassian/pkg/infra/models"
+	"github.com/ctreminiom/go-atlassian/service"
+	"github.com/ctreminiom/go-atlassian/service/mocks"
+	"github.com/stretchr/testify/assert"
+	"net/http"
+	"testing"
+)
+
+func Test_internalIssuePropertyImpl_Gets(t *testing.T) {
+
+	type fields struct {
+		c       service.Connector
+		version string
+	}
+
+	type args struct {
+		ctx          context.Context
+		issueKeyOrID string
+	}
+
+	testCases := []struct {
+		name    string
+		fields  fields
+		args    args
+		on      func(*fields)
+		wantErr bool
+		Err     error
+	}{
+		{
+			name:   "when the api version is v3",
+			fields: fields{version: "3"},
+			args: args{
+				ctx:          context.Background(),
+				issueKeyOrID: "DUMMY-1",
+			},
+			on: func(fields *fields) {
+
+				client := mocks.NewConnector(t)
+
+				client.On("NewRequest",
+					context.Background(),
+					http.MethodGet,
+					"rest/api/3/issue/DUMMY-1/properties",
+					"", nil).
+					Return(&http.Request{}, nil)
+
+				client.On("Call",
+					&http.Request{},
+					&model.PropertyPageScheme{}).
+					Return(&model.ResponseScheme{}, nil)
+
+				fields.c = client
+			},
+			wantErr: false,
+			Err:     nil,
+		},
+
+		{
+			name:   "when the api version is v2",
+			fields: fields{version: "2"},
+			args: args{
+				ctx:          context.Background(),
+				issueKeyOrID: "DUMMY-1",
+			},
+			on: func(fields *fields) {
+
+				client := mocks.NewConnector(t)
+
+				client.On("NewRequest",
+					context.Background(),
+					http.MethodGet,
+					"rest/api/2/issue/DUMMY-1/properties",
+					"", nil).
+					Return(&http.Request{}, nil)
+
+				client.On("Call",
+					&http.Request{},
+					&model.PropertyPageScheme{}).
+					Return(&model.ResponseScheme{}, nil)
+
+				fields.c = client
+			},
+			wantErr: false,
+			Err:     nil,
+		},
+
+		{
+			name:   "when the issue key or id is not provided",
+			fields: fields{version: "3"},
+			args: args{
+				ctx: context.TODO(),
+			},
+			wantErr: true,
+			Err:     model.ErrNoIssueKeyOrIDError,
+		},
+
+		{
+			name:   "when the http request cannot be created",
+			fields: fields{version: "3"},
+			args: args{
+				ctx:          context.Background(),
+				issueKeyOrID: "DUMMY-1",
+			},
+			on: func(fields *fields) {
+
+				client := mocks.NewConnector(t)
+
+				client.On("NewRequest",
+					context.Background(),
+					http.MethodGet,
+					"rest/api/3/issue/DUMMY-1/properties",
+					"", nil).
+					Return(&http.Request{}, errors.New("error, unable to create the http request"))
+
+				fields.c = client
+			},
+			wantErr: true,
+			Err:     errors.New("error, unable to create the http request"),
+		},
+	}
+
+	for _, testCase := range testCases {
+		t.Run(testCase.name, func(t *testing.T) {
+
+			if testCase.on != nil {
+				testCase.on(&testCase.fields)
+			}
+
+			newService, err := NewIssuePropertyService(testCase.fields.c, testCase.fields.version)
+			assert.NoError(t, err)
+
+			gotResult, gotResponse, err := newService.Gets(testCase.args.ctx, testCase.args.issueKeyOrID)
+
+			if testCase.wantErr {
+
+				if err != nil {
+					t.Logf("error returned: %v", err.Error())
+				}
+
+				assert.EqualError(t, err, testCase.Err.Error())
+
+			} else {
+
+				assert.NoError(t, err)
+				assert.NotEqual(t, gotResponse, nil)
+				assert.NotEqual(t, gotResult, nil)
+			}
+
+		})
+	}
+}
+
+func Test_internalIssuePropertyImpl_Get(t *testing.T) {
+
+	type fields struct {
+		c       service.Connector
+		version string
+	}
+
+	type args struct {
+		ctx          context.Context
+		issueKeyOrID string
+		propertyKey  string
+	}
+
+	testCases := []struct {
+		name    string
+		fields  fields
+		args    args
+		on      func(*fields)
+		wantErr bool
+		Err     error
+	}{
+		{
+			name:   "when the api version is v3",
+			fields: fields{version: "3"},
+			args: args{
+				ctx:          context.Background(),
+				issueKeyOrID: "DUMMY-1",
+				propertyKey:  "alliance",
+			},
+			on: func(fields *fields) {
+
+				client := mocks.NewConnector(t)
+
+				client.On("NewRequest",
+					context.Background(),
+					http.MethodGet,
+					"rest/api/3/issue/DUMMY-1/properties/alliance",
+					"", nil).
+					Return(&http.Request{}, nil)
+
+				client.On("Call",
+					&http.Request{},
+					&model.EntityPropertyScheme{}).
+					Return(&model.ResponseScheme{}, nil)
+
+				fields.c = client
+			},
+			wantErr: false,
+			Err:     nil,
+		},
+
+		{
+			name:   "when the api version is v2",
+			fields: fields{version: "2"},
+			args: args{
+				ctx:          context.Background(),
+				issueKeyOrID: "DUMMY-1",
+				propertyKey:  "alliance",
+			},
+			on: func(fields *fields) {
+
+				client := mocks.NewConnector(t)
+
+				client.On("NewRequest",
+					context.Background(),
+					http.MethodGet,
+					"rest/api/2/issue/DUMMY-1/properties/alliance",
+					"", nil).
+					Return(&http.Request{}, nil)
+
+				client.On("Call",
+					&http.Request{},
+					&model.EntityPropertyScheme{}).
+					Return(&model.ResponseScheme{}, nil)
+
+				fields.c = client
+			},
+			wantErr: false,
+			Err:     nil,
+		},
+
+		{
+			name:   "when the issue key or id is not provided",
+			fields: fields{version: "3"},
+			args: args{
+				ctx: context.Background(),
+			},
+			wantErr: true,
+			Err:     model.ErrNoIssueKeyOrIDError,
+		},
+
+		{
+			name:   "when the property key is not provided",
+			fields: fields{version: "3"},
+			args: args{
+				ctx:          context.Background(),
+				issueKeyOrID: "DUMMY-1",
+			},
+			wantErr: true,
+			Err:     model.ErrNoPropertyKeyError,
+		},
+
+		{
+			name:   "when the http request cannot be created",
+			fields: fields{version: "3"},
+			args: args{
+				ctx:          context.Background(),
+				issueKeyOrID: "DUMMY-1",
+				propertyKey:  "alliance",
+			},
+			on: func(fields *fields) {
+
+				client := mocks.NewConnector(t)
+
+				client.On("NewRequest",
+					context.Background(),
+					http.MethodGet,
+					"rest/api/3/issue/DUMMY-1/properties/alliance",
+					"", nil).
+					Return(&http.Request{}, errors.New("error, unable to create the http request"))
+
+				fields.c = client
+			},
+			wantErr: true,
+			Err:     errors.New("error, unable to create the http request"),
+		},
+	}
+
+	for _, testCase := range testCases {
+		t.Run(testCase.name, func(t *testing.T) {
+
+			if testCase.on != nil {
+				testCase.on(&testCase.fields)
+			}
+
+			newService, err := NewIssuePropertyService(testCase.fields.c, testCase.fields.version)
+			assert.NoError(t, err)
+
+			gotResult, gotResponse, err := newService.Get(testCase.args.ctx, testCase.args.issueKeyOrID, testCase.args.propertyKey)
+
+			if testCase.wantErr {
+
+				if err != nil {
+					t.Logf("error returned: %v", err.Error())
+				}
+
+				assert.EqualError(t, err, testCase.Err.Error())
+
+			} else {
+
+				assert.NoError(t, err)
+				assert.NotEqual(t, gotResponse, nil)
+				assert.NotEqual(t, gotResult, nil)
+			}
+
+		})
+	}
+}
+
+func Test_internalIssuePropertyImpl_Set(t *testing.T) {
+
+	payloadMocked := map[string]interface{}{
+		"system.conversation.id": "b1bf38be-5e94-4b40-a3b8-9278735ee1e6",
+		"system.support.time":    "1m",
+	}
+
+	type fields struct {
+		c       service.Connector
+		version string
+	}
+
+	type args struct {
+		ctx          context.Context
+		issueKeyOrID string
+		propertyKey  string
+		payload      interface{}
+	}
+
+	testCases := []struct {
+		name    string
+		fields  fields
+		args    args
+		on      func(*fields)
+		wantErr bool
+		Err     error
+	}{
+		{
+			name:   "when the api version is v3",
+			fields: fields{version: "3"},
+			args: args{
+				ctx:          context.Background(),
+				issueKeyOrID: "DUMMY-1",
+				propertyKey:  "alliance",
+				payload:      payloadMocked,
+			},
+			on: func(fields *fields) {
+
+				client := mocks.NewConnector(t)
+
+				client.On("NewRequest",
+					context.Background(),
+					http.MethodPut,
+					"rest/api/3/issue/DUMMY-1/properties/alliance",
+					"", payloadMocked).
+					Return(&http.Request{}, nil)
+
+				client.On("Call",
+					&http.Request{},
+					nil).
+					Return(&model.ResponseScheme{}, nil)
+
+				fields.c = client
+			},
+			wantErr: false,
+			Err:     nil,
+		},
+
+		{
+			name:   "when the api version is v2",
+			fields: fields{version: "2"},
+			args: args{
+				ctx:          context.Background(),
+				issueKeyOrID: "DUMMY-1",
+				propertyKey:  "alliance",
+				payload:      payloadMocked,
+			},
+			on: func(fields *fields) {
+
+				client := mocks.NewConnector(t)
+
+				client.On("NewRequest",
+					context.Background(),
+					http.MethodPut,
+					"rest/api/2/issue/DUMMY-1/properties/alliance",
+					"", payloadMocked).
+					Return(&http.Request{}, nil)
+
+				client.On("Call",
+					&http.Request{},
+					nil).
+					Return(&model.ResponseScheme{}, nil)
+
+				fields.c = client
+			},
+			wantErr: false,
+			Err:     nil,
+		},
+
+		{
+			name:   "when the issue key or id is not provided",
+			fields: fields{version: "3"},
+			args: args{
+				ctx: context.Background(),
+			},
+			wantErr: true,
+			Err:     model.ErrNoIssueKeyOrIDError,
+		},
+
+		{
+			name:   "when the property key is not provided",
+			fields: fields{version: "3"},
+			args: args{
+				ctx:          context.Background(),
+				issueKeyOrID: "DUMMY-1",
+			},
+			wantErr: true,
+			Err:     model.ErrNoPropertyKeyError,
+		},
+
+		{
+			name:   "when the http request cannot be created",
+			fields: fields{version: "3"},
+			args: args{
+				ctx:          context.Background(),
+				issueKeyOrID: "DUMMY-1",
+				propertyKey:  "alliance",
+				payload:      payloadMocked,
+			},
+			on: func(fields *fields) {
+
+				client := mocks.NewConnector(t)
+
+				client.On("NewRequest",
+					context.Background(),
+					http.MethodPut,
+					"rest/api/3/issue/DUMMY-1/properties/alliance",
+					"", payloadMocked).
+					Return(&http.Request{}, errors.New("error, unable to create the http request"))
+
+				fields.c = client
+			},
+			wantErr: true,
+			Err:     errors.New("error, unable to create the http request"),
+		},
+	}
+
+	for _, testCase := range testCases {
+		t.Run(testCase.name, func(t *testing.T) {
+
+			if testCase.on != nil {
+				testCase.on(&testCase.fields)
+			}
+
+			newService, err := NewIssuePropertyService(testCase.fields.c, testCase.fields.version)
+			assert.NoError(t, err)
+
+			gotResponse, err := newService.Set(testCase.args.ctx, testCase.args.issueKeyOrID, testCase.args.propertyKey,
+				testCase.args.payload)
+
+			if testCase.wantErr {
+
+				if err != nil {
+					t.Logf("error returned: %v", err.Error())
+				}
+
+				assert.EqualError(t, err, testCase.Err.Error())
+
+			} else {
+
+				assert.NoError(t, err)
+				assert.NotEqual(t, gotResponse, nil)
+			}
+
+		})
+	}
+}
+
+func Test_internalIssuePropertyImpl_Delete(t *testing.T) {
+
+	type fields struct {
+		c       service.Connector
+		version string
+	}
+
+	type args struct {
+		ctx          context.Context
+		issueKeyOrID string
+		propertyKey  string
+	}
+
+	testCases := []struct {
+		name    string
+		fields  fields
+		args    args
+		on      func(*fields)
+		wantErr bool
+		Err     error
+	}{
+		{
+			name:   "when the api version is v3",
+			fields: fields{version: "3"},
+			args: args{
+				ctx:          context.Background(),
+				issueKeyOrID: "DUMMY-1",
+				propertyKey:  "alliance",
+			},
+			on: func(fields *fields) {
+
+				client := mocks.NewConnector(t)
+
+				client.On("NewRequest",
+					context.Background(),
+					http.MethodDelete,
+					"rest/api/3/issue/DUMMY-1/properties/alliance",
+					"", nil).
+					Return(&http.Request{}, nil)
+
+				client.On("Call",
+					&http.Request{},
+					nil).
+					Return(&model.ResponseScheme{}, nil)
+
+				fields.c = client
+			},
+			wantErr: false,
+			Err:     nil,
+		},
+
+		{
+			name:   "when the api version is v2",
+			fields: fields{version: "2"},
+			args: args{
+				ctx:          context.Background(),
+				issueKeyOrID: "DUMMY-1",
+				propertyKey:  "alliance",
+			},
+			on: func(fields *fields) {
+
+				client := mocks.NewConnector(t)
+
+				client.On("NewRequest",
+					context.Background(),
+					http.MethodDelete,
+					"rest/api/2/issue/DUMMY-1/properties/alliance",
+					"", nil).
+					Return(&http.Request{}, nil)
+
+				client.On("Call",
+					&http.Request{},
+					nil).
+					Return(&model.ResponseScheme{}, nil)
+
+				fields.c = client
+			},
+			wantErr: false,
+			Err:     nil,
+		},
+
+		{
+			name:   "when the issue key or id is not provided",
+			fields: fields{version: "3"},
+			args: args{
+				ctx: context.Background(),
+			},
+			wantErr: true,
+			Err:     model.ErrNoIssueKeyOrIDError,
+		},
+
+		{
+			name:   "when the property key is not provided",
+			fields: fields{version: "3"},
+			args: args{
+				ctx:          context.Background(),
+				issueKeyOrID: "DUMMY-1",
+			},
+			wantErr: true,
+			Err:     model.ErrNoPropertyKeyError,
+		},
+
+		{
+			name:   "when the http request cannot be created",
+			fields: fields{version: "3"},
+			args: args{
+				ctx:          context.Background(),
+				issueKeyOrID: "DUMMY-1",
+				propertyKey:  "alliance",
+			},
+			on: func(fields *fields) {
+
+				client := mocks.NewConnector(t)
+
+				client.On("NewRequest",
+					context.Background(),
+					http.MethodDelete,
+					"rest/api/3/issue/DUMMY-1/properties/alliance",
+					"", nil).
+					Return(&http.Request{}, errors.New("error, unable to create the http request"))
+
+				fields.c = client
+			},
+			wantErr: true,
+			Err:     errors.New("error, unable to create the http request"),
+		},
+	}
+
+	for _, testCase := range testCases {
+		t.Run(testCase.name, func(t *testing.T) {
+
+			if testCase.on != nil {
+				testCase.on(&testCase.fields)
+			}
+
+			newService, err := NewIssuePropertyService(testCase.fields.c, testCase.fields.version)
+			assert.NoError(t, err)
+
+			gotResponse, err := newService.Delete(testCase.args.ctx, testCase.args.issueKeyOrID, testCase.args.propertyKey)
+
+			if testCase.wantErr {
+
+				if err != nil {
+					t.Logf("error returned: %v", err.Error())
+				}
+
+				assert.EqualError(t, err, testCase.Err.Error())
+
+			} else {
+
+				assert.NoError(t, err)
+				assert.NotEqual(t, gotResponse, nil)
+			}
+
+		})
+	}
+}
+
+func TestNewIssuePropertyService(t *testing.T) {
+
+	type args struct {
+		client  service.Connector
+		version string
+	}
+
+	testCases := []struct {
+		name    string
+		args    args
+		wantErr bool
+		err     error
+	}{
+		{
+			name: "when the parameters are correct",
+			args: args{
+				client:  nil,
+				version: "3",
+			},
+			wantErr: false,
+		},
+
+		{
+			name: "when the version is not provided",
+			args: args{
+				client:  nil,
+				version: "",
+			},
+			wantErr: true,
+			err:     model.ErrNoVersionProvided,
+		},
+	}
+	for _, testCase := range testCases {
+		t.Run(testCase.name, func(t *testing.T) {
+			got, err := NewIssuePropertyService(testCase.args.client, testCase.args.version)
+
+			if testCase.wantErr {
+
+				if err != nil {
+					t.Logf("error returned: %v", err.Error())
+				}
+
+				assert.EqualError(t, err, testCase.err.Error())
+
+			} else {
+
+				assert.NoError(t, err)
+				assert.NotEqual(t, got, nil)
+			}
+		})
+	}
+}
diff --git a/jira/internal/project_property_impl_test.go b/jira/internal/project_property_impl_test.go
index 9e43862..63cd0d5 100644
--- a/jira/internal/project_property_impl_test.go
+++ b/jira/internal/project_property_impl_test.go
@@ -35,7 +35,7 @@ func Test_internalProjectPropertyImpl_Gets(t *testing.T) {
 			name:   "when the api version is v3",
 			fields: fields{version: "3"},
 			args: args{
-				ctx:            context.TODO(),
+				ctx:            context.Background(),
 				projectKeyOrId: "DUMMY",
 			},
 			on: func(fields *fields) {
@@ -51,7 +51,7 @@ func Test_internalProjectPropertyImpl_Gets(t *testing.T) {
 
 				client.On("Call",
 					&http.Request{},
-					&model.ProjectPropertyPageScheme{}).
+					&model.PropertyPageScheme{}).
 					Return(&model.ResponseScheme{}, nil)
 
 				fields.c = client
@@ -64,7 +64,7 @@ func Test_internalProjectPropertyImpl_Gets(t *testing.T) {
 			name:   "when the api version is v2",
 			fields: fields{version: "2"},
 			args: args{
-				ctx:            context.TODO(),
+				ctx:            context.Background(),
 				projectKeyOrId: "DUMMY",
 			},
 			on: func(fields *fields) {
@@ -80,7 +80,7 @@ func Test_internalProjectPropertyImpl_Gets(t *testing.T) {
 
 				client.On("Call",
 					&http.Request{},
-					&model.ProjectPropertyPageScheme{}).
+					&model.PropertyPageScheme{}).
 					Return(&model.ResponseScheme{}, nil)
 
 				fields.c = client
@@ -103,7 +103,7 @@ func Test_internalProjectPropertyImpl_Gets(t *testing.T) {
 			name:   "when the http request cannot be created",
 			fields: fields{version: "3"},
 			args: args{
-				ctx:            context.TODO(),
+				ctx:            context.Background(),
 				projectKeyOrId: "DUMMY",
 			},
 			on: func(fields *fields) {
@@ -180,7 +180,7 @@ func Test_internalProjectPropertyImpl_Get(t *testing.T) {
 			name:   "when the api version is v3",
 			fields: fields{version: "3"},
 			args: args{
-				ctx:            context.TODO(),
+				ctx:            context.Background(),
 				projectKeyOrId: "DUMMY",
 				propertyKey:    "alliance",
 			},
@@ -210,7 +210,7 @@ func Test_internalProjectPropertyImpl_Get(t *testing.T) {
 			name:   "when the api version is v2",
 			fields: fields{version: "2"},
 			args: args{
-				ctx:            context.TODO(),
+				ctx:            context.Background(),
 				projectKeyOrId: "DUMMY",
 				propertyKey:    "alliance",
 			},
@@ -240,7 +240,7 @@ func Test_internalProjectPropertyImpl_Get(t *testing.T) {
 			name:   "when the project key or id is not provided",
 			fields: fields{version: "3"},
 			args: args{
-				ctx: context.TODO(),
+				ctx: context.Background(),
 			},
 			wantErr: true,
 			Err:     model.ErrNoProjectIDOrKeyError,
@@ -250,7 +250,7 @@ func Test_internalProjectPropertyImpl_Get(t *testing.T) {
 			name:   "when the property key is not provided",
 			fields: fields{version: "3"},
 			args: args{
-				ctx:            context.TODO(),
+				ctx:            context.Background(),
 				projectKeyOrId: "DUMMY",
 			},
 			wantErr: true,
@@ -261,7 +261,7 @@ func Test_internalProjectPropertyImpl_Get(t *testing.T) {
 			name:   "when the http request cannot be created",
 			fields: fields{version: "3"},
 			args: args{
-				ctx:            context.TODO(),
+				ctx:            context.Background(),
 				projectKeyOrId: "DUMMY",
 				propertyKey:    "alliance",
 			},
@@ -339,7 +339,7 @@ func Test_internalProjectPropertyImpl_Delete(t *testing.T) {
 			name:   "when the api version is v3",
 			fields: fields{version: "3"},
 			args: args{
-				ctx:            context.TODO(),
+				ctx:            context.Background(),
 				projectKeyOrId: "DUMMY",
 				propertyKey:    "alliance",
 			},
@@ -369,7 +369,7 @@ func Test_internalProjectPropertyImpl_Delete(t *testing.T) {
 			name:   "when the api version is v2",
 			fields: fields{version: "2"},
 			args: args{
-				ctx:            context.TODO(),
+				ctx:            context.Background(),
 				projectKeyOrId: "DUMMY",
 				propertyKey:    "alliance",
 			},
@@ -399,7 +399,7 @@ func Test_internalProjectPropertyImpl_Delete(t *testing.T) {
 			name:   "when the project key or id is not provided",
 			fields: fields{version: "3"},
 			args: args{
-				ctx: context.TODO(),
+				ctx: context.Background(),
 			},
 			wantErr: true,
 			Err:     model.ErrNoProjectIDOrKeyError,
@@ -409,7 +409,7 @@ func Test_internalProjectPropertyImpl_Delete(t *testing.T) {
 			name:   "when the property key is not provided",
 			fields: fields{version: "3"},
 			args: args{
-				ctx:            context.TODO(),
+				ctx:            context.Background(),
 				projectKeyOrId: "DUMMY",
 			},
 			wantErr: true,
@@ -420,7 +420,7 @@ func Test_internalProjectPropertyImpl_Delete(t *testing.T) {
 			name:   "when the http request cannot be created",
 			fields: fields{version: "3"},
 			args: args{
-				ctx:            context.TODO(),
+				ctx:            context.Background(),
 				projectKeyOrId: "DUMMY",
 				propertyKey:    "alliance",
 			},
@@ -503,7 +503,7 @@ func Test_internalProjectPropertyImpl_Set(t *testing.T) {
 			name:   "when the api version is v3",
 			fields: fields{version: "3"},
 			args: args{
-				ctx:            context.TODO(),
+				ctx:            context.Background(),
 				projectKeyOrId: "DUMMY",
 				propertyKey:    "alliance",
 				payload:        payloadMocked,
@@ -534,7 +534,7 @@ func Test_internalProjectPropertyImpl_Set(t *testing.T) {
 			name:   "when the api version is v2",
 			fields: fields{version: "2"},
 			args: args{
-				ctx:            context.TODO(),
+				ctx:            context.Background(),
 				projectKeyOrId: "DUMMY",
 				propertyKey:    "alliance",
 				payload:        payloadMocked,
@@ -565,7 +565,7 @@ func Test_internalProjectPropertyImpl_Set(t *testing.T) {
 			name:   "when the project key or id is not provided",
 			fields: fields{version: "3"},
 			args: args{
-				ctx: context.TODO(),
+				ctx: context.Background(),
 			},
 			wantErr: true,
 			Err:     model.ErrNoProjectIDOrKeyError,
@@ -575,7 +575,7 @@ func Test_internalProjectPropertyImpl_Set(t *testing.T) {
 			name:   "when the property key is not provided",
 			fields: fields{version: "3"},
 			args: args{
-				ctx:            context.TODO(),
+				ctx:            context.Background(),
 				projectKeyOrId: "DUMMY",
 			},
 			wantErr: true,
@@ -586,7 +586,7 @@ func Test_internalProjectPropertyImpl_Set(t *testing.T) {
 			name:   "when the http request cannot be created",
 			fields: fields{version: "3"},
 			args: args{
-				ctx:            context.TODO(),
+				ctx:            context.Background(),
 				projectKeyOrId: "DUMMY",
 				propertyKey:    "alliance",
 				payload:        payloadMocked,